1use crate::{Deserialize, DeserializeError, Serialize, SerializeError};
7use core::{iter, marker::PhantomData};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48#[must_use = "must call `serialize` on this array"]
49pub struct DynamicArray<Length, Collection> {
50 inner: Collection,
52 _length: PhantomData<Length>,
54}
55
56impl<Length, Collection> From<Collection> for DynamicArray<Length, Collection>
57where
58 Length: crate::Length,
59 Collection: IntoIterator + Copy,
60 Collection::Item: Serialize,
61{
62 fn from(collection: Collection) -> Self {
63 Self {
64 inner: collection,
65 _length: PhantomData,
66 }
67 }
68}
69
70impl<Length, Collection> Serialize for DynamicArray<Length, Collection>
71where
72 Length: crate::Length,
73 Collection: IntoIterator + Copy,
74 Collection::Item: Serialize,
75{
76 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
77 where
78 Buffer: bytes::BufMut + ?Sized,
79 {
80 Length::serialize_with(
81 |_value, buffer| {
82 self.inner.into_iter().try_fold(0_usize, |acc, elem| {
84 elem.serialize(buffer)
85 .and_then(|size| acc.checked_add(size).ok_or(SerializeError::SizeOverflow))
86 })
87 },
88 |_value| {
89 self.inner.into_iter().try_fold(0_usize, |acc, elem| {
91 elem.size().and_then(|size| acc.checked_add(size))
92 })
93 },
94 0,
95 buffer,
96 )
97 }
98
99 fn size(&self) -> Option<usize> {
100 self.inner
102 .into_iter()
103 .try_fold(Length::size(), |acc, elem| {
104 elem.size().and_then(|size| acc.checked_add(size))
105 })
106 }
107}
108
109impl<Length, Collection> Deserialize for DynamicArray<Length, Collection>
110where
111 Length: crate::Length,
112 Collection: IntoIterator + FromIterator<<Collection::Item as Deserialize>::Output>,
113 Collection::Item: Deserialize,
114{
115 type Output = Collection;
116
117 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
118 where
119 Buffer: bytes::Buf + ?Sized,
120 {
121 Length::deserialize_with(
122 |buffer| {
123 let mut error: Option<DeserializeError> = None;
125 let collection = iter::from_fn(|| {
126 if error.is_none() && buffer.has_remaining() {
128 Collection::Item::deserialize(buffer)
129 .map_err(|err| {
130 error = Some(err);
132 })
133 .ok()
134 } else {
135 None
136 }
137 })
138 .collect();
139 error.map_or_else(|| Ok(collection), Err)
141 },
142 buffer,
143 )
144 }
145
146 fn size_hint() -> Option<usize> {
147 Some(Length::size())
149 }
150}
151
152#[cfg(test)]
153#[expect(clippy::inline_modules, reason = "false-positive")]
154mod tests {
155 use super::*;
156 use crate::LengthU32;
157 use alloc::{vec, vec::Vec};
158
159 #[test]
160 fn serialize() {
161 let value = vec![1_u16, 2, 3, 4];
162 let array = <DynamicArray<LengthU32, _>>::from(&value);
163 let bytes = <DynamicArray<LengthU32, _>>::from(&value)
164 .to_bytes()
165 .expect("should serialize the Vec");
166 assert_eq!(Some(bytes.len()), array.size());
167 assert_eq!(bytes, [0_u8, 0, 0, 8, 0, 1, 0, 2, 0, 3, 0, 4].as_slice());
168 }
169
170 #[test]
171 fn serialize_empty() {
172 let value: Vec<u16> = vec![];
173 let array = <DynamicArray<LengthU32, _>>::from(&value);
174 let bytes = <DynamicArray<LengthU32, _>>::from(&value)
175 .to_bytes()
176 .expect("should serialize the Vec");
177 assert_eq!(Some(bytes.len()), array.size());
178 assert_eq!(bytes, [0_u8, 0, 0, 0].as_slice());
179 }
180
181 #[test]
182 fn deserialize() {
183 let buffer = [0_u8, 0, 0, 8, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5];
184 let output = DynamicArray::<LengthU32, Vec<u16>>::deserialize(&mut buffer.as_slice())
185 .expect("should deserialize the Vec");
186 assert_eq!(output, vec![1_u16, 2, 3, 4]);
187 assert_eq!(DynamicArray::<LengthU32, Vec<u16>>::size_hint(), Some(4));
188 }
189
190 #[test]
191 fn deserialize_empty() {
192 let buffer = [0_u8, 0, 0, 0, 0, 1];
193 let output = DynamicArray::<LengthU32, Vec<u16>>::deserialize(&mut buffer.as_slice())
194 .expect("should deserialize the Vec");
195 assert_eq!(output, Vec::<u16>::new());
196 assert_eq!(DynamicArray::<LengthU32, Vec<u16>>::size_hint(), Some(4));
197 }
198
199 #[test]
200 fn deserialize_error() {
201 let buffer = [0_u8, 0, 0, 3, 0, 1, 0];
202 let error = DynamicArray::<LengthU32, Vec<u16>>::deserialize(&mut buffer.as_slice())
203 .expect_err("shouldn't deserialize the Vec");
204 assert_eq!(error, DeserializeError::InsufficientData);
205 }
206
207 #[test]
208 fn dynamic_vec() {
209 let value = vec![1_u16, 2, 3, 4];
210 let mut bytes = DynamicArray::<LengthU32, _>::from(&value)
211 .to_bytes()
212 .expect("should serialize the Vec");
213 let output = DynamicArray::<LengthU32, Vec<u16>>::deserialize(&mut bytes)
214 .expect("should deserialize the Vec");
215 assert_eq!(value, output);
216 }
217
218 #[test]
219 #[cfg(feature = "std")]
220 fn dynamic_hash_map() {
221 use std::collections::HashMap;
222
223 let value = HashMap::<i32, i32>::from_iter(vec![(1_i32, 2_i32), (3_i32, 4_i32)]);
224 let mut bytes = DynamicArray::<LengthU32, _>::from(&value)
225 .to_bytes()
226 .expect("should serialize the HashMap");
227 let output = DynamicArray::<LengthU32, HashMap<i32, i32>>::deserialize(&mut bytes)
228 .expect("should deserialize the HashMap");
229 assert_eq!(value, output);
230 }
231}