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 into 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(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(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(feature = "alloc")]
153#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
154pub mod owned {
155    //! Traits for encoding `SMPP` values using a bytes buffer.
156
157    use bytes::BytesMut;
158
159    use super::Length;
160
161    /// Trait for encoding `SMPP` values into a buffer.
162    ///
163    /// # Implementation
164    ///
165    /// ```rust
166    /// # use bytes::BytesMut;
167    /// # use rusmpp_core::encode::{owned::Encode, Length};
168    ///
169    /// struct Foo {
170    ///     a: u8,
171    ///     b: u16,
172    ///     c: u32,
173    /// }
174    ///
175    /// impl Length for Foo {
176    ///     fn length(&self) -> usize {
177    ///         self.a.length() + self.b.length() + self.c.length()
178    ///     }
179    /// }
180    ///
181    /// impl Encode for Foo {
182    ///     fn encode(&self, dst: &mut BytesMut) {
183    ///         self.a.encode(dst);
184    ///         self.b.encode(dst);
185    ///         self.c.encode(dst);
186    ///     }
187    /// }
188    ///
189    /// let foo = Foo {
190    ///     a: 0x01,
191    ///     b: 0x0203,
192    ///     c: 0x04050607,
193    /// };
194    ///
195    /// let mut buf = BytesMut::with_capacity(1024);
196    ///
197    /// assert!(buf.capacity() >= foo.length());
198    ///
199    /// foo.encode(&mut buf);
200    ///
201    /// let expected = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
202    ///
203    /// let buf = buf.split_to(foo.length());
204    ///
205    /// assert_eq!(&buf[..], expected);
206    /// ```
207    pub trait Encode: Length {
208        /// Encode a value into a destination buffer.
209        ///
210        /// Implementors are allowed to panic if the slice is not big enough to hold the encoded value. If `dst.capacity()` < [`Length::length`]
211        fn encode(&self, dst: &mut BytesMut);
212    }
213
214    impl<T: Encode> Encode for Option<T> {
215        fn encode(&self, dst: &mut BytesMut) {
216            if let Some(item) = self.as_ref() {
217                item.encode(dst)
218            }
219        }
220    }
221
222    impl<T: Encode> Encode for &[T] {
223        fn encode(&self, dst: &mut BytesMut) {
224            for item in *self {
225                item.encode(dst);
226            }
227        }
228    }
229
230    impl<T: Encode> Encode for alloc::vec::Vec<T> {
231        fn encode(&self, dst: &mut BytesMut) {
232            self.as_slice().encode(dst)
233        }
234    }
235
236    impl<T: Encode, const N: usize> Encode for heapless::vec::Vec<T, N> {
237        fn encode(&self, dst: &mut BytesMut) {
238            self.as_slice().encode(dst)
239        }
240    }
241}
242
243#[cfg(test)]
244mod tests {
245    mod borrowed {
246
247        use super::super::*;
248
249        #[test]
250        fn length_option() {
251            let value: Option<u8> = Some(0u8);
252            assert_eq!(value.length(), 1);
253
254            let value: Option<u8> = None;
255            assert_eq!(value.length(), 0);
256        }
257
258        #[test]
259        fn encode_option() {
260            let buf = &mut [0u8; 1024];
261            let value: Option<u8> = Some(0u8);
262            assert!(buf.len() >= value.length());
263            let size = value.encode(buf);
264            assert_eq!(size, 1);
265            assert_eq!(&buf[..size], &[0]);
266
267            let value: Option<u8> = None;
268            assert!(buf.len() >= value.length());
269            let size = value.encode(buf);
270            assert_eq!(size, 0);
271        }
272
273        #[cfg(feature = "alloc")]
274        mod owned_extensions {
275            use crate::types::borrowed::{
276                AnyOctetString, COctetString, EmptyOrFullCOctetString, OctetString,
277            };
278
279            use super::*;
280
281            #[test]
282            fn length_vec() {
283                let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
284                assert_eq!(values.length(), 10);
285
286                let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
287                assert_eq!(values.length(), 20);
288
289                let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
290                assert_eq!(values.length(), 40);
291
292                let values =
293                    alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
294                assert_eq!(values.length(), 10);
295
296                let values = alloc::vec![
297                    COctetString::<1, 6>::new(b"Hello\0").unwrap(),
298                    COctetString::<1, 6>::new(b"World\0").unwrap(),
299                ];
300                assert_eq!(values.length(), 12);
301
302                let values = alloc::vec![
303                    EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
304                    EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
305                ];
306                assert_eq!(values.length(), 12);
307
308                let values = alloc::vec![
309                    OctetString::<0, 5>::new(b"Hello").unwrap(),
310                    OctetString::<0, 5>::new(b"World").unwrap(),
311                ];
312                assert_eq!(values.length(), 10);
313            }
314
315            #[test]
316            fn encode_vec() {
317                let buf = &mut [0u8; 1024];
318
319                let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
320                assert!(buf.len() >= values.length());
321                let size = values.encode(buf);
322                assert_eq!(size, 10);
323                assert_eq!(&buf[..size], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
324
325                let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
326                assert!(buf.len() >= values.length());
327                let size = values.encode(buf);
328                assert_eq!(size, 20);
329                assert_eq!(
330                    &buf[..size],
331                    &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9]
332                );
333
334                let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
335                assert!(buf.len() >= values.length());
336                let size = values.encode(buf);
337                assert_eq!(size, 40);
338                assert_eq!(
339                    &buf[..size],
340                    &[
341                        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,
342                        0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9
343                    ]
344                );
345
346                let values =
347                    alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
348                assert!(buf.len() >= values.length());
349                let size = values.encode(buf);
350                assert_eq!(size, 10);
351                assert_eq!(&buf[..size], b"HelloWorld");
352
353                let values = alloc::vec![
354                    COctetString::<1, 6>::new(b"Hello\0").unwrap(),
355                    COctetString::<1, 6>::new(b"World\0").unwrap(),
356                ];
357                assert!(buf.len() >= values.length());
358                let size = values.encode(buf);
359                assert_eq!(size, 12);
360                assert_eq!(&buf[..size], b"Hello\0World\0");
361
362                let values = alloc::vec![
363                    EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
364                    EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
365                ];
366                assert!(buf.len() >= values.length());
367                let size = values.encode(buf);
368                assert_eq!(size, 12);
369                assert_eq!(&buf[..size], b"Hello\0World\0");
370
371                let values = alloc::vec![
372                    OctetString::<0, 5>::new(b"Hello").unwrap(),
373                    OctetString::<0, 5>::new(b"World").unwrap(),
374                ];
375                assert!(buf.len() >= values.length());
376                let size = values.encode(buf);
377                assert_eq!(size, 10);
378                assert_eq!(&buf[..size], b"HelloWorld");
379            }
380        }
381    }
382
383    #[cfg(feature = "alloc")]
384    mod owned {
385        use bytes::BytesMut;
386
387        use crate::types::owned::{
388            AnyOctetString, COctetString, EmptyOrFullCOctetString, OctetString,
389        };
390
391        use super::super::{Length, owned::Encode};
392
393        #[test]
394        fn encode_option() {
395            let mut buf = BytesMut::with_capacity(1024);
396            let value: Option<u8> = Some(0u8);
397            assert!(buf.capacity() >= value.length());
398            value.encode(&mut buf);
399            assert_eq!(buf.len(), 1);
400            assert_eq!(&buf[..1], &[0]);
401
402            let mut buf = BytesMut::with_capacity(1024);
403            let value: Option<u8> = None;
404            assert!(buf.capacity() >= value.length());
405            value.encode(&mut buf);
406            assert_eq!(buf.len(), 0);
407        }
408
409        #[test]
410        fn encode_vec() {
411            let mut buf = BytesMut::with_capacity(1024);
412            let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
413            assert!(buf.capacity() >= values.length());
414            values.encode(&mut buf);
415            assert_eq!(buf.len(), 10);
416            assert_eq!(&buf[..10], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
417
418            let mut buf = BytesMut::with_capacity(1024);
419            let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
420            assert!(buf.capacity() >= values.length());
421            values.encode(&mut buf);
422            assert_eq!(buf.len(), 20);
423            assert_eq!(
424                &buf[..20],
425                &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9]
426            );
427
428            let mut buf = BytesMut::with_capacity(1024);
429            let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
430            assert!(buf.capacity() >= values.length());
431            values.encode(&mut buf);
432            assert_eq!(buf.len(), 40);
433            assert_eq!(
434                &buf[..40],
435                &[
436                    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,
437                    0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9
438                ]
439            );
440
441            let mut buf = BytesMut::with_capacity(1024);
442            let values = alloc::vec![
443                AnyOctetString::from_static_slice(b"Hello"),
444                AnyOctetString::from_static_slice(b"World")
445            ];
446            assert!(buf.capacity() >= values.length());
447            values.encode(&mut buf);
448            assert_eq!(buf.len(), 10);
449            assert_eq!(&buf[..10], b"HelloWorld");
450
451            let mut buf = BytesMut::with_capacity(1024);
452            let values = alloc::vec![
453                COctetString::<1, 6>::from_static_slice(b"Hello\0").unwrap(),
454                COctetString::<1, 6>::from_static_slice(b"World\0").unwrap(),
455            ];
456            assert!(buf.capacity() >= values.length());
457            values.encode(&mut buf);
458            assert_eq!(buf.len(), 12);
459            assert_eq!(&buf[..12], b"Hello\0World\0");
460
461            let mut buf = BytesMut::with_capacity(1024);
462            let values = alloc::vec![
463                EmptyOrFullCOctetString::<6>::from_static_slice(b"Hello\0").unwrap(),
464                EmptyOrFullCOctetString::<6>::from_static_slice(b"World\0").unwrap(),
465            ];
466            assert!(buf.capacity() >= values.length());
467            values.encode(&mut buf);
468            assert_eq!(buf.len(), 12);
469            assert_eq!(&buf[..12], b"Hello\0World\0");
470
471            let mut buf = BytesMut::with_capacity(1024);
472            let values = alloc::vec![
473                OctetString::<0, 5>::from_static_slice(b"Hello").unwrap(),
474                OctetString::<0, 5>::from_static_slice(b"World").unwrap(),
475            ];
476            assert!(buf.capacity() >= values.length());
477            values.encode(&mut buf);
478            assert_eq!(buf.len(), 10);
479            assert_eq!(&buf[..10], b"HelloWorld");
480        }
481    }
482}