veecle_os_data_support_someip/
serialize.rs

1//! Trait for serializing SOME/IP data types.
2
3use core::marker::PhantomData;
4
5// Re-export the derive macro.
6pub use veecle_os_data_support_someip_macros::Serialize;
7
8use crate::length::LengthField;
9
10/// An error while serializing a SOME/IP payload type.
11#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
12pub enum SerializeError {
13    /// The payload slice has too few bytes to parse the SOME/IP payload type.
14    #[error("the writer buffer is too small")]
15    BufferTooSmall,
16    /// The capacity of the storage buffer is exceeded.
17    #[error("the capacity of the storage buffer too small")]
18    StorageBufferTooSmall,
19    /// The length of a dynamic structure is bigger than the length field can encode.
20    #[error("a length value is too big for the length field")]
21    LengthOverflow,
22    /// The minimum capacity of a dynamic type is subceeded.
23    #[error("the dynamic data type expected more data")]
24    DynamicTypeUnderflow,
25    /// The maximum capacity of a dynamic type is exceeded.
26    #[error("the capacity of the dynamic data type is too small")]
27    DynamicTypeOverflow,
28}
29
30/// Writes bytes to an underlying byte-slice.
31#[derive(Debug)]
32pub struct ByteWriter<'a> {
33    /// Slice of bytes the writer writes to.
34    buffer: &'a mut [u8],
35    /// Writer offset into the slice.
36    offset: usize,
37}
38
39impl<'a> ByteWriter<'a> {
40    /// Creates a new byte writer.
41    pub fn new(buffer: &'a mut [u8]) -> Self {
42        Self { buffer, offset: 0 }
43    }
44
45    /// Writes a single byte.
46    pub fn write_byte(&mut self, byte: u8) -> Result<(), SerializeError> {
47        if self.offset >= self.buffer.len() {
48            return Err(SerializeError::BufferTooSmall);
49        }
50
51        self.buffer[self.offset] = byte;
52        self.offset += 1;
53
54        Ok(())
55    }
56
57    /// Writes a slice of bytes.
58    pub fn write_slice(&mut self, slice: &[u8]) -> Result<(), SerializeError> {
59        let remaining = &mut self.buffer[self.offset..];
60
61        if remaining.len() < slice.len() {
62            return Err(SerializeError::BufferTooSmall);
63        }
64
65        remaining[..slice.len()].copy_from_slice(slice);
66        self.offset += slice.len();
67
68        Ok(())
69    }
70
71    /// Counts the number of bytes written inside the provided closure.
72    pub fn write_counted(
73        &mut self,
74        mut f: impl FnMut(&mut ByteWriter) -> Result<(), SerializeError>,
75    ) -> Result<usize, SerializeError> {
76        let offset_before = self.offset;
77
78        f(self)?;
79
80        let offset_after = self.offset;
81
82        Ok(offset_after.saturating_sub(offset_before))
83    }
84
85    /// Reserves a length field in the writer. Returns a handle that can be used to write the data later.
86    pub fn reserve_length<T>(&mut self) -> Result<ReservedLength<T>, SerializeError>
87    where
88        T: LengthField,
89    {
90        let remaining = &mut self.buffer[self.offset..];
91
92        if remaining.len() < core::mem::size_of::<T>() {
93            return Err(SerializeError::BufferTooSmall);
94        }
95
96        let offset = self.offset;
97        self.offset += core::mem::size_of::<T>();
98
99        Ok(ReservedLength {
100            offset,
101            _marker: PhantomData,
102        })
103    }
104
105    /// Writes the value of a reserved space.
106    pub fn write_length<T>(
107        &mut self,
108        reserved: ReservedLength<T>,
109        value: &T,
110    ) -> Result<(), SerializeError>
111    where
112        T: Serialize,
113    {
114        let mut reserved_writer =
115            ByteWriter::new(&mut self.buffer[reserved.offset..][..core::mem::size_of::<T>()]);
116
117        value.serialize_partial(&mut reserved_writer)
118    }
119}
120
121/// Represents the reserved space for a length field in the writer.
122#[derive(Debug)]
123pub struct ReservedLength<T> {
124    offset: usize,
125    _marker: PhantomData<T>,
126}
127
128/// A trait for serializing SOME/IP payload types to a slice of bytes.
129pub trait Serialize {
130    /// Returns the number of bytes required to store the serialized version of self.
131    fn required_length(&self) -> usize;
132
133    /// Serializes to a byte writer.
134    fn serialize_partial(&self, byte_writer: &mut ByteWriter) -> Result<(), SerializeError>;
135}
136
137/// An extension trait to expose a nicer API to the user.
138pub trait SerializeExt: Sized {
139    /// Serializes a SOME/IP payload type to a given slice of bytes using [`Serialize`] and returns the number of
140    /// bytes written to the buffer.
141    fn serialize<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a [u8], SerializeError>;
142}
143
144impl<T> SerializeExt for T
145where
146    T: Serialize,
147{
148    fn serialize<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a [u8], SerializeError> {
149        let mut writer = ByteWriter::new(buffer);
150        let written = writer.write_counted(|writer| self.serialize_partial(writer))?;
151        Ok(&buffer[..written])
152    }
153}