Skip to main content

rsomeip_bytes/
de.rs

1//! Deserialization according to the SOME/IP protocol.
2//!
3//! Provides the [`Deserialize`] trait for deserializing data, and several implementations of this
4//! trait for types of the standard library.
5
6use crate::{Buf, Bytes};
7use alloc::{borrow::Cow, boxed::Box, rc::Rc, sync::Arc};
8use core::array;
9
10/// Deserialize data from a SOME/IP byte stream.
11pub trait Deserialize {
12    /// Type of the deserialized data.
13    type Output: Sized;
14
15    /// Deserializes an instance of [`Deserialize::Output`] from the buffer.
16    ///
17    /// # Errors
18    ///
19    /// Returns a [`DeserializeError`] if the deserialization fails.
20    ///
21    /// # Examples
22    ///
23    /// ```rust
24    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
25    /// use rsomeip_bytes::{Deserialize as _};
26    ///
27    /// // The buffer can be any type that implements `Buf`.
28    /// let buffer = [0x12_u8, 0x34];
29    ///
30    /// // Deserialize a type from the buffer.
31    /// let value = u16::deserialize(&mut buffer.as_slice())?;
32    /// assert_eq!(value, 0x1234);
33    /// # Ok(()) }
34    /// ```
35    ///
36    /// # Implementation notes
37    ///
38    /// Care should be taken so that the serialized data matches the interface definition and that
39    /// it's compatible with the SOME/IP on-wire format to prevent issues during deserialization.
40    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
41    where
42        Buffer: Buf + ?Sized;
43
44    /// Returns the minimum size of a correctly serialized [`Self::Output`].
45    ///
46    /// Deserialization is guaranteed to fail if the buffer doesn't contain at least this amount
47    /// of bytes.
48    ///
49    /// Having more than this amount of bytes in the buffer doesn't guarantee that deserialization
50    /// does succeed however, as the correct size of some types can only be known at runtime, but
51    /// it's guaranteed to be at least this value.
52    ///
53    /// Returns [`None`] if the size is larger than [`usize::MAX`].
54    ///
55    /// # Examples
56    ///
57    /// ```rust
58    /// use rsomeip_bytes::{Deserialize as _};
59    ///
60    /// // Basic types match the in-memory size.
61    /// assert_eq!(u8::size_hint(), Some(1));
62    /// assert_eq!(u16::size_hint(), Some(2));
63    /// assert_eq!(u32::size_hint(), Some(4));
64    /// ```
65    ///
66    /// # Implementation notes
67    ///
68    /// The value returned by this method should include the size of all statically known elements
69    /// of [`Self::Output`].
70    #[must_use]
71    fn size_hint() -> Option<usize>;
72}
73
74/// Error when deserializing data.
75#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
76#[non_exhaustive]
77pub enum DeserializeError {
78    /// There is insufficient data in the buffer to deserialize the complete type.
79    #[error("insufficient data in buffer")]
80    InsufficientData,
81    /// An invariant of the deserialized type wasn't upheld.
82    #[error("invariant failed: {0}")]
83    InvariantFailed(Cow<'static, str>),
84    /// Value of the length field exceeds [`usize::MAX`].
85    #[error("length exceeds usize::MAX")]
86    LengthOverflow,
87}
88
89impl DeserializeError {
90    /// Creates a new [`DeserializeError::InvariantFailed`] with the given `message`.
91    ///
92    /// # Examples
93    ///
94    /// ```rust
95    /// use rsomeip_bytes::DeserializeError;
96    ///
97    /// // Can use static error messages.
98    /// let borrowed = DeserializeError::invariant("generic error");
99    /// assert_eq!(borrowed.to_string(), "invariant failed: generic error");
100    ///
101    /// // Or dynamic error messages.
102    /// let owned = DeserializeError::invariant(format!("specific error: {}", 42));
103    /// assert_eq!(owned.to_string(), "invariant failed: specific error: 42");
104    /// ```
105    #[inline]
106    #[must_use]
107    pub fn invariant(message: impl Into<Cow<'static, str>>) -> Self {
108        Self::InvariantFailed(message.into())
109    }
110}
111
112/// Implements [`Deserialize`] for smart pointers.
113macro_rules! impl_deserialize_ptr {
114    ($name:ty) => {
115        impl<T> Deserialize for $name
116        where
117            T: Deserialize<Output = T>,
118            $name: From<T>,
119        {
120            type Output = $name;
121
122            fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
123            where
124                Buffer: Buf + ?Sized,
125            {
126                T::deserialize(buffer).map(<$name>::from)
127            }
128
129            fn size_hint() -> Option<usize> {
130                T::size_hint()
131            }
132        }
133    };
134}
135
136impl_deserialize_ptr!(Box<T>);
137impl_deserialize_ptr!(Rc<T>);
138impl_deserialize_ptr!(Arc<T>);
139
140/// Implements [`Deserialize`] for a tuple.
141///
142/// Elements are deserialized by the order that they appear in the tuple. The size hint is the sum
143/// of the size hint of each individual element.
144macro_rules! impl_deserialize_tuple {
145    ( $( $name:ident )+ ) => {
146        impl<$($name: Deserialize<Output=$name>),+> Deserialize for ($($name,)+) {
147            type Output = Self;
148            fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
149                where Buffer: Buf + ?Sized
150            {
151                Ok((
152                    $($name::deserialize(buffer)?,)+
153                ))
154            }
155
156            fn size_hint() -> Option<usize> {
157                Some(0_usize)
158                $(
159                    .and_then(|total| {
160                        <$name>::size_hint().and_then(|size| total.checked_add(size))
161                    })
162                )+
163            }
164        }
165    };
166}
167
168impl_deserialize_tuple! { A }
169impl_deserialize_tuple! { A B }
170impl_deserialize_tuple! { A B C }
171impl_deserialize_tuple! { A B C D }
172impl_deserialize_tuple! { A B C D E }
173impl_deserialize_tuple! { A B C D E F }
174impl_deserialize_tuple! { A B C D E F G }
175impl_deserialize_tuple! { A B C D E F G H }
176impl_deserialize_tuple! { A B C D E F G H I }
177impl_deserialize_tuple! { A B C D E F G H I J }
178impl_deserialize_tuple! { A B C D E F G H I J K }
179impl_deserialize_tuple! { A B C D E F G H I J K L }
180
181/// Implements [`Deserialize`] for a basic type.
182macro_rules! impl_deserialize_basic_type {
183    ($name:ty, $try_get:ident) => {
184        impl Deserialize for $name {
185            type Output = Self;
186
187            fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
188            where
189                Buffer: Buf + ?Sized,
190            {
191                buffer
192                    .$try_get()
193                    .map_err(|_err| DeserializeError::InsufficientData)
194            }
195
196            /// Returns the size of `self` when serialized.
197            ///
198            /// Never returns [`None`].
199            fn size_hint() -> Option<usize> {
200                Some(size_of::<$name>())
201            }
202        }
203    };
204}
205
206impl_deserialize_basic_type!(u8, try_get_u8);
207impl_deserialize_basic_type!(u16, try_get_u16);
208impl_deserialize_basic_type!(u32, try_get_u32);
209impl_deserialize_basic_type!(u64, try_get_u64);
210impl_deserialize_basic_type!(i8, try_get_i8);
211impl_deserialize_basic_type!(i16, try_get_i16);
212impl_deserialize_basic_type!(i32, try_get_i32);
213impl_deserialize_basic_type!(i64, try_get_i64);
214impl_deserialize_basic_type!(f32, try_get_f32);
215impl_deserialize_basic_type!(f64, try_get_f64);
216
217impl Deserialize for bool {
218    type Output = Self;
219
220    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
221    where
222        Buffer: Buf + ?Sized,
223    {
224        // Only check the first bit.
225        u8::deserialize(buffer).map(|value| (value & 0x01) == 0x01)
226    }
227
228    fn size_hint() -> Option<usize> {
229        Some(1)
230    }
231}
232
233// TODO(brunoldsilva): drop the `Default` bound when `array::try_from_fn` stabilizes.
234impl<T, const N: usize> Deserialize for [T; N]
235where
236    T: Deserialize<Output = T> + Default,
237{
238    type Output = Self;
239
240    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
241    where
242        Buffer: Buf + ?Sized,
243    {
244        // First error found during deserialization.
245        let mut error: Option<DeserializeError> = None;
246        // Deserialize the elements into an array. Use defaults in case of an error.
247        let array = array::from_fn(|_| {
248            if error.is_none() {
249                T::deserialize(buffer)
250                    .map_err(|err| {
251                        error = Some(err);
252                    })
253                    .unwrap_or_default()
254            } else {
255                T::default()
256            }
257        });
258        // Return the array or the first error that occurred.
259        error.map_or_else(|| Ok(array), Err)
260    }
261
262    fn size_hint() -> Option<usize> {
263        T::size_hint().and_then(|size| size.checked_mul(N))
264    }
265}
266
267impl Deserialize for Bytes {
268    type Output = Self;
269
270    fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
271    where
272        Buffer: Buf + ?Sized,
273    {
274        Ok(buffer.copy_to_bytes(buffer.remaining()))
275    }
276
277    fn size_hint() -> Option<usize> {
278        Some(0)
279    }
280}
281
282#[cfg(test)]
283#[expect(clippy::inline_modules, reason = "rust-clippy#17342")]
284mod tests {
285    use super::*;
286    use bytes::Bytes;
287
288    /// Tests the [`Deserialize`] implementation of a basic type.
289    ///
290    /// It checks if the value `1` can be deserialized from a buffer, and if an error is returned
291    /// from an empty buffer.
292    macro_rules! test_deserialize_basic_type {
293        ($t:ty, $name:tt) => {
294            #[test]
295            fn $name() {
296                assert_eq!(<$t>::size_hint(), Some(size_of::<$t>()));
297                let value = <$t>::try_from(1_u8).expect("1_u8 fits in every other basic type");
298                let buffer = value.to_be_bytes();
299                let mut cursor = buffer.as_slice();
300                assert_eq!(<$t>::deserialize(&mut cursor), Ok(value));
301                assert_eq!(
302                    <$t>::deserialize(&mut cursor),
303                    Err(DeserializeError::InsufficientData)
304                );
305            }
306        };
307    }
308
309    test_deserialize_basic_type!(u8, deserialize_u8);
310    test_deserialize_basic_type!(u16, deserialize_u16);
311    test_deserialize_basic_type!(u32, deserialize_u32);
312    test_deserialize_basic_type!(u64, deserialize_u64);
313    test_deserialize_basic_type!(i8, deserialize_i8);
314    test_deserialize_basic_type!(i16, deserialize_i16);
315    test_deserialize_basic_type!(i32, deserialize_i32);
316    test_deserialize_basic_type!(i64, deserialize_i64);
317    test_deserialize_basic_type!(f32, deserialize_f32);
318    test_deserialize_basic_type!(f64, deserialize_f64);
319
320    #[test]
321    fn deserialize_bool() {
322        assert_eq!(bool::size_hint(), Some(size_of::<u8>()));
323        let mut buffer = Bytes::copy_from_slice(&[0_u8, 1_u8]);
324        assert_eq!(bool::deserialize(&mut buffer), Ok(false));
325        assert_eq!(bool::deserialize(&mut buffer), Ok(true));
326        assert_eq!(
327            bool::deserialize(&mut buffer),
328            Err(DeserializeError::InsufficientData)
329        );
330    }
331
332    #[test]
333    fn deserialize_array() {
334        assert_eq!(<[u8; 2]>::size_hint(), Some(size_of::<u16>()));
335        let mut buffer = Bytes::copy_from_slice(&[1_u8, 2_u8]);
336        assert_eq!(<[u8; 2]>::deserialize(&mut buffer), Ok([1_u8, 2_u8]));
337        assert_eq!(
338            <[u8; 2]>::deserialize(&mut buffer),
339            Err(DeserializeError::InsufficientData)
340        );
341    }
342
343    #[test]
344    fn deserialize_tuple() {
345        assert_eq!(<(u8, u8)>::size_hint(), Some(size_of::<u16>()));
346        let mut buffer = Bytes::copy_from_slice(&[1_u8, 2_u8]);
347        assert_eq!(<(u8, u8)>::deserialize(&mut buffer), Ok((1_u8, 2_u8)));
348        assert_eq!(
349            <(u8, u8)>::deserialize(&mut buffer),
350            Err(DeserializeError::InsufficientData)
351        );
352    }
353
354    #[test]
355    fn deserialize_bytes() {
356        assert_eq!(Bytes::size_hint(), Some(0));
357        let mut buffer = Bytes::copy_from_slice(&[1_u8, 2]);
358        let output = Bytes::deserialize(&mut buffer).expect("should deserialize the bytes");
359        assert_eq!(output, [1_u8, 2].as_slice());
360    }
361
362    #[test]
363    fn deserialize_box() {
364        assert_eq!(Box::<u16>::size_hint(), u16::size_hint());
365        let mut buffer = Bytes::copy_from_slice(&[1_u8, 2]);
366        let output = Box::<u16>::deserialize(&mut buffer).expect("should deserialize the Box");
367        assert_eq!(*output, 0x0102_u16);
368    }
369}