diff --git a/src/enc/impls.rs b/src/enc/impls.rs index 6f7c431..7a05569 100644 --- a/src/enc/impls.rs +++ b/src/enc/impls.rs @@ -103,6 +103,27 @@ impl Encodeable for &'_ [u8] { } } +// BlockedTODO: https://github.com/rust-lang/rust/issues/37653 +// +// We'll want to implement encoding for both &[u8] and &[T: Encodeable], +// but those implementations overlap because u8 also implements Encodeabl +// +// default impl Encodeable for &'_ [u8] { +// fn encode(&self, mut encoder: E) -> Result<(), EncodeError> { +// encoder.encode_slice(*self) +// } +// } +// +// impl Encodeable for &'_ [T] { +// fn encode(&self, mut encoder: E) -> Result<(), EncodeError> { +// self.len().encode(&mut encoder)?; +// for item in self.iter() { +// item.encode(&mut encoder)?; +// } +// Ok(()) +// } +// } + impl Encodeable for &'_ str { fn encode(&self, mut encoder: E) -> Result<(), EncodeError> { encoder.encode_slice(self.as_bytes()) diff --git a/src/features/impl_alloc.rs b/src/features/impl_alloc.rs index c31bf18..bbe3d1f 100644 --- a/src/features/impl_alloc.rs +++ b/src/features/impl_alloc.rs @@ -1,5 +1,11 @@ -use crate::{config, enc, error, Config}; -use alloc::vec::Vec; +use crate::{ + config, + de::{Decodable, Decode}, + enc::{self, Encode, Encodeable}, + error::{DecodeError, EncodeError}, + Config, +}; +use alloc::{boxed::Box, vec::Vec}; #[derive(Default)] struct VecWriter { @@ -7,14 +13,14 @@ struct VecWriter { } impl enc::write::Writer for VecWriter { - fn write(&mut self, bytes: &[u8]) -> Result<(), error::EncodeError> { + fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> { self.inner.extend_from_slice(bytes); Ok(()) } } /// Encode the given value into a `Vec`. -pub fn encode_to_vec(val: E) -> Result, error::EncodeError> { +pub fn encode_to_vec(val: E) -> Result, EncodeError> { encode_to_vec_with_config(val, config::Default) } @@ -22,9 +28,78 @@ pub fn encode_to_vec(val: E) -> Result, error::Encod pub fn encode_to_vec_with_config( val: E, config: C, -) -> Result, error::EncodeError> { +) -> Result, EncodeError> { let writer = VecWriter::default(); let mut encoder = enc::Encoder::<_, C>::new(writer, config); val.encode(&mut encoder)?; Ok(encoder.into_writer().inner) } + +impl<'de, T> Decodable for Vec +where + T: Decodable, +{ + fn decode(mut decoder: D) -> Result { + let len = usize::decode(&mut decoder)?; + let mut vec = Vec::with_capacity(len); + for _ in 0..len { + vec.push(T::decode(&mut decoder)?); + } + Ok(vec) + } +} + +impl Encodeable for Vec +where + T: Encodeable, +{ + fn encode(&self, mut encoder: E) -> Result<(), EncodeError> { + self.len().encode(&mut encoder)?; + for item in self.iter() { + item.encode(&mut encoder)?; + } + Ok(()) + } +} + +impl<'de, T> Decodable for Box +where + T: Decodable, +{ + fn decode(decoder: D) -> Result { + let t = T::decode(decoder)?; + Ok(Box::new(t)) + } +} + +impl Encodeable for Box +where + T: Encodeable, +{ + fn encode(&self, encoder: E) -> Result<(), EncodeError> { + T::encode(self, encoder) + } +} + +impl<'de, T> Decodable for Box<[T]> +where + T: Decodable, +{ + fn decode(decoder: D) -> Result { + let vec = Vec::decode(decoder)?; + Ok(vec.into_boxed_slice()) + } +} + +impl Encodeable for Box<[T]> +where + T: Encodeable, +{ + fn encode(&self, mut encoder: E) -> Result<(), EncodeError> { + self.len().encode(&mut encoder)?; + for item in self.iter() { + item.encode(&mut encoder)?; + } + Ok(()) + } +} diff --git a/tests/alloc.rs b/tests/alloc.rs index 1dee965..e051d77 100644 --- a/tests/alloc.rs +++ b/tests/alloc.rs @@ -1,5 +1,9 @@ #![cfg(feature = "alloc")] +mod utils; + +use utils::the_same; + struct Foo { pub a: u32, pub b: u32, @@ -34,3 +38,10 @@ fn test_vec() { assert_eq!(foo.a, 5); assert_eq!(foo.b, 10); } + +#[test] +fn test_alloc_commons() { + the_same::>(vec![1, 2, 3, 4, 5]); + the_same(Box::::new(5)); + the_same(Box::<[u32]>::from(vec![1, 2, 3, 4, 5])); +} diff --git a/tests/basic_types.rs b/tests/basic_types.rs index afe338d..8e7781f 100644 --- a/tests/basic_types.rs +++ b/tests/basic_types.rs @@ -1,95 +1,6 @@ -use bincode::config::{self, Config}; -use core::fmt::Debug; +mod utils; -fn the_same_with_config(element: V, config: C) -where - V: bincode::enc::Encodeable - + for<'de> bincode::de::Decodable - + PartialEq - + Debug - + Clone - + 'static, - C: Config, -{ - let mut buffer = [0u8; 1024]; - let len = bincode::encode_into_slice_with_config(element.clone(), &mut buffer, config).unwrap(); - println!( - "{:?}: {:?} ({:?})", - element, - &buffer[..len], - core::any::type_name::() - ); - let decoded: V = bincode::decode_with_config(&mut buffer, config).unwrap(); - - assert_eq!(element, decoded); -} -fn the_same(element: V) -where - V: bincode::enc::Encodeable - + for<'de> bincode::de::Decodable - + PartialEq - + Debug - + Clone - + 'static, -{ - // A matrix of each different config option possible - the_same_with_config( - element.clone(), - config::Default - .with_little_endian() - .with_fixed_int_encoding() - .skip_fixed_array_length(), - ); - the_same_with_config( - element.clone(), - config::Default - .with_big_endian() - .with_fixed_int_encoding() - .skip_fixed_array_length(), - ); - the_same_with_config( - element.clone(), - config::Default - .with_little_endian() - .with_variable_int_encoding() - .skip_fixed_array_length(), - ); - the_same_with_config( - element.clone(), - config::Default - .with_big_endian() - .with_variable_int_encoding() - .skip_fixed_array_length(), - ); - the_same_with_config( - element.clone(), - config::Default - .with_little_endian() - .with_fixed_int_encoding() - .write_fixed_array_length(), - ); - the_same_with_config( - element.clone(), - config::Default - .with_big_endian() - .with_fixed_int_encoding() - .write_fixed_array_length(), - ); - the_same_with_config( - element.clone(), - config::Default - .with_little_endian() - .with_variable_int_encoding() - .write_fixed_array_length(), - ); - the_same_with_config( - element, - config::Default - .with_big_endian() - .with_variable_int_encoding() - .write_fixed_array_length(), - ); -} +use utils::the_same; #[test] fn test_numbers() { diff --git a/tests/utils.rs b/tests/utils.rs new file mode 100644 index 0000000..69955b6 --- /dev/null +++ b/tests/utils.rs @@ -0,0 +1,93 @@ +use bincode::config::{self, Config}; +use core::fmt::Debug; + +fn the_same_with_config(element: V, config: C) +where + V: bincode::enc::Encodeable + + for<'de> bincode::de::Decodable + + PartialEq + + Debug + + Clone + + 'static, + C: Config, +{ + let mut buffer = [0u8; 1024]; + let len = bincode::encode_into_slice_with_config(element.clone(), &mut buffer, config).unwrap(); + println!( + "{:?}: {:?} ({:?})", + element, + &buffer[..len], + core::any::type_name::() + ); + let decoded: V = bincode::decode_with_config(&mut buffer, config).unwrap(); + + assert_eq!(element, decoded); +} + +pub fn the_same(element: V) +where + V: bincode::enc::Encodeable + + for<'de> bincode::de::Decodable + + PartialEq + + Debug + + Clone + + 'static, +{ + // A matrix of each different config option possible + the_same_with_config( + element.clone(), + config::Default + .with_little_endian() + .with_fixed_int_encoding() + .skip_fixed_array_length(), + ); + the_same_with_config( + element.clone(), + config::Default + .with_big_endian() + .with_fixed_int_encoding() + .skip_fixed_array_length(), + ); + the_same_with_config( + element.clone(), + config::Default + .with_little_endian() + .with_variable_int_encoding() + .skip_fixed_array_length(), + ); + the_same_with_config( + element.clone(), + config::Default + .with_big_endian() + .with_variable_int_encoding() + .skip_fixed_array_length(), + ); + the_same_with_config( + element.clone(), + config::Default + .with_little_endian() + .with_fixed_int_encoding() + .write_fixed_array_length(), + ); + the_same_with_config( + element.clone(), + config::Default + .with_big_endian() + .with_fixed_int_encoding() + .write_fixed_array_length(), + ); + the_same_with_config( + element.clone(), + config::Default + .with_little_endian() + .with_variable_int_encoding() + .write_fixed_array_length(), + ); + the_same_with_config( + element, + config::Default + .with_big_endian() + .with_variable_int_encoding() + .write_fixed_array_length(), + ); +}