rsomeip_bytes/
macros.rs

1/// Serializes a series of variables into the given `buffer`.
2///
3/// An optional `length` parameter can be specified to serialize the variables using [`serialize_len`].
4///
5/// # Performance Considerations
6///
7/// This macro is provided simply as a convenience for implementing the [`Serialize`] trait.
8///
9/// It uses tuples to serialize the variables into the buffer, which may not work well in every
10/// situation.
11///
12/// # Examples
13///
14/// ```rust
15/// use rsomeip_bytes::{BytesMut, Serialize, serialize_into};
16///
17/// let [a, b, c, d] = [1u8, 2, 3, 4];
18/// let mut buffer = BytesMut::new();
19///
20/// let mut size = 0;
21/// size += serialize_into!(&mut buffer, a, b).expect("should serialize");
22/// size += serialize_into!(&mut buffer, length = U8, c, d).expect("should serialize");
23///
24/// assert_eq!(size, 5);
25/// assert_eq!(buffer[..], [1u8, 2, 2, 3, 4]);
26/// ```
27///
28/// [`Serialize`]: crate::Serialize
29/// [`serialize_len`]: crate::Serialize::serialize_len
30#[macro_export]
31macro_rules! serialize_into {
32    ($buffer:expr, length=$length:ident, $($member:expr),+) => {
33        (
34            $($member,)+
35        ).serialize_len($crate::LengthField::$length, $buffer)
36    };
37    ($buffer:expr, $($member:expr),+) => {
38        (
39            $($member,)+
40        ).serialize($buffer)
41    };
42}
43
44/// Returns the combined size hint of a series of variables.
45///
46/// An optional `length` parameter can be specified to include a length field in the size
47/// calculations.
48///
49/// # Examples
50///
51/// ```rust
52/// use rsomeip_bytes::{Serialize, size_hint};
53///
54/// let [a, b, c, d] = [1u8, 2, 3, 4];
55///
56/// let mut size = 0;
57/// size += size_hint!(a, b);
58/// size += size_hint!(length = U32, c, d);
59/// assert_eq!(size, 8);
60/// ```
61#[macro_export]
62macro_rules! size_hint {
63    (length=$length:ident, $($member:expr),+) => {{
64        let mut size = 0;
65        size += (|length: $crate::LengthField| {
66                match length {
67                    $crate::LengthField::U8 => 0u8.size_hint(),
68                    $crate::LengthField::U16 => 0u16.size_hint(),
69                    $crate::LengthField::U32 => 0u32.size_hint(),
70                }
71            })($crate::LengthField::$length);
72        $(size += $member.size_hint();)+
73        size
74    }};
75    ($($member:expr),+) => {{
76        let mut size = 0;
77        $(size += $member.size_hint();)+
78        size
79    }};
80}
81
82/// Deserializes a series of variables from the given `buffer`.
83///
84/// An optional `length` parameter can be specified to deserialize the variables using
85/// [`deserialize_len`].
86///
87/// # Performance Considerations
88///
89/// This macro is provided simply as a convenience for implementing the [`Deserialize`] trait.
90///
91/// It uses tuples to deserialize the variables from the buffer, which may not be the most performant
92/// solution for every use case, but is one that works well in most situations.
93///
94/// # Examples
95///
96/// ```rust
97/// use rsomeip_bytes::{Bytes, Deserialize, deserialize_from};
98///
99/// let mut buffer = Bytes::copy_from_slice(&[1u8, 2, 2, 3, 4][..]);
100///
101/// let (a, b) = deserialize_from!(&mut buffer, u8, u8).expect("should deserialize");
102/// let (c, d) = deserialize_from!(&mut buffer, length = U8, u8, u8).expect("should deserialize");
103///
104/// assert_eq!([a, b, c, d], [1u8, 2, 3, 4]);
105/// ```
106///
107/// [`Deserialize`]: crate::Deserialize
108/// [`deserialize_len`]: crate::Deserialize::deserialize_len
109#[macro_export]
110macro_rules! deserialize_from {
111    ($buffer:expr, length=$length:ident, $($repr:ty),+) => {
112        <(
113            $($repr),+
114        )>::deserialize_len($crate::LengthField::$length, $buffer)
115    };
116    ($buffer:expr, $($repr:ty),+) => {
117        <(
118            $($repr),+
119        )>::deserialize($buffer)
120    };
121}
122
123#[cfg(test)]
124mod tests {
125    use crate::{Deserialize, Serialize};
126    use bytes::{Bytes, BytesMut};
127
128    #[test]
129    fn serialize_macro() {
130        let [a, b, c, d] = [1u8, 2, 3, 4];
131        let mut buffer = BytesMut::new();
132        let mut size = 0;
133        size += serialize_into!(&mut buffer, &a, b).expect("should serialize");
134        size += serialize_into!(&mut buffer, length = U8, &c, d).expect("should serialize");
135        assert_eq!(size, 5);
136        assert_eq!(buffer[..], [1u8, 2, 2, 3, 4]);
137    }
138
139    #[test]
140    fn size_hint_macro() {
141        let [a, b, c, d] = [1u8, 2, 3, 4];
142        let mut size = 0;
143        size += size_hint!(&a, b);
144        size += size_hint!(length = U32, &c, d);
145        assert_eq!(size, 8);
146    }
147
148    #[test]
149    fn deserialize_macro() {
150        let mut buffer = Bytes::copy_from_slice(&[1u8, 2, 2, 3, 4][..]);
151        let (a, b) = deserialize_from!(&mut buffer, u8, u8).expect("should deserialize");
152        let (c, d) =
153            deserialize_from!(&mut buffer, length = U8, u8, u8).expect("should deserialize");
154        assert_eq!([a, b, c, d], [1u8, 2, 3, 4]);
155    }
156}