diff --git a/Cargo.toml b/Cargo.toml index e0f48513..ab1fe808 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ unty = "0.0.3" # Used for tests [dev-dependencies] +ouroboros = "0.18.3" serde_derive = "1.0" serde_json = { version = "1.0", default-features = false } tempfile = "3.2" @@ -47,6 +48,7 @@ chrono = { version = "0.4", features = ["serde"] } glam = { version = "0.25", features = ["serde"] } bincode_1 = { version = "1.3", package = "bincode" } serde = { version = "1.0", features = ["derive"] } +bumpalo = { version = "3.16.0", features = ["collections"] } [[bench]] name = "varint" diff --git a/compatibility/src/lib.rs b/compatibility/src/lib.rs index 05d4dbe2..93385fef 100644 --- a/compatibility/src/lib.rs +++ b/compatibility/src/lib.rs @@ -11,7 +11,7 @@ mod sway; pub fn test_same_with_config(t: &T, bincode_1_options: O, bincode_2_config: C) where T: bincode_2::Encode - + bincode_2::Decode + + bincode_2::Decode<()> + serde::Serialize + serde::de::DeserializeOwned + core::fmt::Debug @@ -60,7 +60,7 @@ where pub fn test_same(t: T) where T: bincode_2::Encode - + bincode_2::Decode + + bincode_2::Decode<()> + serde::Serialize + serde::de::DeserializeOwned + core::fmt::Debug diff --git a/compatibility/src/sway.rs b/compatibility/src/sway.rs index 84167d45..c456a50b 100644 --- a/compatibility/src/sway.rs +++ b/compatibility/src/sway.rs @@ -32,6 +32,7 @@ pub enum FTXresponse { Error(FTXresponseFailure), } + #[derive( bincode_2::Encode, bincode_2::Decode, serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, )] diff --git a/derive/src/attribute.rs b/derive/src/attribute.rs index 30f817b9..d6e80422 100644 --- a/derive/src/attribute.rs +++ b/derive/src/attribute.rs @@ -5,6 +5,7 @@ pub struct ContainerAttributes { pub crate_name: String, pub bounds: Option<(String, Literal)>, pub decode_bounds: Option<(String, Literal)>, + pub decode_context: Option<(String, Literal)>, pub borrow_decode_bounds: Option<(String, Literal)>, pub encode_bounds: Option<(String, Literal)>, } @@ -15,6 +16,7 @@ impl Default for ContainerAttributes { crate_name: "::bincode".to_string(), bounds: None, decode_bounds: None, + decode_context: None, encode_bounds: None, borrow_decode_bounds: None, } @@ -56,6 +58,15 @@ impl FromAttribute for ContainerAttributes { return Err(Error::custom_at("Should be a literal str", val.span())); } } + ParsedAttribute::Property(key, val) if key.to_string() == "decode_context" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.decode_context = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } ParsedAttribute::Property(key, val) if key.to_string() == "encode_bounds" => { let val_string = val.to_string(); if val_string.starts_with('"') && val_string.ends_with('"') { diff --git a/derive/src/derive_enum.rs b/derive/src/derive_enum.rs index e00f1daa..36a95858 100644 --- a/derive/src/derive_enum.rs +++ b/derive/src/derive_enum.rs @@ -219,25 +219,36 @@ impl DeriveEnum { pub fn generate_decode(self, generator: &mut Generator) -> Result<()> { let crate_name = self.attributes.crate_name.as_str(); + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; // Remember to keep this mostly in sync with generate_borrow_decode let enum_name = generator.target_name().to_string(); - generator - .impl_for(format!("{}::Decode", crate_name)) + let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name)); + + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .with_trait_generics([decode_context]) .modify_generic_constraints(|generics, where_constraints| { if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { where_constraints.clear(); where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; } else { for g in generics.iter_generics() { - where_constraints.push_constraint(g, format!("{}::Decode", crate_name))?; + where_constraints.push_constraint(g, format!("{}::Decode<__Context>", crate_name))?; } } Ok(()) })? .generate_fn("decode") - .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name)]) + .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name, decode_context)]) .with_arg("decoder", "&mut __D") .with_return_type(format!("core::result::Result", crate_name)) .body(|fn_builder| { @@ -249,7 +260,7 @@ impl DeriveEnum { } else { fn_builder .push_parsed(format!( - "let variant_index = ::decode(decoder)?;", + "let variant_index = >::decode(decoder)?;", crate_name ))?; fn_builder.push_parsed("match variant_index")?; @@ -286,13 +297,13 @@ impl DeriveEnum { if attributes.with_serde { variant_body .push_parsed(format!( - "<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?.0,", + "<{0}::serde::Compat<_> as {0}::Decode::<__D::Context>>::decode(decoder)?.0,", crate_name ))?; } else { variant_body .push_parsed(format!( - "{}::Decode::decode(decoder)?,", + "{}::Decode::<__D::Context>::decode(decoder)?,", crate_name ))?; } @@ -318,17 +329,30 @@ impl DeriveEnum { pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> { let crate_name = &self.attributes.crate_name; + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + // Remember to keep this mostly in sync with generate_decode let enum_name = generator.target_name().to_string(); - generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]) + let mut impl_for = generator + .impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]) + .with_trait_generics([decode_context]); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for .modify_generic_constraints(|generics, where_constraints| { if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { where_constraints.clear(); where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; } else { for g in generics.iter_generics() { - where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap(); + where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap(); } for lt in generics.iter_lifetimes() { where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?; @@ -337,7 +361,7 @@ impl DeriveEnum { Ok(()) })? .generate_fn("borrow_decode") - .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)]) + .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)]) .with_arg("decoder", "&mut __D") .with_return_type(format!("core::result::Result", crate_name)) .body(|fn_builder| { @@ -348,7 +372,7 @@ impl DeriveEnum { ))?; } else { fn_builder - .push_parsed(format!("let variant_index = ::decode(decoder)?;", crate_name))?; + .push_parsed(format!("let variant_index = >::decode(decoder)?;", crate_name))?; fn_builder.push_parsed("match variant_index")?; fn_builder.group(Delimiter::Brace, |variant_case| { for (mut variant_index, variant) in self.iter_fields() { @@ -382,9 +406,9 @@ impl DeriveEnum { let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); if attributes.with_serde { variant_body - .push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?.0,", crate_name))?; + .push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<__D::Context>>::borrow_decode(decoder)?.0,", crate_name))?; } else { - variant_body.push_parsed(format!("{}::BorrowDecode::borrow_decode(decoder)?,", crate_name))?; + variant_body.push_parsed(format!("{}::BorrowDecode::<__D::Context>::borrow_decode(decoder)?,", crate_name))?; } } } diff --git a/derive/src/derive_struct.rs b/derive/src/derive_struct.rs index f6dba0b1..52002efc 100644 --- a/derive/src/derive_struct.rs +++ b/derive/src/derive_struct.rs @@ -1,6 +1,4 @@ use crate::attribute::{ContainerAttributes, FieldAttributes}; -use virtue::generate::Generator; -use virtue::parse::Fields; use virtue::prelude::*; pub(crate) struct DeriveStruct { @@ -67,22 +65,32 @@ impl DeriveStruct { pub fn generate_decode(self, generator: &mut Generator) -> Result<()> { // Remember to keep this mostly in sync with generate_borrow_decode let crate_name = &self.attributes.crate_name; + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; - generator - .impl_for(format!("{}::Decode", crate_name)) + let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name)); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .with_trait_generics([decode_context]) .modify_generic_constraints(|generics, where_constraints| { if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { where_constraints.clear(); where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; } else { for g in generics.iter_generics() { - where_constraints.push_constraint(g, format!("{}::Decode", crate_name)).unwrap(); + where_constraints.push_constraint(g, format!("{}::Decode<{}>", crate_name, decode_context)).unwrap(); } } Ok(()) })? .generate_fn("decode") - .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name)]) + .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name, decode_context)]) .with_arg("decoder", "&mut __D") .with_return_type(format!("core::result::Result", crate_name)) .body(|fn_body| { @@ -103,9 +111,10 @@ impl DeriveStruct { if attributes.with_serde { struct_body .push_parsed(format!( - "{1}: (<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?).0,", + "{1}: (<{0}::serde::Compat<_> as {0}::Decode::<{2}>>::decode(decoder)?).0,", crate_name, - field + field, + decode_context, ))?; } else { struct_body @@ -131,15 +140,27 @@ impl DeriveStruct { // Remember to keep this mostly in sync with generate_decode let crate_name = self.attributes.crate_name; - generator - .impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]) + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + + let mut impl_for = + generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]).with_trait_generics([decode_context]); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .modify_generic_constraints(|generics, where_constraints| { if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { where_constraints.clear(); where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; } else { for g in generics.iter_generics() { - where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap(); + where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap(); } for lt in generics.iter_lifetimes() { where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?; @@ -148,7 +169,7 @@ impl DeriveStruct { Ok(()) })? .generate_fn("borrow_decode") - .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)]) + .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)]) .with_arg("decoder", "&mut __D") .with_return_type(format!("core::result::Result", crate_name)) .body(|fn_body| { @@ -163,16 +184,18 @@ impl DeriveStruct { if attributes.with_serde { struct_body .push_parsed(format!( - "{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?).0,", + "{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<'_, {2}>>::borrow_decode(decoder)?).0,", crate_name, - field + field, + decode_context, ))?; } else { struct_body .push_parsed(format!( - "{1}: {0}::BorrowDecode::borrow_decode(decoder)?,", + "{1}: {0}::BorrowDecode::<'_, {2}>::borrow_decode(decoder)?,", crate_name, - field + field, + decode_context, ))?; } } diff --git a/src/atomic.rs b/src/atomic.rs index 1b702520..003621fe 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -27,7 +27,7 @@ impl Encode for AtomicBool { } #[cfg(target_has_atomic = "8")] -impl Decode for AtomicBool { +impl Decode for AtomicBool { fn decode(decoder: &mut D) -> Result { Ok(AtomicBool::new(Decode::decode(decoder)?)) } @@ -46,7 +46,7 @@ impl Encode for AtomicU8 { } #[cfg(target_has_atomic = "8")] -impl Decode for AtomicU8 { +impl Decode for AtomicU8 { fn decode(decoder: &mut D) -> Result { Ok(AtomicU8::new(Decode::decode(decoder)?)) } @@ -65,7 +65,7 @@ impl Encode for AtomicU16 { } #[cfg(target_has_atomic = "16")] -impl Decode for AtomicU16 { +impl Decode for AtomicU16 { fn decode(decoder: &mut D) -> Result { Ok(AtomicU16::new(Decode::decode(decoder)?)) } @@ -84,7 +84,7 @@ impl Encode for AtomicU32 { } #[cfg(target_has_atomic = "32")] -impl Decode for AtomicU32 { +impl Decode for AtomicU32 { fn decode(decoder: &mut D) -> Result { Ok(AtomicU32::new(Decode::decode(decoder)?)) } @@ -103,7 +103,7 @@ impl Encode for AtomicU64 { } #[cfg(target_has_atomic = "64")] -impl Decode for AtomicU64 { +impl Decode for AtomicU64 { fn decode(decoder: &mut D) -> Result { Ok(AtomicU64::new(Decode::decode(decoder)?)) } @@ -122,7 +122,7 @@ impl Encode for AtomicUsize { } #[cfg(target_has_atomic = "ptr")] -impl Decode for AtomicUsize { +impl Decode for AtomicUsize { fn decode(decoder: &mut D) -> Result { Ok(AtomicUsize::new(Decode::decode(decoder)?)) } @@ -141,7 +141,7 @@ impl Encode for AtomicI8 { } #[cfg(target_has_atomic = "8")] -impl Decode for AtomicI8 { +impl Decode for AtomicI8 { fn decode(decoder: &mut D) -> Result { Ok(AtomicI8::new(Decode::decode(decoder)?)) } @@ -160,7 +160,7 @@ impl Encode for AtomicI16 { } #[cfg(target_has_atomic = "16")] -impl Decode for AtomicI16 { +impl Decode for AtomicI16 { fn decode(decoder: &mut D) -> Result { Ok(AtomicI16::new(Decode::decode(decoder)?)) } @@ -179,7 +179,7 @@ impl Encode for AtomicI32 { } #[cfg(target_has_atomic = "32")] -impl Decode for AtomicI32 { +impl Decode for AtomicI32 { fn decode(decoder: &mut D) -> Result { Ok(AtomicI32::new(Decode::decode(decoder)?)) } @@ -198,7 +198,7 @@ impl Encode for AtomicI64 { } #[cfg(target_has_atomic = "64")] -impl Decode for AtomicI64 { +impl Decode for AtomicI64 { fn decode(decoder: &mut D) -> Result { Ok(AtomicI64::new(Decode::decode(decoder)?)) } @@ -217,7 +217,7 @@ impl Encode for AtomicIsize { } #[cfg(target_has_atomic = "ptr")] -impl Decode for AtomicIsize { +impl Decode for AtomicIsize { fn decode(decoder: &mut D) -> Result { Ok(AtomicIsize::new(Decode::decode(decoder)?)) } diff --git a/src/de/decoder.rs b/src/de/decoder.rs index b538b07b..80da88dc 100644 --- a/src/de/decoder.rs +++ b/src/de/decoder.rs @@ -16,30 +16,34 @@ use crate::{config::Config, error::DecodeError, utils::Sealed}; /// # let slice: &[u8] = &[0, 0, 0, 0]; /// # let some_reader = bincode::de::read::SliceReader::new(slice); /// use bincode::de::{DecoderImpl, Decode}; -/// let mut decoder = DecoderImpl::new(some_reader, bincode::config::standard()); +/// let mut decoder = DecoderImpl::new(some_reader, bincode::config::standard(), ()); /// // this u32 can be any Decode /// let value = u32::decode(&mut decoder).unwrap(); /// ``` -pub struct DecoderImpl { +pub struct DecoderImpl<'context, R, C: Config, Context> { reader: R, config: C, bytes_read: usize, + context: &'context mut Context, } -impl DecoderImpl { +impl<'context, R: Reader, C: Config, Context> DecoderImpl<'context, R, C, Context> { /// Construct a new Decoder - pub const fn new(reader: R, config: C) -> DecoderImpl { + pub fn new(reader: R, config: C, context: &'context mut Context) -> DecoderImpl<'context, R, C, Context> { DecoderImpl { reader, config, bytes_read: 0, + context, } } } -impl Sealed for DecoderImpl {} +impl<'context, R, C: Config, Context> Sealed for DecoderImpl<'context, R, C, Context> {} -impl<'de, R: BorrowReader<'de>, C: Config> BorrowDecoder<'de> for DecoderImpl { +impl<'context, 'de, R: BorrowReader<'de>, C: Config, Context> BorrowDecoder<'de> + for DecoderImpl<'context, R, C, Context> +{ type BR = R; fn borrow_reader(&mut self) -> &mut Self::BR { @@ -47,10 +51,11 @@ impl<'de, R: BorrowReader<'de>, C: Config> BorrowDecoder<'de> for DecoderImpl Decoder for DecoderImpl { +impl<'context, R: Reader, C: Config, Context> Decoder for DecoderImpl<'context, R, C, Context> { type R = R; type C = C; + type Context = Context; fn reader(&mut self) -> &mut Self::R { &mut self.reader @@ -87,4 +92,50 @@ impl Decoder for DecoderImpl { self.bytes_read -= n; } } + + fn context(&mut self) -> &mut Self::Context { + self.context + } +} + +pub struct WithContext<'a, D: ?Sized, C> { + pub(crate) decoder: &'a mut D, + pub(crate) context: &'a mut C, +} + +impl<'a, C, D: Decoder + ?Sized> Sealed for WithContext<'a, D, C> {} + +impl<'a, Context, D: Decoder + ?Sized> Decoder for WithContext<'a, D, Context> { + type R = D::R; + + type C = D::C; + + type Context = Context; + + fn context(&mut self) -> &mut Self::Context { + &mut self.context + } + + fn reader(&mut self) -> &mut Self::R { + self.decoder.reader() + } + + fn config(&self) -> &Self::C { + self.decoder.config() + } + + fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError> { + self.decoder.claim_bytes_read(n) + } + + fn unclaim_bytes_read(&mut self, n: usize) { + self.decoder.unclaim_bytes_read(n) + } +} + +impl<'de, 'a, C, D: BorrowDecoder<'de>> BorrowDecoder<'de> for WithContext<'a, D, C> { + type BR = D::BR; + fn borrow_reader(&mut self) -> &mut Self::BR { + self.decoder.borrow_reader() + } } diff --git a/src/de/impl_tuples.rs b/src/de/impl_tuples.rs index 951444e0..f4c5dc97 100644 --- a/src/de/impl_tuples.rs +++ b/src/de/impl_tuples.rs @@ -4,14 +4,14 @@ use crate::error::DecodeError; macro_rules! impl_tuple { () => {}; ($first:ident $(, $extra:ident)*) => { - impl<'de, $first $(, $extra)*> BorrowDecode<'de> for ($first, $($extra, )*) + impl<'de, $first $(, $extra)*, Context> BorrowDecode<'de, Context> for ($first, $($extra, )*) where - $first: BorrowDecode<'de>, + $first: BorrowDecode<'de, Context>, $( - $extra : BorrowDecode<'de>, + $extra : BorrowDecode<'de, Context>, )* { - fn borrow_decode>(decoder: &mut BD) -> Result { + fn borrow_decode>(decoder: &mut BD) -> Result { Ok(( $first::borrow_decode(decoder)?, $($extra :: borrow_decode(decoder)?, )* @@ -19,14 +19,14 @@ macro_rules! impl_tuple { } } - impl<$first $(, $extra)*> Decode for ($first, $($extra, )*) + impl Decode for ($first, $($extra, )*) where - $first: Decode, + $first: Decode, $( - $extra : Decode, + $extra : Decode, )* { - fn decode(decoder: &mut DE) -> Result { + fn decode>(decoder: &mut DE) -> Result { Ok(( $first::decode(decoder)?, $($extra :: decode(decoder)?, )* diff --git a/src/de/impls.rs b/src/de/impls.rs index bf88847d..a9c4ab69 100644 --- a/src/de/impls.rs +++ b/src/de/impls.rs @@ -18,8 +18,8 @@ use core::{ time::Duration, }; -impl Decode for bool { - fn decode(decoder: &mut D) -> Result { +impl Decode for bool { + fn decode>(decoder: &mut D) -> Result { match u8::decode(decoder)? { 0 => Ok(false), 1 => Ok(true), @@ -29,9 +29,9 @@ impl Decode for bool { } impl_borrow_decode!(bool); -impl Decode for u8 { +impl Decode for u8 { #[inline] - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(1)?; if let Some(buf) = decoder.reader().peek_read(1) { let byte = buf[0]; @@ -46,8 +46,8 @@ impl Decode for u8 { } impl_borrow_decode!(u8); -impl Decode for NonZeroU8 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroU8 { + fn decode>(decoder: &mut D) -> Result { NonZeroU8::new(u8::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::U8, }) @@ -55,8 +55,8 @@ impl Decode for NonZeroU8 { } impl_borrow_decode!(NonZeroU8); -impl Decode for u16 { - fn decode(decoder: &mut D) -> Result { +impl Decode for u16 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(2)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -75,8 +75,8 @@ impl Decode for u16 { } impl_borrow_decode!(u16); -impl Decode for NonZeroU16 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroU16 { + fn decode>(decoder: &mut D) -> Result { NonZeroU16::new(u16::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::U16, }) @@ -84,8 +84,8 @@ impl Decode for NonZeroU16 { } impl_borrow_decode!(NonZeroU16); -impl Decode for u32 { - fn decode(decoder: &mut D) -> Result { +impl Decode for u32 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(4)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -104,8 +104,8 @@ impl Decode for u32 { } impl_borrow_decode!(u32); -impl Decode for NonZeroU32 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroU32 { + fn decode>(decoder: &mut D) -> Result { NonZeroU32::new(u32::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::U32, }) @@ -113,8 +113,8 @@ impl Decode for NonZeroU32 { } impl_borrow_decode!(NonZeroU32); -impl Decode for u64 { - fn decode(decoder: &mut D) -> Result { +impl Decode for u64 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(8)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -133,8 +133,8 @@ impl Decode for u64 { } impl_borrow_decode!(u64); -impl Decode for NonZeroU64 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroU64 { + fn decode>(decoder: &mut D) -> Result { NonZeroU64::new(u64::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::U64, }) @@ -142,8 +142,8 @@ impl Decode for NonZeroU64 { } impl_borrow_decode!(NonZeroU64); -impl Decode for u128 { - fn decode(decoder: &mut D) -> Result { +impl Decode for u128 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(16)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -162,8 +162,8 @@ impl Decode for u128 { } impl_borrow_decode!(u128); -impl Decode for NonZeroU128 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroU128 { + fn decode>(decoder: &mut D) -> Result { NonZeroU128::new(u128::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::U128, }) @@ -171,8 +171,8 @@ impl Decode for NonZeroU128 { } impl_borrow_decode!(NonZeroU128); -impl Decode for usize { - fn decode(decoder: &mut D) -> Result { +impl Decode for usize { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(8)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -196,8 +196,8 @@ impl Decode for usize { } impl_borrow_decode!(usize); -impl Decode for NonZeroUsize { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroUsize { + fn decode>(decoder: &mut D) -> Result { NonZeroUsize::new(usize::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::Usize, }) @@ -205,8 +205,8 @@ impl Decode for NonZeroUsize { } impl_borrow_decode!(NonZeroUsize); -impl Decode for i8 { - fn decode(decoder: &mut D) -> Result { +impl Decode for i8 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(1)?; let mut bytes = [0u8; 1]; decoder.reader().read(&mut bytes)?; @@ -215,8 +215,8 @@ impl Decode for i8 { } impl_borrow_decode!(i8); -impl Decode for NonZeroI8 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroI8 { + fn decode>(decoder: &mut D) -> Result { NonZeroI8::new(i8::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::I8, }) @@ -224,8 +224,8 @@ impl Decode for NonZeroI8 { } impl_borrow_decode!(NonZeroI8); -impl Decode for i16 { - fn decode(decoder: &mut D) -> Result { +impl Decode for i16 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(2)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -244,8 +244,8 @@ impl Decode for i16 { } impl_borrow_decode!(i16); -impl Decode for NonZeroI16 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroI16 { + fn decode>(decoder: &mut D) -> Result { NonZeroI16::new(i16::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::I16, }) @@ -253,8 +253,8 @@ impl Decode for NonZeroI16 { } impl_borrow_decode!(NonZeroI16); -impl Decode for i32 { - fn decode(decoder: &mut D) -> Result { +impl Decode for i32 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(4)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -273,8 +273,8 @@ impl Decode for i32 { } impl_borrow_decode!(i32); -impl Decode for NonZeroI32 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroI32 { + fn decode>(decoder: &mut D) -> Result { NonZeroI32::new(i32::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::I32, }) @@ -282,8 +282,8 @@ impl Decode for NonZeroI32 { } impl_borrow_decode!(NonZeroI32); -impl Decode for i64 { - fn decode(decoder: &mut D) -> Result { +impl Decode for i64 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(8)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -302,8 +302,8 @@ impl Decode for i64 { } impl_borrow_decode!(i64); -impl Decode for NonZeroI64 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroI64 { + fn decode>(decoder: &mut D) -> Result { NonZeroI64::new(i64::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::I64, }) @@ -311,8 +311,8 @@ impl Decode for NonZeroI64 { } impl_borrow_decode!(NonZeroI64); -impl Decode for i128 { - fn decode(decoder: &mut D) -> Result { +impl Decode for i128 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(16)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -331,8 +331,8 @@ impl Decode for i128 { } impl_borrow_decode!(i128); -impl Decode for NonZeroI128 { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroI128 { + fn decode>(decoder: &mut D) -> Result { NonZeroI128::new(i128::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::I128, }) @@ -340,8 +340,8 @@ impl Decode for NonZeroI128 { } impl_borrow_decode!(NonZeroI128); -impl Decode for isize { - fn decode(decoder: &mut D) -> Result { +impl Decode for isize { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(8)?; match D::C::INT_ENCODING { IntEncoding::Variable => { @@ -360,8 +360,8 @@ impl Decode for isize { } impl_borrow_decode!(isize); -impl Decode for NonZeroIsize { - fn decode(decoder: &mut D) -> Result { +impl Decode for NonZeroIsize { + fn decode>(decoder: &mut D) -> Result { NonZeroIsize::new(isize::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { non_zero_type: IntegerType::Isize, }) @@ -369,8 +369,8 @@ impl Decode for NonZeroIsize { } impl_borrow_decode!(NonZeroIsize); -impl Decode for f32 { - fn decode(decoder: &mut D) -> Result { +impl Decode for f32 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(4)?; let mut bytes = [0u8; 4]; decoder.reader().read(&mut bytes)?; @@ -382,8 +382,8 @@ impl Decode for f32 { } impl_borrow_decode!(f32); -impl Decode for f64 { - fn decode(decoder: &mut D) -> Result { +impl Decode for f64 { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(8)?; let mut bytes = [0u8; 8]; decoder.reader().read(&mut bytes)?; @@ -395,31 +395,35 @@ impl Decode for f64 { } impl_borrow_decode!(f64); -impl Decode for Wrapping { - fn decode(decoder: &mut D) -> Result { +impl> Decode for Wrapping { + fn decode>(decoder: &mut D) -> Result { Ok(Wrapping(T::decode(decoder)?)) } } -impl<'de, T: BorrowDecode<'de>> BorrowDecode<'de> for Wrapping { - fn borrow_decode>(decoder: &mut D) -> Result { +impl<'de, Context, T: BorrowDecode<'de, Context>> BorrowDecode<'de, Context> for Wrapping { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { Ok(Wrapping(T::borrow_decode(decoder)?)) } } -impl Decode for Reverse { - fn decode(decoder: &mut D) -> Result { +impl> Decode for Reverse { + fn decode>(decoder: &mut D) -> Result { Ok(Reverse(T::decode(decoder)?)) } } -impl<'de, T: BorrowDecode<'de>> BorrowDecode<'de> for Reverse { - fn borrow_decode>(decoder: &mut D) -> Result { +impl<'de, Context, T: BorrowDecode<'de, Context>> BorrowDecode<'de, Context> for Reverse { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { Ok(Reverse(T::borrow_decode(decoder)?)) } } -impl Decode for char { - fn decode(decoder: &mut D) -> Result { +impl Decode for char { + fn decode>(decoder: &mut D) -> Result { let mut array = [0u8; 4]; // Look at the first byte to see how many bytes must be read @@ -448,26 +452,30 @@ impl Decode for char { } impl_borrow_decode!(char); -impl<'a, 'de: 'a> BorrowDecode<'de> for &'a [u8] { - fn borrow_decode>(decoder: &mut D) -> Result { +impl<'a, 'de: 'a, Context> BorrowDecode<'de, Context> for &'a [u8] { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let len = super::decode_slice_len(decoder)?; decoder.claim_bytes_read(len)?; decoder.borrow_reader().take_bytes(len) } } -impl<'a, 'de: 'a> BorrowDecode<'de> for &'a str { - fn borrow_decode>(decoder: &mut D) -> Result { +impl<'a, 'de: 'a, Context> BorrowDecode<'de, Context> for &'a str { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let slice = <&[u8]>::borrow_decode(decoder)?; core::str::from_utf8(slice).map_err(|inner| DecodeError::Utf8 { inner }) } } -impl Decode for [T; N] +impl Decode for [T; N] where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?; if unty::type_equal::() { @@ -493,11 +501,13 @@ where } } -impl<'de, T, const N: usize> BorrowDecode<'de> for [T; N] +impl<'de, T, const N: usize, Context> BorrowDecode<'de, Context> for [T; N] where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?; if unty::type_equal::() { @@ -523,25 +533,25 @@ where } } -impl Decode for () { - fn decode(_: &mut D) -> Result { +impl Decode for () { + fn decode>(_: &mut D) -> Result { Ok(()) } } impl_borrow_decode!(()); -impl Decode for core::marker::PhantomData { - fn decode(_: &mut D) -> Result { +impl Decode for core::marker::PhantomData { + fn decode>(_: &mut D) -> Result { Ok(core::marker::PhantomData) } } impl_borrow_decode!(core::marker::PhantomData, T); -impl Decode for Option +impl Decode for Option where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { match super::decode_option_variant(decoder, core::any::type_name::>())? { Some(_) => { let val = T::decode(decoder)?; @@ -552,11 +562,13 @@ where } } -impl<'de, T> BorrowDecode<'de> for Option +impl<'de, T, Context> BorrowDecode<'de, Context> for Option where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { match super::decode_option_variant(decoder, core::any::type_name::>())? { Some(_) => { let val = T::borrow_decode(decoder)?; @@ -567,12 +579,12 @@ where } } -impl Decode for Result +impl Decode for Result where - T: Decode, - U: Decode, + T: Decode, + U: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let is_ok = u32::decode(decoder)?; match is_ok { 0 => { @@ -592,12 +604,14 @@ where } } -impl<'de, T, U> BorrowDecode<'de> for Result +impl<'de, T, U, Context> BorrowDecode<'de, Context> for Result where - T: BorrowDecode<'de>, - U: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, + U: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let is_ok = u32::decode(decoder)?; match is_ok { 0 => { @@ -617,48 +631,52 @@ where } } -impl Decode for Cell +impl Decode for Cell where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = T::decode(decoder)?; Ok(Cell::new(t)) } } -impl<'de, T> BorrowDecode<'de> for Cell +impl<'de, T, Context> BorrowDecode<'de, Context> for Cell where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = T::borrow_decode(decoder)?; Ok(Cell::new(t)) } } -impl Decode for RefCell +impl Decode for RefCell where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = T::decode(decoder)?; Ok(RefCell::new(t)) } } -impl<'de, T> BorrowDecode<'de> for RefCell +impl<'de, T, Context> BorrowDecode<'de, Context> for RefCell where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = T::borrow_decode(decoder)?; Ok(RefCell::new(t)) } } -impl Decode for Duration { - fn decode(decoder: &mut D) -> Result { +impl Decode for Duration { + fn decode>(decoder: &mut D) -> Result { const NANOS_PER_SEC: u64 = 1_000_000_000; let secs: u64 = Decode::decode(decoder)?; let nanos: u32 = Decode::decode(decoder)?; @@ -670,54 +688,58 @@ impl Decode for Duration { } impl_borrow_decode!(Duration); -impl Decode for Range +impl Decode for Range where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let min = T::decode(decoder)?; let max = T::decode(decoder)?; Ok(min..max) } } -impl<'de, T> BorrowDecode<'de> for Range +impl<'de, T, Context> BorrowDecode<'de, Context> for Range where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let min = T::borrow_decode(decoder)?; let max = T::borrow_decode(decoder)?; Ok(min..max) } } -impl Decode for RangeInclusive +impl Decode for RangeInclusive where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let min = T::decode(decoder)?; let max = T::decode(decoder)?; Ok(RangeInclusive::new(min, max)) } } -impl<'de, T> BorrowDecode<'de> for RangeInclusive +impl<'de, T, Context> BorrowDecode<'de, Context> for RangeInclusive where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let min = T::borrow_decode(decoder)?; let max = T::borrow_decode(decoder)?; Ok(RangeInclusive::new(min, max)) } } -impl Decode for Bound +impl Decode for Bound where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { match u32::decode(decoder)? { 0 => Ok(Bound::Unbounded), 1 => Ok(Bound::Included(T::decode(decoder)?)), @@ -731,11 +753,13 @@ where } } -impl<'de, T> BorrowDecode<'de> for Bound +impl<'de, T, Context> BorrowDecode<'de, Context> for Bound where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { match u32::decode(decoder)? { 0 => Ok(Bound::Unbounded), 1 => Ok(Bound::Included(T::borrow_decode(decoder)?)), diff --git a/src/de/mod.rs b/src/de/mod.rs index 061f5b48..1ce655c6 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -5,7 +5,10 @@ mod impl_core; mod impl_tuples; mod impls; -use self::read::{BorrowReader, Reader}; +use self::{ + decoder::WithContext, + read::{BorrowReader, Reader}, +}; use crate::{ config::{Config, InternalLimitConfig}, error::DecodeError, @@ -18,11 +21,13 @@ pub use self::decoder::DecoderImpl; /// Trait that makes a type able to be decoded, akin to serde's `DeserializeOwned` trait. /// +/// Some types may require specific contexts. For example, to decode arena-based collections, an arena allocator must be provided as a context. In these cases, the context type `Context` should be specified or bounded. +/// /// This trait should be implemented for types which do not have references to data in the reader. For types that contain e.g. `&str` and `&[u8]`, implement [BorrowDecode] instead. /// /// Whenever you implement `Decode` for your type, the base trait `BorrowDecode` is automatically implemented. /// -/// This trait will be automatically implemented if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to your type. Note that if the type contains any lifetimes, `BorrowDecode` will be implemented instead. +/// This trait will be automatically implemented with unbounded `Context` if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to your type. Note that if the type contains any lifetimes, `BorrowDecode` will be implemented instead. /// /// # Implementing this trait manually /// @@ -44,8 +49,8 @@ pub use self::decoder::DecoderImpl; /// # pub x: f32, /// # pub y: f32, /// # } -/// impl bincode::Decode for Entity { -/// fn decode( +/// impl bincode::Decode for Entity { +/// fn decode>( /// decoder: &mut D, /// ) -> core::result::Result { /// Ok(Self { @@ -54,8 +59,8 @@ pub use self::decoder::DecoderImpl; /// }) /// } /// } -/// impl<'de> bincode::BorrowDecode<'de> for Entity { -/// fn borrow_decode>( +/// impl<'de, Context> bincode::BorrowDecode<'de, Context> for Entity { +/// fn borrow_decode>( /// decoder: &mut D, /// ) -> core::result::Result { /// Ok(Self { @@ -71,20 +76,33 @@ pub use self::decoder::DecoderImpl; /// To get specific integer types, you can use: /// ``` /// # struct Foo; -/// # impl bincode::Decode for Foo { -/// # fn decode( +/// # impl bincode::Decode for Foo { +/// # fn decode>( /// # decoder: &mut D, /// # ) -> core::result::Result { -/// let x: u8 = bincode::Decode::decode(decoder)?; -/// let x = ::decode(decoder)?; +/// let x: u8 = bincode::Decode::::decode(decoder)?; +/// let x = >::decode(decoder)?; /// # Ok(Foo) /// # } /// # } /// # bincode::impl_borrow_decode!(Foo); /// ``` -pub trait Decode: Sized { +/// +/// You can use `Context` to require contexts for decoding a type: +/// ``` +/// # /// # use bumpalo::Bump; +/// use bincode::de::Decoder; +/// use bincode::error::DecodeError; +/// struct BytesInArena<'a>(bumpalo::collections::Vec<'a, u8>); +/// impl<'a> bincode::Decode<&'a bumpalo::Bump> for BytesInArena<'a> { +/// fn decode(decoder: &mut D) -> Result { +/// todo!() +/// } +/// # } +/// ``` +pub trait Decode: Sized { /// Attempt to decode this type with the given [Decode]. - fn decode(decoder: &mut D) -> Result; + fn decode>(decoder: &mut D) -> Result; } /// Trait that makes a type able to be decoded, akin to serde's `Deserialize` trait. @@ -92,17 +110,32 @@ pub trait Decode: Sized { /// This trait should be implemented for types that contain borrowed data, like `&str` and `&[u8]`. If your type does not have borrowed data, consider implementing [Decode] instead. /// /// This trait will be automatically implemented if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to a type with a lifetime. -pub trait BorrowDecode<'de>: Sized { +pub trait BorrowDecode<'de, Context>: Sized { /// Attempt to decode this type with the given [BorrowDecode]. - fn borrow_decode>(decoder: &mut D) -> Result; + fn borrow_decode>( + decoder: &mut D, + ) -> Result; } /// Helper macro to implement `BorrowDecode` for any type that implements `Decode`. #[macro_export] macro_rules! impl_borrow_decode { - ($ty:ty $(, $param:ident),*) => { - impl<'de $(, $param)*> $crate::BorrowDecode<'de> for $ty { - fn borrow_decode>( + ($ty:ty $(, $param:tt)*) => { + impl<'de $(, $param)*, __Context> $crate::BorrowDecode<'de, __Context> for $ty { + fn borrow_decode>( + decoder: &mut D, + ) -> core::result::Result { + $crate::Decode::decode(decoder) + } + } + }; +} + +#[macro_export] +macro_rules! impl_borrow_decode_with_context { + ($ty:ty, $context:ty $(, $param:tt)*) => { + impl<'de $(, $param)*> $crate::BorrowDecode<'de, $context> for $ty { + fn borrow_decode>( decoder: &mut D, ) -> core::result::Result { $crate::Decode::decode(decoder) @@ -119,6 +152,19 @@ pub trait Decoder: Sealed { /// The concrete [Config] type type C: Config; + /// The decoding context type + type Context; + + /// Returns the decoding context + fn context(&mut self) -> &mut Self::Context; + + fn with_context<'a, C>(&'a mut self, context: &'a mut C) -> WithContext<'a, Self, C> { + WithContext { + decoder: self, + context, + } + } + /// Returns a mutable reference to the reader fn reader(&mut self) -> &mut Self::R; @@ -166,8 +212,8 @@ pub trait Decoder: Sealed { /// # self.0.push(t); /// # } /// # } - /// impl Decode for Container { - /// fn decode(decoder: &mut D) -> Result { + /// impl> Decode for Container { + /// fn decode>(decoder: &mut D) -> Result { /// let len = u64::decode(decoder)?; /// let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?; /// // Make sure we don't allocate too much memory @@ -182,8 +228,8 @@ pub trait Decoder: Sealed { /// Ok(result) /// } /// } - /// impl<'de, T: bincode::BorrowDecode<'de>> bincode::BorrowDecode<'de> for Container { - /// fn borrow_decode>( + /// impl<'de, Context, T: bincode::BorrowDecode<'de, Context>> bincode::BorrowDecode<'de, Context> for Container { + /// fn borrow_decode>( /// decoder: &mut D, /// ) -> core::result::Result { /// let len = u64::borrow_decode(decoder)?; @@ -223,6 +269,8 @@ where type C = T::C; + type Context = T::Context; + fn reader(&mut self) -> &mut Self::R { T::reader(self) } @@ -240,6 +288,10 @@ where fn unclaim_bytes_read(&mut self, n: usize) { T::unclaim_bytes_read(self, n) } + + fn context(&mut self) -> &mut Self::Context { + T::context(self) + } } impl<'a, 'de, T> BorrowDecoder<'de> for &'a mut T diff --git a/src/features/impl_alloc.rs b/src/features/impl_alloc.rs index d4e656ee..2437f4e5 100644 --- a/src/features/impl_alloc.rs +++ b/src/features/impl_alloc.rs @@ -63,19 +63,21 @@ pub fn encode_to_vec(val: E, config: C) -> Result Decode for BinaryHeap +impl Decode for BinaryHeap where - T: Decode + Ord, + T: Decode + Ord, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { Ok(Vec::::decode(decoder)?.into()) } } -impl<'de, T> BorrowDecode<'de> for BinaryHeap +impl<'de, T, Context> BorrowDecode<'de, Context> for BinaryHeap where - T: BorrowDecode<'de> + Ord, + T: BorrowDecode<'de, Context> + Ord, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { Ok(Vec::::borrow_decode(decoder)?.into()) } } @@ -94,12 +96,12 @@ where } } -impl Decode for BTreeMap +impl Decode for BTreeMap where - K: Decode + Ord, - V: Decode, + K: Decode + Ord, + V: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::<(K, V)>(len)?; @@ -115,12 +117,14 @@ where Ok(map) } } -impl<'de, K, V> BorrowDecode<'de> for BTreeMap +impl<'de, K, V, Context> BorrowDecode<'de, Context> for BTreeMap where - K: BorrowDecode<'de> + Ord, - V: BorrowDecode<'de>, + K: BorrowDecode<'de, Context> + Ord, + V: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::<(K, V)>(len)?; @@ -152,11 +156,11 @@ where } } -impl Decode for BTreeSet +impl Decode for BTreeSet where - T: Decode + Ord, + T: Decode + Ord, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::(len)?; @@ -171,11 +175,13 @@ where Ok(map) } } -impl<'de, T> BorrowDecode<'de> for BTreeSet +impl<'de, T, Context> BorrowDecode<'de, Context> for BTreeSet where - T: BorrowDecode<'de> + Ord, + T: BorrowDecode<'de, Context> + Ord, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::(len)?; @@ -204,19 +210,21 @@ where } } -impl Decode for VecDeque +impl Decode for VecDeque where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { Ok(Vec::::decode(decoder)?.into()) } } -impl<'de, T> BorrowDecode<'de> for VecDeque +impl<'de, T, Context> BorrowDecode<'de, Context> for VecDeque where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { Ok(Vec::::borrow_decode(decoder)?.into()) } } @@ -248,11 +256,11 @@ where } } -impl Decode for Vec +impl Decode for Vec where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let len = crate::de::decode_slice_len(decoder)?; if unty::type_equal::() { @@ -277,11 +285,13 @@ where } } -impl<'de, T> BorrowDecode<'de> for Vec +impl<'de, T, Context> BorrowDecode<'de, Context> for Vec where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let len = crate::de::decode_slice_len(decoder)?; if unty::type_equal::() { @@ -326,8 +336,8 @@ where } } -impl Decode for String { - fn decode(decoder: &mut D) -> Result { +impl Decode for String { + fn decode>(decoder: &mut D) -> Result { let bytes = Vec::::decode(decoder)?; String::from_utf8(bytes).map_err(|e| DecodeError::Utf8 { inner: e.utf8_error(), @@ -336,7 +346,7 @@ impl Decode for String { } impl_borrow_decode!(String); -impl Decode for Box { +impl Decode for Box { fn decode(decoder: &mut D) -> Result { String::decode(decoder).map(String::into_boxed_str) } @@ -349,20 +359,22 @@ impl Encode for String { } } -impl Decode for Box +impl Decode for Box where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = T::decode(decoder)?; Ok(Box::new(t)) } } -impl<'de, T> BorrowDecode<'de> for Box +impl<'de, T, Context> BorrowDecode<'de, Context> for Box where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = T::borrow_decode(decoder)?; Ok(Box::new(t)) } @@ -377,42 +389,46 @@ where } } -impl Decode for Box<[T]> +impl Decode for Box<[T]> where - T: Decode + 'static, + T: Decode + 'static, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let vec = Vec::decode(decoder)?; Ok(vec.into_boxed_slice()) } } -impl<'de, T> BorrowDecode<'de> for Box<[T]> +impl<'de, T, Context> BorrowDecode<'de, Context> for Box<[T]> where - T: BorrowDecode<'de> + 'de, + T: BorrowDecode<'de, Context> + 'de, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let vec = Vec::borrow_decode(decoder)?; Ok(vec.into_boxed_slice()) } } -impl<'cow, T> Decode for Cow<'cow, T> +impl<'cow, Context, T> Decode for Cow<'cow, T> where T: ToOwned + ?Sized, - ::Owned: Decode, + ::Owned: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = ::Owned::decode(decoder)?; Ok(Cow::Owned(t)) } } -impl<'cow, T> BorrowDecode<'cow> for Cow<'cow, T> +impl<'cow, T, Context> BorrowDecode<'cow, Context> for Cow<'cow, T> where T: ToOwned + ?Sized, - &'cow T: BorrowDecode<'cow>, + &'cow T: BorrowDecode<'cow, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = <&T>::borrow_decode(decoder)?; Ok(Cow::Borrowed(t)) } @@ -441,35 +457,39 @@ fn test_cow_round_trip() { assert_eq!(start, end); } -impl Decode for Rc +impl Decode for Rc where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = T::decode(decoder)?; Ok(Rc::new(t)) } } -impl Decode for Rc { - fn decode(decoder: &mut D) -> Result { +impl Decode for Rc { + fn decode>(decoder: &mut D) -> Result { let decoded = String::decode(decoder)?; Ok(decoded.into()) } } -impl<'de, T> BorrowDecode<'de> for Rc +impl<'de, T, Context> BorrowDecode<'de, Context> for Rc where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = T::borrow_decode(decoder)?; Ok(Rc::new(t)) } } -impl<'de> BorrowDecode<'de> for Rc { - fn borrow_decode>(decoder: &mut D) -> Result { +impl<'de, Context> BorrowDecode<'de, Context> for Rc { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let decoded = String::decode(decoder)?; Ok(decoded.into()) } @@ -484,59 +504,65 @@ where } } -impl Decode for Rc<[T]> +impl Decode for Rc<[T]> where - T: Decode + 'static, + T: Decode + 'static, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let vec = Vec::decode(decoder)?; Ok(vec.into()) } } -impl<'de, T> BorrowDecode<'de> for Rc<[T]> +impl<'de, T, Context> BorrowDecode<'de, Context> for Rc<[T]> where - T: BorrowDecode<'de> + 'de, + T: BorrowDecode<'de, Context> + 'de, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let vec = Vec::borrow_decode(decoder)?; Ok(vec.into()) } } #[cfg(target_has_atomic = "ptr")] -impl Decode for Arc +impl Decode for Arc where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = T::decode(decoder)?; Ok(Arc::new(t)) } } #[cfg(target_has_atomic = "ptr")] -impl Decode for Arc { - fn decode(decoder: &mut D) -> Result { +impl Decode for Arc { + fn decode>(decoder: &mut D) -> Result { let decoded = String::decode(decoder)?; Ok(decoded.into()) } } #[cfg(target_has_atomic = "ptr")] -impl<'de, T> BorrowDecode<'de> for Arc +impl<'de, T, Context> BorrowDecode<'de, Context> for Arc where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = T::borrow_decode(decoder)?; Ok(Arc::new(t)) } } #[cfg(target_has_atomic = "ptr")] -impl<'de> BorrowDecode<'de> for Arc { - fn borrow_decode>(decoder: &mut D) -> Result { +impl<'de, Context> BorrowDecode<'de, Context> for Arc { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let decoded = String::decode(decoder)?; Ok(decoded.into()) } @@ -553,22 +579,24 @@ where } #[cfg(target_has_atomic = "ptr")] -impl Decode for Arc<[T]> +impl Decode for Arc<[T]> where - T: Decode + 'static, + T: Decode + 'static, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let vec = Vec::decode(decoder)?; Ok(vec.into()) } } #[cfg(target_has_atomic = "ptr")] -impl<'de, T> BorrowDecode<'de> for Arc<[T]> +impl<'de, T, Context> BorrowDecode<'de, Context> for Arc<[T]> where - T: BorrowDecode<'de> + 'de, + T: BorrowDecode<'de, Context> + 'de, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let vec = Vec::borrow_decode(decoder)?; Ok(vec.into()) } diff --git a/src/features/impl_std.rs b/src/features/impl_std.rs index 04fae2f1..7cf74e72 100644 --- a/src/features/impl_std.rs +++ b/src/features/impl_std.rs @@ -23,12 +23,26 @@ use std::{ /// /// [config]: config/index.html #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -pub fn decode_from_std_read( +pub fn decode_from_std_read, C: Config, R: std::io::Read>( src: &mut R, config: C, +) -> Result { + decode_from_std_read_with_context(src, config, &mut ()) +} + +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn decode_from_std_read_with_context< + Context, + D: Decode, + C: Config, + R: std::io::Read, +>( + src: &mut R, + config: C, + context: &mut Context, ) -> Result { let reader = IoReader::new(src); - let mut decoder = DecoderImpl::<_, C>::new(reader, config); + let mut decoder = DecoderImpl::<_, C, Context>::new(reader, config, context); D::decode(&mut decoder) } @@ -140,8 +154,8 @@ impl Encode for CString { } } -impl Decode for CString { - fn decode(decoder: &mut D) -> Result { +impl Decode for CString { + fn decode>(decoder: &mut D) -> Result { let vec = std::vec::Vec::decode(decoder)?; CString::new(vec).map_err(|inner| DecodeError::CStringNulError { position: inner.nul_position(), @@ -162,20 +176,22 @@ where } } -impl Decode for Mutex +impl Decode for Mutex where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = T::decode(decoder)?; Ok(Mutex::new(t)) } } -impl<'de, T> BorrowDecode<'de> for Mutex +impl<'de, T, Context> BorrowDecode<'de, Context> for Mutex where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = T::borrow_decode(decoder)?; Ok(Mutex::new(t)) } @@ -193,20 +209,22 @@ where } } -impl Decode for RwLock +impl Decode for RwLock where - T: Decode, + T: Decode, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let t = T::decode(decoder)?; Ok(RwLock::new(t)) } } -impl<'de, T> BorrowDecode<'de> for RwLock +impl<'de, T, Context> BorrowDecode<'de, Context> for RwLock where - T: BorrowDecode<'de>, + T: BorrowDecode<'de, Context>, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let t = T::borrow_decode(decoder)?; Ok(RwLock::new(t)) } @@ -224,8 +242,8 @@ impl Encode for SystemTime { } } -impl Decode for SystemTime { - fn decode(decoder: &mut D) -> Result { +impl Decode for SystemTime { + fn decode>(decoder: &mut D) -> Result { let duration = Duration::decode(decoder)?; match SystemTime::UNIX_EPOCH.checked_add(duration) { Some(t) => Ok(t), @@ -244,8 +262,10 @@ impl Encode for &'_ Path { } } -impl<'de> BorrowDecode<'de> for &'de Path { - fn borrow_decode>(decoder: &mut D) -> Result { +impl<'de, Context> BorrowDecode<'de, Context> for &'de Path { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let str = <&'de str>::borrow_decode(decoder)?; Ok(Path::new(str)) } @@ -257,8 +277,8 @@ impl Encode for PathBuf { } } -impl Decode for PathBuf { - fn decode(decoder: &mut D) -> Result { +impl Decode for PathBuf { + fn decode>(decoder: &mut D) -> Result { let string = std::string::String::decode(decoder)?; Ok(string.into()) } @@ -280,8 +300,8 @@ impl Encode for IpAddr { } } -impl Decode for IpAddr { - fn decode(decoder: &mut D) -> Result { +impl Decode for IpAddr { + fn decode>(decoder: &mut D) -> Result { match u32::decode(decoder)? { 0 => Ok(IpAddr::V4(Ipv4Addr::decode(decoder)?)), 1 => Ok(IpAddr::V6(Ipv6Addr::decode(decoder)?)), @@ -301,8 +321,8 @@ impl Encode for Ipv4Addr { } } -impl Decode for Ipv4Addr { - fn decode(decoder: &mut D) -> Result { +impl Decode for Ipv4Addr { + fn decode>(decoder: &mut D) -> Result { let mut buff = [0u8; 4]; decoder.reader().read(&mut buff)?; Ok(Self::from(buff)) @@ -316,8 +336,8 @@ impl Encode for Ipv6Addr { } } -impl Decode for Ipv6Addr { - fn decode(decoder: &mut D) -> Result { +impl Decode for Ipv6Addr { + fn decode>(decoder: &mut D) -> Result { let mut buff = [0u8; 16]; decoder.reader().read(&mut buff)?; Ok(Self::from(buff)) @@ -340,8 +360,8 @@ impl Encode for SocketAddr { } } -impl Decode for SocketAddr { - fn decode(decoder: &mut D) -> Result { +impl Decode for SocketAddr { + fn decode>(decoder: &mut D) -> Result { match u32::decode(decoder)? { 0 => Ok(SocketAddr::V4(SocketAddrV4::decode(decoder)?)), 1 => Ok(SocketAddr::V6(SocketAddrV6::decode(decoder)?)), @@ -362,8 +382,8 @@ impl Encode for SocketAddrV4 { } } -impl Decode for SocketAddrV4 { - fn decode(decoder: &mut D) -> Result { +impl Decode for SocketAddrV4 { + fn decode>(decoder: &mut D) -> Result { let ip = Ipv4Addr::decode(decoder)?; let port = u16::decode(decoder)?; Ok(Self::new(ip, port)) @@ -378,8 +398,8 @@ impl Encode for SocketAddrV6 { } } -impl Decode for SocketAddrV6 { - fn decode(decoder: &mut D) -> Result { +impl Decode for SocketAddrV6 { + fn decode>(decoder: &mut D) -> Result { let ip = Ipv6Addr::decode(decoder)?; let port = u16::decode(decoder)?; Ok(Self::new(ip, port, 0, 0)) @@ -421,13 +441,13 @@ where } } -impl Decode for HashMap +impl Decode for HashMap where - K: Decode + Eq + std::hash::Hash, - V: Decode, + K: Decode + Eq + std::hash::Hash, + V: Decode, S: std::hash::BuildHasher + Default, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::<(K, V)>(len)?; @@ -444,13 +464,15 @@ where Ok(map) } } -impl<'de, K, V, S> BorrowDecode<'de> for HashMap +impl<'de, K, V, S, Context> BorrowDecode<'de, Context> for HashMap where - K: BorrowDecode<'de> + Eq + std::hash::Hash, - V: BorrowDecode<'de>, + K: BorrowDecode<'de, Context> + Eq + std::hash::Hash, + V: BorrowDecode<'de, Context>, S: std::hash::BuildHasher + Default, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::<(K, V)>(len)?; @@ -468,12 +490,12 @@ where } } -impl Decode for HashSet +impl Decode for HashSet where - T: Decode + Eq + Hash, + T: Decode + Eq + Hash, S: std::hash::BuildHasher + Default, { - fn decode(decoder: &mut D) -> Result { + fn decode>(decoder: &mut D) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::(len)?; @@ -490,12 +512,14 @@ where } } -impl<'de, T, S> BorrowDecode<'de> for HashSet +impl<'de, T, S, Context> BorrowDecode<'de, Context> for HashSet where - T: BorrowDecode<'de> + Eq + Hash, + T: BorrowDecode<'de, Context> + Eq + Hash, S: std::hash::BuildHasher + Default, { - fn borrow_decode>(decoder: &mut D) -> Result { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { let len = crate::de::decode_slice_len(decoder)?; decoder.claim_container_read::(len)?; diff --git a/src/features/serde/de_borrowed.rs b/src/features/serde/de_borrowed.rs index 093a1984..ee0815eb 100644 --- a/src/features/serde/de_borrowed.rs +++ b/src/features/serde/de_borrowed.rs @@ -19,7 +19,8 @@ where C: Config, { let reader = crate::de::read::SliceReader::new(slice); - let mut decoder = crate::de::DecoderImpl::new(reader, config); + let mut context = (); + let mut decoder = crate::de::DecoderImpl::new(reader, config, &mut context); let serde_decoder = SerdeDecoder { de: &mut decoder, pd: PhantomData, @@ -37,7 +38,8 @@ where C: Config, { let reader = crate::de::read::SliceReader::new(slice); - let mut decoder = crate::de::DecoderImpl::new(reader, config); + let mut context = (); + let mut decoder = crate::de::DecoderImpl::new(reader, config, &mut context); let serde_decoder = SerdeDecoder { de: &mut decoder, pd: PhantomData, @@ -56,7 +58,8 @@ where C: Config, { let reader = crate::de::read::SliceReader::new(slice); - let mut decoder = crate::de::DecoderImpl::new(reader, config); + let mut context = (); + let mut decoder = crate::de::DecoderImpl::new(reader, config, &mut context); let serde_decoder = SerdeDecoder { de: &mut decoder, pd: PhantomData, diff --git a/src/features/serde/de_owned.rs b/src/features/serde/de_owned.rs index 502a92a5..292efb3c 100644 --- a/src/features/serde/de_owned.rs +++ b/src/features/serde/de_owned.rs @@ -20,7 +20,8 @@ where C: Config, { let reader = crate::de::read::SliceReader::new(slice); - let mut decoder = crate::de::DecoderImpl::new(reader, config); + let mut context = (); + let mut decoder = crate::de::DecoderImpl::new(reader, config, &mut context); let serde_decoder = SerdeDecoder { de: &mut decoder }; let result = D::deserialize(serde_decoder)?; let bytes_read = slice.len() - decoder.reader().slice.len(); @@ -39,7 +40,8 @@ pub fn decode_from_std_read( config: C, ) -> Result { let reader = crate::IoReader::new(src); - let mut decoder = crate::de::DecoderImpl::new(reader, config); + let mut context = (); + let mut decoder = crate::de::DecoderImpl::new(reader, config, &mut context); let serde_decoder = SerdeDecoder { de: &mut decoder }; D::deserialize(serde_decoder) } @@ -53,7 +55,8 @@ pub fn decode_from_reader( reader: R, config: C, ) -> Result { - let mut decoder = crate::de::DecoderImpl::<_, C>::new(reader, config); + let mut context = (); + let mut decoder = crate::de::DecoderImpl::<_, C, ()>::new(reader, config, &mut context); let serde_decoder = SerdeDecoder { de: &mut decoder }; D::deserialize(serde_decoder) } diff --git a/src/features/serde/mod.rs b/src/features/serde/mod.rs index 353c0c47..f5aff515 100644 --- a/src/features/serde/mod.rs +++ b/src/features/serde/mod.rs @@ -182,7 +182,7 @@ impl serde::ser::Error for crate::error::EncodeError { #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Compat(pub T); -impl crate::Decode for Compat +impl crate::Decode for Compat where T: serde::de::DeserializeOwned, { @@ -191,7 +191,7 @@ where T::deserialize(serde_decoder).map(Compat) } } -impl<'de, T> crate::BorrowDecode<'de> for Compat +impl<'de, T, Context> crate::BorrowDecode<'de, Context> for Compat where T: serde::de::DeserializeOwned, { @@ -244,7 +244,7 @@ where #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct BorrowCompat(pub T); -impl<'de, T> crate::de::BorrowDecode<'de> for BorrowCompat +impl<'de, T, Context> crate::de::BorrowDecode<'de, Context> for BorrowCompat where T: serde::de::Deserialize<'de>, { diff --git a/src/lib.rs b/src/lib.rs index e7c4d4af..89974a4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![warn(missing_docs, unused_lifetimes)] +#![warn(unused_lifetimes)] #![cfg_attr(docsrs, feature(doc_cfg))] //! Bincode is a crate for encoding and decoding using a tiny binary @@ -145,12 +145,20 @@ pub fn encode_into_writer( /// See the [config] module for more information on configurations. /// /// [config]: config/index.html -pub fn decode_from_slice( +pub fn decode_from_slice, C: Config>( src: &[u8], config: C, +) -> Result<(D, usize), error::DecodeError> { + decode_from_slice_with_context(src, config, &mut ()) +} + +pub fn decode_from_slice_with_context, C: Config>( + src: &[u8], + config: C, + context: &mut Context, ) -> Result<(D, usize), error::DecodeError> { let reader = de::read::SliceReader::new(src); - let mut decoder = de::DecoderImpl::<_, C>::new(reader, config); + let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context); let result = D::decode(&mut decoder)?; let bytes_read = src.len() - decoder.reader().slice.len(); Ok((result, bytes_read)) @@ -161,12 +169,25 @@ pub fn decode_from_slice( /// See the [config] module for more information on configurations. /// /// [config]: config/index.html -pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a>, C: Config>( +pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>( + src: &'a [u8], + config: C, +) -> Result<(D, usize), error::DecodeError> { + borrow_decode_from_slice_with_context(src, config, &mut ()) +} + +pub fn borrow_decode_from_slice_with_context< + 'a, + Context, + D: de::BorrowDecode<'a, Context>, + C: Config, +>( src: &'a [u8], config: C, + context: &mut Context, ) -> Result<(D, usize), error::DecodeError> { let reader = de::read::SliceReader::new(src); - let mut decoder = de::DecoderImpl::<_, C>::new(reader, config); + let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context); let result = D::borrow_decode(&mut decoder)?; let bytes_read = src.len() - decoder.reader().slice.len(); Ok((result, bytes_read)) @@ -177,11 +198,12 @@ pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a>, C: Config>( /// See the [config] module for more information on configurations. /// /// [config]: config/index.html -pub fn decode_from_reader( +pub fn decode_from_reader, R: Reader, C: Config>( reader: R, config: C, ) -> Result { - let mut decoder = de::DecoderImpl::<_, C>::new(reader, config); + let mut context = (); + let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, &mut context); D::decode(&mut decoder) } diff --git a/tests/alloc.rs b/tests/alloc.rs index 73e153c3..f5bc75ee 100644 --- a/tests/alloc.rs +++ b/tests/alloc.rs @@ -29,7 +29,7 @@ impl bincode::Encode for Foo { } } -impl bincode::Decode for Foo { +impl bincode::Decode for Foo { fn decode( decoder: &mut D, ) -> Result { @@ -145,7 +145,9 @@ fn test_container_limits() { bincode::encode_to_vec(DECODE_LIMIT as u64, bincode::config::standard()).unwrap(), ]; - fn validate_fail BorrowDecode<'de> + core::fmt::Debug>(slice: &[u8]) { + fn validate_fail + for<'de> BorrowDecode<'de, ()> + core::fmt::Debug>( + slice: &[u8], + ) { let result = bincode::decode_from_slice::( slice, bincode::config::standard().with_limit::(), diff --git a/tests/context.rs b/tests/context.rs new file mode 100644 index 00000000..145453f2 --- /dev/null +++ b/tests/context.rs @@ -0,0 +1,105 @@ +#![cfg(feature = "alloc")] + +use bincode::{ + config, de::BorrowDecoder, decode_from_slice, decode_from_slice_with_context, encode_to_vec, + error::DecodeError, BorrowDecode, Decode, Encode, +}; +use bumpalo::{collections::Vec, vec, Bump}; + +#[derive(PartialEq, Eq, Debug)] +struct CodableVec<'bump, T: 'bump>(Vec<'bump, T>); + +impl<'bump, T: Encode> Encode for CodableVec<'bump, T> { + fn encode( + &self, + encoder: &mut E, + ) -> Result<(), bincode::error::EncodeError> { + self.0.as_slice().encode(encoder) + } +} + +impl<'bump, T: Decode<&'bump Bump>> Decode<&'bump Bump> for CodableVec<'bump, T> { + fn decode>( + decoder: &mut D, + ) -> Result { + let len = u64::decode(decoder)?; + let len = usize::try_from(len).map_err(|_| DecodeError::OutsideUsizeRange(len))?; + decoder.claim_container_read::(len)?; + let mut vec = Vec::with_capacity_in(len, decoder.context()); + for _ in 0..len { + decoder.unclaim_bytes_read(core::mem::size_of::()); + vec.push(T::decode(decoder)?); + } + Ok(Self(vec)) + } +} + +impl<'de, 'bump, T: BorrowDecode<'de, &'bump Bump>> BorrowDecode<'de, &'bump Bump> + for CodableVec<'bump, T> +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = u64::decode(decoder)?; + let len = usize::try_from(len).map_err(|_| DecodeError::OutsideUsizeRange(len))?; + + decoder.claim_container_read::(len)?; + + let mut vec = Vec::with_capacity_in(len, decoder.context()); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + vec.push(T::borrow_decode(decoder)?); + } + Ok(Self(vec)) + } +} + +#[derive(Encode, Decode, PartialEq, Eq, Debug)] +#[bincode(decode_context = "&'bump Bump")] +struct Container<'bump> { + vec: CodableVec<'bump, u32>, +} + +#[derive(Encode, Decode, PartialEq, Eq, Debug)] +#[bincode(decode_context = "&'bump Bump")] +enum _EnumContainer<'bump> { + Vec(CodableVec<'bump, u32>), +} + +#[ouroboros::self_referencing] +struct SelfReferencing { + bump: Bump, + #[borrows(bump)] + #[not_covariant] + container: Container<'this>, +} + +impl Decode for SelfReferencing { + fn decode>( + decoder: &mut D, + ) -> Result { + SelfReferencing::try_new(Bump::new(), |mut bump| { + Container::decode(&mut decoder.with_context(&mut bump)) + }) + } +} + +#[test] +fn decode_with_context() { + let config = config::standard(); + let bump = Bump::new(); + let container = Container { + vec: CodableVec(vec![in ≎ 1, 2, 3]), + }; + + let bytes = encode_to_vec(&container, config).unwrap(); + let (decoded_container, _) = + decode_from_slice_with_context::<_, Container, _>(&bytes, config, &mut &bump).unwrap(); + + assert_eq!(container, decoded_container); + + let self_referencing: SelfReferencing = decode_from_slice(&bytes, config).unwrap().0; + self_referencing.with_container(|c| assert_eq!(&container, c)) +} diff --git a/tests/derive.rs b/tests/derive.rs index 07f6be2d..b2a23793 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -28,11 +28,11 @@ pub struct Test2 { b: u32, c: u32, } -impl ::bincode::Decode for Test2 +impl ::bincode::Decode for Test2 where - T: ::bincode::Decode, + T: ::bincode::Decode, { - fn decode( + fn decode>( decoder: &mut D, ) -> core::result::Result { Ok(Self { @@ -42,11 +42,11 @@ where }) } } -impl<'__de, T> ::bincode::BorrowDecode<'__de> for Test2 +impl<'__de, T, Context> ::bincode::BorrowDecode<'__de, Context> for Test2 where - T: ::bincode::BorrowDecode<'__de> + '__de, + T: ::bincode::BorrowDecode<'__de, Context> + '__de, { - fn borrow_decode>( + fn borrow_decode>( decoder: &mut D, ) -> core::result::Result { Ok(Self { diff --git a/tests/issues/issue_431.rs b/tests/issues/issue_431.rs index 40c3c6a7..03b35d2f 100644 --- a/tests/issues/issue_431.rs +++ b/tests/issues/issue_431.rs @@ -8,15 +8,19 @@ use std::string::String; #[derive(Decode, Encode, PartialEq, Debug)] #[bincode( - borrow_decode_bounds = "&'__de U<'a, A>: ::bincode::de::BorrowDecode<'__de> + '__de, '__de: 'a" + decode_context = "()", + borrow_decode_bounds = "&'__de U<'a, A>: ::bincode::de::BorrowDecode<'__de, ()> + '__de, '__de: 'a" )] -struct T<'a, A: Clone + Encode + Decode> { +struct T<'a, A: Clone + Encode + Decode<()>> { t: Cow<'a, U<'a, A>>, } #[derive(Clone, Decode, Encode, PartialEq, Debug)] -#[bincode(borrow_decode_bounds = "&'__de A: ::bincode::de::BorrowDecode<'__de> + '__de, '__de: 'a")] -struct U<'a, A: Clone + Encode + Decode> { +#[bincode( + decode_context = "()", + borrow_decode_bounds = "&'__de A: ::bincode::de::BorrowDecode<'__de, ()> + '__de, '__de: 'a" +)] +struct U<'a, A: Clone + Encode + Decode<()>> { u: Cow<'a, A>, } diff --git a/tests/issues/issue_614.rs b/tests/issues/issue_614.rs index b82c50ac..c36b17e1 100644 --- a/tests/issues/issue_614.rs +++ b/tests/issues/issue_614.rs @@ -7,7 +7,7 @@ pub struct A; #[derive(Encode, Decode, Clone)] pub struct B where - T: Clone + Encode + Decode, + T: Clone + Encode + Decode<()>, { pub t: T, } @@ -15,7 +15,7 @@ where #[derive(Encode, Decode)] pub struct MyStruct where - T: Clone + Encode + Decode, + T: Clone + Encode + Decode<()>, { pub a: A, pub b: B, diff --git a/tests/serde.rs b/tests/serde.rs index 65864228..7a5ed839 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -2,7 +2,6 @@ extern crate alloc; -use alloc::string::String; use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, bincode::Encode, bincode::Decode)] @@ -174,7 +173,7 @@ mod derive { fn test_serde_derive() { fn test_encode_decode(start: T, expected_len: usize) where - T: bincode::Encode + bincode::Decode + PartialEq + core::fmt::Debug, + T: bincode::Encode + bincode::Decode<()> + PartialEq + core::fmt::Debug, { let mut slice = [0u8; 100]; let len = bincode::encode_into_slice(&start, &mut slice, bincode::config::standard()) diff --git a/tests/std.rs b/tests/std.rs index 3f6cc803..e505fc8f 100644 --- a/tests/std.rs +++ b/tests/std.rs @@ -31,7 +31,7 @@ impl bincode::Encode for Foo { } } -impl bincode::Decode for Foo { +impl bincode::Decode for Foo { fn decode( decoder: &mut D, ) -> Result { diff --git a/tests/utils.rs b/tests/utils.rs index 6c8392b8..22e35335 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -128,13 +128,18 @@ where #[cfg(feature = "serde")] pub trait TheSameTrait: - bincode::Encode + bincode::Decode + serde::de::DeserializeOwned + serde::Serialize + Debug + 'static + bincode::Encode + + bincode::Decode<()> + + serde::de::DeserializeOwned + + serde::Serialize + + Debug + + 'static { } #[cfg(feature = "serde")] impl TheSameTrait for T where T: bincode::Encode - + bincode::Decode + + bincode::Decode<()> + serde::de::DeserializeOwned + serde::Serialize + Debug @@ -143,9 +148,9 @@ impl TheSameTrait for T where } #[cfg(not(feature = "serde"))] -pub trait TheSameTrait: bincode::Encode + bincode::Decode + Debug + 'static {} +pub trait TheSameTrait: bincode::Encode + bincode::Decode<()> + Debug + 'static {} #[cfg(not(feature = "serde"))] -impl TheSameTrait for T where T: bincode::Encode + bincode::Decode + Debug + 'static {} +impl TheSameTrait for T where T: bincode::Encode + bincode::Decode<()> + Debug + 'static {} #[allow(dead_code)] // This is not used in every test pub fn the_same(element: V) {