diff --git a/msgpacker/src/binary.rs b/msgpacker/src/binary.rs new file mode 100644 index 0000000..3eea1be --- /dev/null +++ b/msgpacker/src/binary.rs @@ -0,0 +1,38 @@ +use core::ops::Deref; + +/// Wrapper struct to mark [u8] that are packed as bin rather than array +#[derive(Debug, PartialEq)] +pub struct MsgPackerBinSlice<'a>(pub &'a [u8]); + +impl<'a> Deref for MsgPackerBinSlice<'a> { + type Target = [u8]; + + fn deref(&self) -> &'a Self::Target { + self.0 + } +} + +#[cfg(feature = "alloc")] +pub mod alloc { + use super::*; + use ::alloc::vec::Vec; + + /// Wrapper struct to mark Vec that are packed as bin rather than array + #[derive(Clone, Debug, PartialEq)] + pub struct MsgPackerBin(pub Vec); + + impl MsgPackerBin { + /// Extracts a MsgPackerBinSlice containing the entire MsgPackerBin. + pub fn as_slice(&self) -> MsgPackerBinSlice { + MsgPackerBinSlice(self.0.as_slice()) + } + } + + impl Deref for MsgPackerBin { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } +} diff --git a/msgpacker/src/lib.rs b/msgpacker/src/lib.rs index b73a978..eb0ca17 100644 --- a/msgpacker/src/lib.rs +++ b/msgpacker/src/lib.rs @@ -13,6 +13,7 @@ extern crate alloc; #[cfg(feature = "alloc")] mod extension; +mod binary; mod error; mod format; mod helpers; @@ -92,6 +93,10 @@ pub trait Unpackable: Sized { pub mod prelude { pub use super::{Error, Packable, Unpackable}; + #[cfg(feature = "alloc")] + pub use super::binary::alloc::MsgPackerBin; + pub use super::binary::MsgPackerBinSlice; + #[cfg(feature = "derive")] pub use super::MsgPacker; diff --git a/msgpacker/src/pack/binary.rs b/msgpacker/src/pack/binary.rs index 01f1d2c..e71a481 100644 --- a/msgpacker/src/pack/binary.rs +++ b/msgpacker/src/pack/binary.rs @@ -1,7 +1,8 @@ use super::{Format, Packable}; +use crate::binary::MsgPackerBinSlice; use core::iter; -impl Packable for [u8] { +impl<'a> Packable for MsgPackerBinSlice<'a> { #[allow(unreachable_code)] fn pack(&self, buf: &mut T) -> usize where @@ -57,9 +58,10 @@ impl Packable for str { #[cfg(feature = "alloc")] mod alloc { use super::*; - use ::alloc::{string::String, vec::Vec}; + use crate::binary::alloc::MsgPackerBin; + use ::alloc::string::String; - impl Packable for Vec { + impl Packable for MsgPackerBin { fn pack(&self, buf: &mut T) -> usize where T: Extend, diff --git a/msgpacker/src/pack/collections.rs b/msgpacker/src/pack/collections.rs index bafee5f..62f882b 100644 --- a/msgpacker/src/pack/collections.rs +++ b/msgpacker/src/pack/collections.rs @@ -68,6 +68,19 @@ where mod alloc { use super::*; use ::alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; + use ::alloc::vec::Vec; + + impl Packable for Vec + where + X: Packable, + { + fn pack(&self, buf: &mut T) -> usize + where + T: Extend, + { + pack_array(buf, self) + } + } impl Packable for BTreeSet where diff --git a/msgpacker/src/unpack/binary.rs b/msgpacker/src/unpack/binary.rs index 5b23c89..d5b36da 100644 --- a/msgpacker/src/unpack/binary.rs +++ b/msgpacker/src/unpack/binary.rs @@ -37,14 +37,15 @@ pub fn unpack_str(mut buf: &[u8]) -> Result<(usize, &str), Error> { #[cfg(feature = "alloc")] mod alloc { use super::*; + use crate::binary::alloc::MsgPackerBin; use crate::helpers::{take_byte_iter, take_num_iter}; use ::alloc::{string::String, vec::Vec}; - impl Unpackable for Vec { + impl Unpackable for MsgPackerBin { type Error = Error; fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { - unpack_bytes(buf).map(|(n, b)| (n, b.to_vec())) + unpack_bytes(buf).map(|(n, b)| (n, MsgPackerBin(b.to_vec()))) } fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> @@ -69,7 +70,7 @@ mod alloc { if v.len() < len { return Err(Error::BufferTooShort); } - Ok((n + len, v)) + Ok((n + len, MsgPackerBin(v))) } } diff --git a/msgpacker/src/unpack/collections.rs b/msgpacker/src/unpack/collections.rs index 4bf9ff5..be9f47a 100644 --- a/msgpacker/src/unpack/collections.rs +++ b/msgpacker/src/unpack/collections.rs @@ -138,6 +138,25 @@ where mod alloc { use super::*; use ::alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; + use ::alloc::vec::Vec; + + impl Unpackable for Vec + where + X: Unpackable + Ord, + { + type Error = ::Error; + + fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { + unpack_array(buf) + } + + fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> + where + I: IntoIterator, + { + unpack_array_iter(bytes) + } + } impl Unpackable for BTreeSet where diff --git a/msgpacker/tests/binary.rs b/msgpacker/tests/binary.rs index ce79bbe..90702ee 100644 --- a/msgpacker/tests/binary.rs +++ b/msgpacker/tests/binary.rs @@ -5,11 +5,11 @@ mod utils; #[test] fn empty_vec() { - let v = vec![]; + let v = MsgPackerBin(vec![]); let mut bytes = vec![]; let n = v.pack(&mut bytes); - let (o, x) = Vec::::unpack(&bytes).unwrap(); - let (p, y) = Vec::::unpack_iter(bytes).unwrap(); + let (o, x) = MsgPackerBin::unpack(&bytes).unwrap(); + let (p, y) = MsgPackerBin::unpack_iter(bytes).unwrap(); assert_eq!(o, n); assert_eq!(p, n); assert_eq!(v, x); @@ -30,22 +30,11 @@ fn empty_str() { } proptest! { - #[test] - fn vec(v: Vec) { - utils::case(v); - } - #[test] fn str(s: String) { utils::case(s); } - #[test] - #[ignore] - fn large_vec(v in prop::collection::vec(any::(), 0..=u16::MAX as usize * 2)) { - utils::case(v); - } - #[test] #[ignore] fn large_str(v in prop::collection::vec(any::(), 0..=u16::MAX as usize * 2)) { diff --git a/msgpacker/tests/collections.rs b/msgpacker/tests/collections.rs index 57b19fb..b9f8ad5 100644 --- a/msgpacker/tests/collections.rs +++ b/msgpacker/tests/collections.rs @@ -32,7 +32,9 @@ struct Value { pub t11: PhantomData, pub t12: Option, pub t13: Option>, - pub t14: Option, + pub t14: Option>, + pub t15: Option>, + pub t16: Option, } proptest! {