Skip to main content

rsomeip_bytes/
array.rs

1//! Dynamic arrays.
2//!
3//! This module provides the [`DynamicArray<Length, Collection>`] type which is used to serialize
4//! and deserialize arbitrary collections with specific length fields.
5
6use crate::{Deserialize, DeserializeError, Serialize, SerializeError};
7use core::{iter, marker::PhantomData};
8
9/// Dynamically sized array.
10///
11/// Used to serialize and deserialize arbitrary collections using specific length fields.
12///
13/// Works on any type that implements [`IntoIterator<Item = Serialize>`] which includes [`Vec<T>`],
14/// [`BTreeMap<K, V>`], and [`Option<T>`].
15///
16/// The length can be [`LengthZero`], [`LengthU8`], [`LengthU16`] or [`LengthU32`] for 0, 8, 16, and
17/// 32 bit length fields, respectively.
18///
19/// # Examples
20///
21/// ```rust
22/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
23/// use rsomeip_bytes::{Deserialize as _, DynamicArray, LengthU32, Serialize as _};
24///
25/// // Works on any value that implements `IntoIterator`.
26/// let value = vec![1, 2, 3, 4, 5];
27///
28/// // Specify the size of the length field in the generic parameters. It will be included when
29/// // serializing the value.
30/// let array = DynamicArray::<LengthU32, _>::from(&value);
31///
32/// // The array also implements the `Serialize` trait.
33/// let mut bytes = array.to_bytes()?;
34///
35/// // And `Deserialize`, as well.
36/// let output = DynamicArray::<LengthU32, Vec<i32>>::deserialize(&mut bytes)?;
37/// assert_eq!(value, output);
38/// # Ok(()) }
39/// ```
40///
41/// [`Vec<T>`]: alloc::vec::Vec
42/// [`BTreeMap<K, V>`]: alloc::collections::BTreeMap
43/// [`LengthZero`]: crate::LengthZero
44/// [`LengthU8`]: crate::LengthU8
45/// [`LengthU16`]: crate::LengthU16
46/// [`LengthU32`]: crate::LengthU32
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48#[must_use = "must call `serialize` on this array"]
49pub struct DynamicArray<Length, Collection> {
50    /// Collection to serialize.
51    inner: Collection,
52    /// Length to include before the value.
53    _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                // Serialize each item of the array individually and add up the results.
83                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                // Add up the size of each element in the array.
90                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        // Add up the size of each element in the array plus the size of the length field.
101        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                // First error encountered during deserialization.
124                let mut error: Option<DeserializeError> = None;
125                let collection = iter::from_fn(|| {
126                    // Deserialize one item at a time.
127                    if error.is_none() && buffer.has_remaining() {
128                        Collection::Item::deserialize(buffer)
129                            .map_err(|err| {
130                                // Record the error.
131                                error = Some(err);
132                            })
133                            .ok()
134                    } else {
135                        None
136                    }
137                })
138                .collect();
139                // Return the first error or the collection if none was encountered.
140                error.map_or_else(|| Ok(collection), Err)
141            },
142            buffer,
143        )
144    }
145
146    fn size_hint() -> Option<usize> {
147        // Only the size of the length field is known at compile time.
148        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}