Skip to content

Commit 6d86dc2

Browse files
committed
Decode with context
1 parent f34a7ad commit 6d86dc2

22 files changed

+419
-170
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ chrono = { version = "0.4", features = ["serde"] }
4747
glam = { version = "0.25", features = ["serde"] }
4848
bincode_1 = { version = "1.3", package = "bincode" }
4949
serde = { version = "1.0", features = ["derive"] }
50+
bumpalo = { version = "3.16.0", features = ["collections"] }
5051

5152
[[bench]]
5253
name = "varint"

compatibility/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod sway;
1111
pub fn test_same_with_config<T, C, O>(t: &T, bincode_1_options: O, bincode_2_config: C)
1212
where
1313
T: bincode_2::Encode
14-
+ bincode_2::Decode
14+
+ bincode_2::Decode<()>
1515
+ serde::Serialize
1616
+ serde::de::DeserializeOwned
1717
+ core::fmt::Debug
@@ -60,7 +60,7 @@ where
6060
pub fn test_same<T>(t: T)
6161
where
6262
T: bincode_2::Encode
63-
+ bincode_2::Decode
63+
+ bincode_2::Decode<()>
6464
+ serde::Serialize
6565
+ serde::de::DeserializeOwned
6666
+ core::fmt::Debug

compatibility/src/sway.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub enum FTXresponse<T> {
3232
Error(FTXresponseFailure),
3333
}
3434

35+
3536
#[derive(
3637
bincode_2::Encode, bincode_2::Decode, serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq,
3738
)]

derive/src/attribute.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
use proc_macro::Literal;
12
use virtue::prelude::*;
23
use virtue::utils::{parse_tagged_attribute, ParsedAttribute};
34

45
pub struct ContainerAttributes {
56
pub crate_name: String,
67
pub bounds: Option<(String, Literal)>,
78
pub decode_bounds: Option<(String, Literal)>,
9+
pub decode_context: Option<(String, Literal)>,
810
pub borrow_decode_bounds: Option<(String, Literal)>,
911
pub encode_bounds: Option<(String, Literal)>,
1012
}
@@ -15,6 +17,7 @@ impl Default for ContainerAttributes {
1517
crate_name: "::bincode".to_string(),
1618
bounds: None,
1719
decode_bounds: None,
20+
decode_context: None,
1821
encode_bounds: None,
1922
borrow_decode_bounds: None,
2023
}
@@ -56,6 +59,15 @@ impl FromAttribute for ContainerAttributes {
5659
return Err(Error::custom_at("Should be a literal str", val.span()));
5760
}
5861
}
62+
ParsedAttribute::Property(key, val) if key.to_string() == "decode_context" => {
63+
let val_string = val.to_string();
64+
if val_string.starts_with('"') && val_string.ends_with('"') {
65+
result.decode_context =
66+
Some((val_string[1..val_string.len() - 1].to_string(), val));
67+
} else {
68+
return Err(Error::custom_at("Should be a literal str", val.span()));
69+
}
70+
}
5971
ParsedAttribute::Property(key, val) if key.to_string() == "encode_bounds" => {
6072
let val_string = val.to_string();
6173
if val_string.starts_with('"') && val_string.ends_with('"') {

derive/src/derive_enum.rs

+38-13
Original file line numberDiff line numberDiff line change
@@ -219,25 +219,37 @@ impl DeriveEnum {
219219
pub fn generate_decode(self, generator: &mut Generator) -> Result<()> {
220220
let crate_name = self.attributes.crate_name.as_str();
221221

222+
let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
223+
decode_context.as_str()
224+
} else {
225+
"__Ctx"
226+
};
222227
// Remember to keep this mostly in sync with generate_borrow_decode
223228

224229
let enum_name = generator.target_name().to_string();
225230

226-
generator
227-
.impl_for(format!("{}::Decode", crate_name))
231+
let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name));
232+
233+
234+
if self.attributes.decode_context.is_none() {
235+
impl_for = impl_for.with_impl_generics(["__Ctx"]);
236+
}
237+
238+
impl_for
239+
.with_trait_generics([decode_context])
228240
.modify_generic_constraints(|generics, where_constraints| {
229241
if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
230242
where_constraints.clear();
231243
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
232244
} else {
233245
for g in generics.iter_generics() {
234-
where_constraints.push_constraint(g, format!("{}::Decode", crate_name))?;
246+
where_constraints.push_constraint(g, format!("{}::Decode<__Ctx>", crate_name))?;
235247
}
236248
}
237249
Ok(())
238250
})?
239251
.generate_fn("decode")
240-
.with_generic_deps("__D", [format!("{}::de::Decoder", crate_name)])
252+
.with_generic_deps("__D", [format!("{}::de::Decoder<Ctx = {}>", crate_name, decode_context)])
241253
.with_arg("decoder", "&mut __D")
242254
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
243255
.body(|fn_builder| {
@@ -249,7 +261,7 @@ impl DeriveEnum {
249261
} else {
250262
fn_builder
251263
.push_parsed(format!(
252-
"let variant_index = <u32 as {}::Decode>::decode(decoder)?;",
264+
"let variant_index = <u32 as {}::Decode::<__D::Ctx>>::decode(decoder)?;",
253265
crate_name
254266
))?;
255267
fn_builder.push_parsed("match variant_index")?;
@@ -286,13 +298,13 @@ impl DeriveEnum {
286298
if attributes.with_serde {
287299
variant_body
288300
.push_parsed(format!(
289-
"<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?.0,",
301+
"<{0}::serde::Compat<_> as {0}::Decode::<__D::Ctx>>::decode(decoder)?.0,",
290302
crate_name
291303
))?;
292304
} else {
293305
variant_body
294306
.push_parsed(format!(
295-
"{}::Decode::decode(decoder)?,",
307+
"{}::Decode::<__D::Ctx>::decode(decoder)?,",
296308
crate_name
297309
))?;
298310
}
@@ -318,17 +330,30 @@ impl DeriveEnum {
318330
pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> {
319331
let crate_name = &self.attributes.crate_name;
320332

333+
let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
334+
decode_context.as_str()
335+
} else {
336+
"__Ctx"
337+
};
338+
321339
// Remember to keep this mostly in sync with generate_decode
322340
let enum_name = generator.target_name().to_string();
323341

324-
generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
342+
let mut impl_for = generator
343+
.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
344+
.with_trait_generics([decode_context]);
345+
if self.attributes.decode_context.is_none() {
346+
impl_for = impl_for.with_impl_generics(["__Ctx"]);
347+
}
348+
349+
impl_for
325350
.modify_generic_constraints(|generics, where_constraints| {
326351
if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
327352
where_constraints.clear();
328353
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
329354
} else {
330355
for g in generics.iter_generics() {
331-
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap();
356+
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap();
332357
}
333358
for lt in generics.iter_lifetimes() {
334359
where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?;
@@ -337,7 +362,7 @@ impl DeriveEnum {
337362
Ok(())
338363
})?
339364
.generate_fn("borrow_decode")
340-
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
365+
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Ctx = {}>", crate_name, decode_context)])
341366
.with_arg("decoder", "&mut __D")
342367
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
343368
.body(|fn_builder| {
@@ -348,7 +373,7 @@ impl DeriveEnum {
348373
))?;
349374
} else {
350375
fn_builder
351-
.push_parsed(format!("let variant_index = <u32 as {}::Decode>::decode(decoder)?;", crate_name))?;
376+
.push_parsed(format!("let variant_index = <u32 as {}::Decode::<__D::Ctx>>::decode(decoder)?;", crate_name))?;
352377
fn_builder.push_parsed("match variant_index")?;
353378
fn_builder.group(Delimiter::Brace, |variant_case| {
354379
for (mut variant_index, variant) in self.iter_fields() {
@@ -382,9 +407,9 @@ impl DeriveEnum {
382407
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
383408
if attributes.with_serde {
384409
variant_body
385-
.push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?.0,", crate_name))?;
410+
.push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<__D::Ctx>>::borrow_decode(decoder)?.0,", crate_name))?;
386411
} else {
387-
variant_body.push_parsed(format!("{}::BorrowDecode::borrow_decode(decoder)?,", crate_name))?;
412+
variant_body.push_parsed(format!("{}::BorrowDecode::<__D::Ctx>::borrow_decode(decoder)?,", crate_name))?;
388413
}
389414
}
390415
}

derive/src/derive_struct.rs

+39-16
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,32 @@ impl DeriveStruct {
6767
pub fn generate_decode(self, generator: &mut Generator) -> Result<()> {
6868
// Remember to keep this mostly in sync with generate_borrow_decode
6969
let crate_name = &self.attributes.crate_name;
70+
let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
71+
decode_context.as_str()
72+
} else {
73+
"__Ctx"
74+
};
7075

71-
generator
72-
.impl_for(format!("{}::Decode", crate_name))
73-
.with_impl_generics(["__Ctx"])
74-
.with_trait_generics(["__Ctx"])
76+
let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name));
77+
if self.attributes.decode_context.is_none() {
78+
impl_for = impl_for.with_impl_generics(["__Ctx"]);
79+
}
80+
81+
impl_for
82+
.with_trait_generics([decode_context])
7583
.modify_generic_constraints(|generics, where_constraints| {
7684
if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
7785
where_constraints.clear();
7886
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
7987
} else {
8088
for g in generics.iter_generics() {
81-
where_constraints.push_constraint(g, format!("{}::Decode<__Ctx>", crate_name)).unwrap();
89+
where_constraints.push_constraint(g, format!("{}::Decode<{}>", crate_name, decode_context)).unwrap();
8290
}
8391
}
8492
Ok(())
8593
})?
8694
.generate_fn("decode")
87-
.with_generic_deps("__D", [format!("{}::de::Decoder<Ctx = __Ctx>", crate_name)])
95+
.with_generic_deps("__D", [format!("{}::de::Decoder<Ctx = {}>", crate_name, decode_context)])
8896
.with_arg("decoder", "&mut __D")
8997
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
9098
.body(|fn_body| {
@@ -105,9 +113,10 @@ impl DeriveStruct {
105113
if attributes.with_serde {
106114
struct_body
107115
.push_parsed(format!(
108-
"{1}: (<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?).0,",
116+
"{1}: (<{0}::serde::Compat<_> as {0}::Decode::<{2}>>::decode(decoder)?).0,",
109117
crate_name,
110-
field
118+
field,
119+
decode_context,
111120
))?;
112121
} else {
113122
struct_body
@@ -133,15 +142,27 @@ impl DeriveStruct {
133142
// Remember to keep this mostly in sync with generate_decode
134143
let crate_name = self.attributes.crate_name;
135144

136-
generator
137-
.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
145+
let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
146+
decode_context.as_str()
147+
} else {
148+
"__Ctx"
149+
};
150+
151+
let mut impl_for =
152+
generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]).with_trait_generics([decode_context]);
153+
if self.attributes.decode_context.is_none() {
154+
impl_for = impl_for.with_impl_generics(["__Ctx"]);
155+
}
156+
157+
impl_for
158+
138159
.modify_generic_constraints(|generics, where_constraints| {
139160
if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
140161
where_constraints.clear();
141162
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
142163
} else {
143164
for g in generics.iter_generics() {
144-
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap();
165+
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap();
145166
}
146167
for lt in generics.iter_lifetimes() {
147168
where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?;
@@ -150,7 +171,7 @@ impl DeriveStruct {
150171
Ok(())
151172
})?
152173
.generate_fn("borrow_decode")
153-
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
174+
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Ctx = {}>", crate_name, decode_context)])
154175
.with_arg("decoder", "&mut __D")
155176
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
156177
.body(|fn_body| {
@@ -165,16 +186,18 @@ impl DeriveStruct {
165186
if attributes.with_serde {
166187
struct_body
167188
.push_parsed(format!(
168-
"{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?).0,",
189+
"{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<'_, {2}>>::borrow_decode(decoder)?).0,",
169190
crate_name,
170-
field
191+
field,
192+
decode_context,
171193
))?;
172194
} else {
173195
struct_body
174196
.push_parsed(format!(
175-
"{1}: {0}::BorrowDecode::borrow_decode(decoder)?,",
197+
"{1}: {0}::BorrowDecode::<'_, {2}>::borrow_decode(decoder)?,",
176198
crate_name,
177-
field
199+
field,
200+
decode_context,
178201
))?;
179202
}
180203
}

src/de/decoder.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{config::Config, error::DecodeError, utils::Sealed};
1616
/// # let slice: &[u8] = &[0, 0, 0, 0];
1717
/// # let some_reader = bincode::de::read::SliceReader::new(slice);
1818
/// use bincode::de::{DecoderImpl, Decode};
19-
/// let mut decoder = DecoderImpl::new(some_reader, bincode::config::standard());
19+
/// let mut decoder = DecoderImpl::new(some_reader, bincode::config::standard(), ());
2020
/// // this u32 can be any Decode
2121
/// let value = u32::decode(&mut decoder).unwrap();
2222
/// ```
@@ -90,4 +90,8 @@ impl<R: Reader, C: Config, Ctx> Decoder for DecoderImpl<R, C, Ctx> {
9090
self.bytes_read -= n;
9191
}
9292
}
93+
94+
fn ctx(&mut self) -> &mut Self::Ctx {
95+
&mut self.ctx
96+
}
9397
}

src/de/impl_tuples.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use crate::error::DecodeError;
44
macro_rules! impl_tuple {
55
() => {};
66
($first:ident $(, $extra:ident)*) => {
7-
impl<'de, $first $(, $extra)*> BorrowDecode<'de> for ($first, $($extra, )*)
7+
impl<'de, $first $(, $extra)*, Ctx> BorrowDecode<'de, Ctx> for ($first, $($extra, )*)
88
where
9-
$first: BorrowDecode<'de>,
9+
$first: BorrowDecode<'de, Ctx>,
1010
$(
11-
$extra : BorrowDecode<'de>,
11+
$extra : BorrowDecode<'de, Ctx>,
1212
)*
1313
{
14-
fn borrow_decode<BD: BorrowDecoder<'de>>(decoder: &mut BD) -> Result<Self, DecodeError> {
14+
fn borrow_decode<BD: BorrowDecoder<'de, Ctx = Ctx>>(decoder: &mut BD) -> Result<Self, DecodeError> {
1515
Ok((
1616
$first::borrow_decode(decoder)?,
1717
$($extra :: borrow_decode(decoder)?, )*
@@ -26,7 +26,7 @@ macro_rules! impl_tuple {
2626
$extra : Decode<Ctx>,
2727
)*
2828
{
29-
fn decode<DE: Decoder<Ctx=Ctx>>(decoder: &mut DE) -> Result<Self, DecodeError> {
29+
fn decode<DE: Decoder<Ctx = Ctx>>(decoder: &mut DE) -> Result<Self, DecodeError> {
3030
Ok((
3131
$first::decode(decoder)?,
3232
$($extra :: decode(decoder)?, )*

0 commit comments

Comments
 (0)