rusmpp_core/
encode.rs

1//! Traits for encoding `SMPP` values.
2
3/// Trait for determining the length of `SMPP` values.
4///
5/// # Implementation
6///
7/// ```rust
8/// # use rusmpp_core::encode::{Encode, Length};
9///
10/// struct Foo {
11///     a: u8,
12///     b: u16,
13///     c: u32,
14/// }
15///
16/// impl Length for Foo {
17///     fn length(&self) -> usize {
18///         self.a.length() + self.b.length() + self.c.length()
19///     }
20/// }
21///
22/// let foo = Foo {
23///     a: 0x01,
24///     b: 0x0203,
25///     c: 0x04050607,
26/// };
27///
28///
29/// assert_eq!(foo.length(), 7);
30/// ```
31pub trait Length {
32    fn length(&self) -> usize;
33}
34
35/// Trait for encoding `SMPP` values into a slice.
36///
37/// # Implementation
38///
39/// ```rust
40/// # use rusmpp_core::encode::{Encode, Length};
41///
42/// struct Foo {
43///     a: u8,
44///     b: u16,
45///     c: u32,
46/// }
47///
48/// impl Length for Foo {
49///     fn length(&self) -> usize {
50///         self.a.length() + self.b.length() + self.c.length()
51///     }
52/// }
53///
54/// impl Encode for Foo {
55///     fn encode(&self, dst: &mut [u8]) -> usize {
56///         let mut size = 0;
57///
58///         size += self.a.encode(&mut dst[size..]);
59///         size += self.b.encode(&mut dst[size..]);
60///         size += self.c.encode(&mut dst[size..]);
61///
62///         size
63///     }
64/// }
65///
66/// let foo = Foo {
67///     a: 0x01,
68///     b: 0x0203,
69///     c: 0x04050607,
70/// };
71///
72/// let buf = &mut [0u8; 1024];
73///
74/// assert!(buf.len() >= foo.length());
75///
76/// let size = foo.encode(buf);
77///
78/// let expected = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
79///
80/// assert_eq!(size, 7);
81/// assert_eq!(&buf[..size], expected);
82/// ```
83pub trait Encode: Length {
84    /// Encode a value to a slice
85    ///
86    /// Implementors are allowed to panic if the slice is not big enough to hold the encoded value. If `dst.len()` < [`Length::length`]
87    fn encode(&self, dst: &mut [u8]) -> usize;
88}
89
90#[doc(hidden)]
91pub trait EncodeExt: Encode {
92    fn encode_move(&self, dst: &mut [u8], size: usize) -> usize {
93        size + self.encode(&mut dst[size..])
94    }
95}
96
97impl<T: Encode> EncodeExt for T {}
98
99impl<T: Length> Length for Option<T> {
100    fn length(&self) -> usize {
101        self.as_ref().map(Length::length).unwrap_or(0)
102    }
103}
104
105impl<T: Length> Length for &[T] {
106    fn length(&self) -> usize {
107        self.iter().map(Length::length).sum()
108    }
109}
110
111#[cfg(any(test, feature = "alloc"))]
112#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
113impl<T: Length> Length for alloc::vec::Vec<T> {
114    fn length(&self) -> usize {
115        self.as_slice().length()
116    }
117}
118
119impl<T: Length, const N: usize> Length for heapless::vec::Vec<T, N> {
120    fn length(&self) -> usize {
121        self.as_slice().length()
122    }
123}
124
125impl<T: Encode> Encode for Option<T> {
126    fn encode(&self, dst: &mut [u8]) -> usize {
127        self.as_ref().map(|item| item.encode(dst)).unwrap_or(0)
128    }
129}
130
131impl<T: Encode> Encode for &[T] {
132    fn encode(&self, dst: &mut [u8]) -> usize {
133        self.iter()
134            .fold(0, |acc, item| acc + item.encode(&mut dst[acc..]))
135    }
136}
137
138#[cfg(any(test, feature = "alloc"))]
139#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
140impl<T: Encode> Encode for alloc::vec::Vec<T> {
141    fn encode(&self, dst: &mut [u8]) -> usize {
142        self.as_slice().encode(dst)
143    }
144}
145
146impl<T: Encode, const N: usize> Encode for heapless::vec::Vec<T, N> {
147    fn encode(&self, dst: &mut [u8]) -> usize {
148        self.as_slice().encode(dst)
149    }
150}
151
152#[cfg(test)]
153mod tests {
154    use super::*;
155
156    mod owned {
157        use crate::types::owned::{
158            AnyOctetString, COctetString, EmptyOrFullCOctetString, OctetString,
159        };
160
161        use super::*;
162
163        #[test]
164        fn length_option() {
165            let value: Option<u8> = Some(0u8);
166            assert_eq!(value.length(), 1);
167
168            let value: Option<u8> = None;
169            assert_eq!(value.length(), 0);
170        }
171
172        #[test]
173        fn length_vec() {
174            let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
175            assert_eq!(values.length(), 10);
176
177            let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
178            assert_eq!(values.length(), 20);
179
180            let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
181            assert_eq!(values.length(), 40);
182
183            let values = alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
184            assert_eq!(values.length(), 10);
185
186            let values = alloc::vec![
187                COctetString::<1, 6>::new(b"Hello\0").unwrap(),
188                COctetString::<1, 6>::new(b"World\0").unwrap(),
189            ];
190            assert_eq!(values.length(), 12);
191
192            let values = alloc::vec![
193                EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
194                EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
195            ];
196            assert_eq!(values.length(), 12);
197
198            let values = alloc::vec![
199                OctetString::<0, 5>::new(b"Hello").unwrap(),
200                OctetString::<0, 5>::new(b"World").unwrap(),
201            ];
202            assert_eq!(values.length(), 10);
203        }
204
205        #[test]
206        fn encode_option() {
207            let buf = &mut [0u8; 1024];
208
209            let value: Option<u8> = Some(0u8);
210            assert!(buf.len() >= value.length());
211
212            let size = value.encode(buf);
213
214            assert_eq!(size, 1);
215            assert_eq!(&buf[..size], &[0]);
216
217            let value: Option<u8> = None;
218            assert!(buf.len() >= value.length());
219
220            let size = value.encode(buf);
221
222            assert_eq!(size, 0);
223        }
224
225        #[test]
226        fn encode_vec() {
227            let buf = &mut [0u8; 1024];
228
229            let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
230            assert!(buf.len() >= values.length());
231
232            let size = values.encode(buf);
233
234            assert_eq!(size, 10);
235            assert_eq!(&buf[..size], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
236
237            let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
238            assert!(buf.len() >= values.length());
239
240            let size = values.encode(buf);
241
242            assert_eq!(size, 20);
243            assert_eq!(
244                &buf[..size],
245                &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9]
246            );
247
248            let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
249            assert!(buf.len() >= values.length());
250
251            let size = values.encode(buf);
252            assert_eq!(size, 40);
253
254            assert_eq!(
255                &buf[..size],
256                &[
257                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0,
258                    0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9
259                ]
260            );
261
262            let values = alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
263            assert!(buf.len() >= values.length());
264
265            let size = values.encode(buf);
266
267            assert_eq!(size, 10);
268            assert_eq!(&buf[..size], b"HelloWorld");
269
270            let values = alloc::vec![
271                COctetString::<1, 6>::new(b"Hello\0").unwrap(),
272                COctetString::<1, 6>::new(b"World\0").unwrap(),
273            ];
274            assert!(buf.len() >= values.length());
275
276            let size = values.encode(buf);
277
278            assert_eq!(size, 12);
279            assert_eq!(&buf[..size], b"Hello\0World\0");
280
281            let values = alloc::vec![
282                EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
283                EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
284            ];
285            assert!(buf.len() >= values.length());
286
287            let size = values.encode(buf);
288
289            assert_eq!(size, 12);
290            assert_eq!(&buf[..size], b"Hello\0World\0");
291
292            let values = alloc::vec![
293                OctetString::<0, 5>::new(b"Hello").unwrap(),
294                OctetString::<0, 5>::new(b"World").unwrap(),
295            ];
296            assert!(buf.len() >= values.length());
297
298            let size = values.encode(buf);
299
300            assert_eq!(size, 10);
301            assert_eq!(&buf[..size], b"HelloWorld");
302        }
303    }
304}