rusmpp/
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::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::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
90pub(crate) trait EncodeExt: Encode {
91    fn encode_move(&self, dst: &mut [u8], size: usize) -> usize {
92        size + self.encode(&mut dst[size..])
93    }
94}
95
96impl<T: Encode> EncodeExt for T {}
97
98impl<T: Length> Length for Option<T> {
99    fn length(&self) -> usize {
100        self.as_ref().map(Length::length).unwrap_or(0)
101    }
102}
103
104impl<T: Length> Length for alloc::vec::Vec<T> {
105    fn length(&self) -> usize {
106        self.iter().map(Length::length).sum()
107    }
108}
109
110impl<T: Encode> Encode for Option<T> {
111    fn encode(&self, dst: &mut [u8]) -> usize {
112        self.as_ref().map(|item| item.encode(dst)).unwrap_or(0)
113    }
114}
115
116impl<T: Encode> Encode for alloc::vec::Vec<T> {
117    fn encode(&self, dst: &mut [u8]) -> usize {
118        self.iter()
119            .fold(0, |acc, item| acc + item.encode(&mut dst[acc..]))
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use crate::types::{AnyOctetString, COctetString, EmptyOrFullCOctetString, OctetString};
126
127    use super::*;
128
129    #[test]
130    fn length_option() {
131        let value: Option<u8> = Some(0u8);
132        assert_eq!(value.length(), 1);
133
134        let value: Option<u8> = None;
135        assert_eq!(value.length(), 0);
136    }
137
138    #[test]
139    fn length_vec() {
140        let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
141        assert_eq!(values.length(), 10);
142
143        let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
144        assert_eq!(values.length(), 20);
145
146        let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
147        assert_eq!(values.length(), 40);
148
149        let values = alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
150        assert_eq!(values.length(), 10);
151
152        let values = alloc::vec![
153            COctetString::<1, 6>::new(b"Hello\0").unwrap(),
154            COctetString::<1, 6>::new(b"World\0").unwrap(),
155        ];
156        assert_eq!(values.length(), 12);
157
158        let values = alloc::vec![
159            EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
160            EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
161        ];
162        assert_eq!(values.length(), 12);
163
164        let values = alloc::vec![
165            OctetString::<0, 5>::new(b"Hello").unwrap(),
166            OctetString::<0, 5>::new(b"World").unwrap(),
167        ];
168        assert_eq!(values.length(), 10);
169    }
170
171    #[test]
172    fn encode_option() {
173        let buf = &mut [0u8; 1024];
174
175        let value: Option<u8> = Some(0u8);
176        assert!(buf.len() >= value.length());
177
178        let size = value.encode(buf);
179
180        assert_eq!(size, 1);
181        assert_eq!(&buf[..size], &[0]);
182
183        let value: Option<u8> = None;
184        assert!(buf.len() >= value.length());
185
186        let size = value.encode(buf);
187
188        assert_eq!(size, 0);
189    }
190
191    #[test]
192    fn encode_vec() {
193        let buf = &mut [0u8; 1024];
194
195        let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
196        assert!(buf.len() >= values.length());
197
198        let size = values.encode(buf);
199
200        assert_eq!(size, 10);
201        assert_eq!(&buf[..size], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
202
203        let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
204        assert!(buf.len() >= values.length());
205
206        let size = values.encode(buf);
207
208        assert_eq!(size, 20);
209        assert_eq!(
210            &buf[..size],
211            &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9]
212        );
213
214        let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
215        assert!(buf.len() >= values.length());
216
217        let size = values.encode(buf);
218        assert_eq!(size, 40);
219
220        assert_eq!(
221            &buf[..size],
222            &[
223                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, 0, 6,
224                0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9
225            ]
226        );
227
228        let values = alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
229        assert!(buf.len() >= values.length());
230
231        let size = values.encode(buf);
232
233        assert_eq!(size, 10);
234        assert_eq!(&buf[..size], b"HelloWorld");
235
236        let values = alloc::vec![
237            COctetString::<1, 6>::new(b"Hello\0").unwrap(),
238            COctetString::<1, 6>::new(b"World\0").unwrap(),
239        ];
240        assert!(buf.len() >= values.length());
241
242        let size = values.encode(buf);
243
244        assert_eq!(size, 12);
245        assert_eq!(&buf[..size], b"Hello\0World\0");
246
247        let values = alloc::vec![
248            EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
249            EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
250        ];
251        assert!(buf.len() >= values.length());
252
253        let size = values.encode(buf);
254
255        assert_eq!(size, 12);
256        assert_eq!(&buf[..size], b"Hello\0World\0");
257
258        let values = alloc::vec![
259            OctetString::<0, 5>::new(b"Hello").unwrap(),
260            OctetString::<0, 5>::new(b"World").unwrap(),
261        ];
262        assert!(buf.len() >= values.length());
263
264        let size = values.encode(buf);
265
266        assert_eq!(size, 10);
267        assert_eq!(&buf[..size], b"HelloWorld");
268    }
269}