From 35352dc2cebfcfefd916614d6619e53997270ff1 Mon Sep 17 00:00:00 2001 From: Kamil Skalski Date: Wed, 18 Mar 2026 16:23:23 +0800 Subject: [PATCH] feat(containers): add function to decode Vec with given body len --- wincode/src/schema/containers.rs | 71 +++++++++++++++++++++++++++++--- wincode/src/schema/mod.rs | 9 ++++ 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/wincode/src/schema/containers.rs b/wincode/src/schema/containers.rs index 95c7f692..49105a6a 100644 --- a/wincode/src/schema/containers.rs +++ b/wincode/src/schema/containers.rs @@ -87,6 +87,69 @@ use { #[cfg(feature = "alloc")] pub struct Vec(PhantomData, PhantomData); +#[cfg(feature = "alloc")] +impl<'de, T, Len> Vec { + /// Decode exactly `len` items of `T` from `reader` into a freshly allocated [`Vec`](vec::Vec). + /// + /// Errors if the prealloc check for `len` fails, fewer than `len` items are available, + /// or any item fails to decode. + /// + /// # Examples + /// + /// ``` + /// # #[cfg(feature = "alloc")] { + /// # use wincode::containers; + /// # use wincode::config::DefaultConfig; + /// # use wincode::len::BincodeLen; + /// # type C = DefaultConfig; + /// let data = [1u8, 2, 3, 4]; + /// let serialized = wincode::serialize(&data).unwrap(); + /// + /// let decoded = containers::Vec::::decode_body_with_len::( + /// &serialized[..], + /// data.len(), + /// ) + /// .unwrap(); + /// + /// assert_eq!(decoded.as_slice(), data.as_slice()); + /// # } + /// ``` + /// + /// ``` + /// # #[cfg(feature = "alloc")] { + /// # use wincode::containers; + /// # use wincode::config::DefaultConfig; + /// # use wincode::len::BincodeLen; + /// # type C = DefaultConfig; + /// let data = [1u8, 2, 3, 4]; + /// let serialized = wincode::serialize(&data).unwrap(); + /// + /// // Requesting more elements than were serialized returns an error. + /// let result = containers::Vec::::decode_body_with_len::( + /// &serialized[..], + /// data.len() + 1, + /// ); + /// + /// assert!(result.is_err()); + /// # } + /// ``` + pub fn decode_body_with_len( + reader: impl Reader<'de>, + len: usize, + ) -> ReadResult> + where + Len: SeqLen, + T: SchemaRead<'de, C>, + { + Len::prealloc_check::(len)?; + let mut vec: vec::Vec = vec::Vec::with_capacity(len); + decode_into_slice_t::(reader, &mut vec.spare_capacity_mut()[..len])?; + // SAFETY: `decode_into_slice_t` initializes all `len` elements on success. + unsafe { vec.set_len(len) }; + Ok(vec) + } +} + /// A [`VecDeque`](std::collections::VecDeque) with a customizable length encoding. #[cfg(feature = "alloc")] pub struct VecDeque(PhantomData, PhantomData); @@ -345,12 +408,8 @@ where type Dst = vec::Vec; fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit) -> ReadResult<()> { - let len = Len::read_prealloc_check::(reader.by_ref())?; - let mut vec: vec::Vec = vec::Vec::with_capacity(len); - decode_into_slice_t::(reader, &mut vec.spare_capacity_mut()[..len])?; - // SAFETY: `decode_into_slice_t` initializes all `len` elements on success. - unsafe { vec.set_len(len) }; - + let len = Len::read(reader.by_ref())?; + let vec = Self::decode_body_with_len(reader, len)?; dst.write(vec); Ok(()) } diff --git a/wincode/src/schema/mod.rs b/wincode/src/schema/mod.rs index 75539483..673f7957 100644 --- a/wincode/src/schema/mod.rs +++ b/wincode/src/schema/mod.rs @@ -2472,6 +2472,15 @@ mod tests { prop_assert_eq!(vec, schema_deserialized); } + #[test] + fn test_vec_body(array in any::<[StructStatic; 32]>()) { + let schema_serialized = serialize(&array).unwrap(); + let schema_deserialized = + containers::Vec::::decode_body_with_len::( + &schema_serialized[..], array.len()).unwrap(); + prop_assert_eq!(array.as_slice(), schema_deserialized.as_slice()); + } + #[test] fn test_serialize_slice(slice in proptest::collection::vec(any::(), 0..=100)) { let bincode_serialized = bincode::serialize(slice.as_slice()).unwrap();