wayk_proto/
serialization.rs

1use crate::error::ProtoError;
2use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
3use std::io::{Cursor, Write};
4
5// === ENCODE ===
6
7/// Common interface for encoding
8pub trait Encode {
9    fn encoded_len(&self) -> usize;
10
11    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError>
12    where
13        Self: Sized;
14
15    fn encode(&self) -> Result<Vec<u8>, ProtoError>
16    where
17        Self: Sized,
18    {
19        let mut buf = Cursor::new(Vec::new());
20        self.encode_into(&mut buf)?;
21        Ok(buf.into_inner())
22    }
23}
24
25sa::assert_obj_safe!(Encode);
26
27// === DECODE ===
28
29/// Common interface for decoding
30///
31/// `'dec` lifetime **should not** appear in the type to which
32/// the `Encode` impl applies.
33///
34/// Types that borrows **should implement the trait like this**:
35/// ```
36/// use wayk_proto::serialization::Decode;
37/// use wayk_proto::error::ProtoError;
38/// use std::io::Cursor;
39///
40/// // my type that borrows
41/// struct MyType<'a> {
42///     data: &'a [u8],
43/// }
44///
45/// impl<'dec: 'a, 'a> Decode<'dec> for MyType<'a> {
46///     fn decode_from(cursor: &mut Cursor<&'dec [u8]>) -> Result<Self, ProtoError> {
47///         unimplemented!()
48///     }
49/// }
50/// ```
51/// That is, **do not do this**:
52/// ```
53/// use wayk_proto::serialization::Decode;
54/// use wayk_proto::error::ProtoError;
55/// use std::io::Cursor;
56///
57/// struct MyType<'a> {
58///     data: &'a [u8],
59/// }
60///
61/// impl<'dec> Decode<'dec> for MyType<'dec> {
62///     fn decode_from(cursor: &mut Cursor<&'dec [u8]>) -> Result<Self, ProtoError> {
63///         unimplemented!()
64///     }
65/// }
66/// ```
67/// Sooner or later it will explodes in your face.
68pub trait Decode<'dec>
69where
70    Self: Sized,
71{
72    fn decode_from(cursor: &mut Cursor<&'dec [u8]>) -> Result<Self, ProtoError>;
73
74    fn decode(bytes: &'dec [u8]) -> Result<Self, ProtoError> {
75        Self::decode_from(&mut Cursor::new(bytes))
76    }
77}
78
79// === implementation for primitive types ===
80
81impl Encode for u8 {
82    fn encoded_len(&self) -> usize {
83        std::mem::size_of::<Self>()
84    }
85
86    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
87        writer.write_u8(*self).map_err(ProtoError::from)
88    }
89}
90
91impl Decode<'_> for u8 {
92    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
93        cursor.read_u8().map_err(ProtoError::from)
94    }
95}
96
97impl Encode for u16 {
98    fn encoded_len(&self) -> usize {
99        std::mem::size_of::<Self>()
100    }
101
102    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
103        writer.write_u16::<LittleEndian>(*self).map_err(ProtoError::from)
104    }
105}
106
107impl Decode<'_> for u16 {
108    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
109        cursor.read_u16::<LittleEndian>().map_err(ProtoError::from)
110    }
111}
112
113impl Encode for u32 {
114    fn encoded_len(&self) -> usize {
115        std::mem::size_of::<Self>()
116    }
117
118    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
119        writer.write_u32::<LittleEndian>(*self).map_err(ProtoError::from)
120    }
121}
122
123impl Decode<'_> for u32 {
124    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
125        cursor.read_u32::<LittleEndian>().map_err(ProtoError::from)
126    }
127}
128
129impl Encode for u64 {
130    fn encoded_len(&self) -> usize {
131        std::mem::size_of::<Self>()
132    }
133
134    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
135        writer.write_u64::<LittleEndian>(*self).map_err(ProtoError::from)
136    }
137}
138
139impl Decode<'_> for u64 {
140    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
141        cursor.read_u64::<LittleEndian>().map_err(ProtoError::from)
142    }
143}
144
145impl Encode for u128 {
146    fn encoded_len(&self) -> usize {
147        std::mem::size_of::<Self>()
148    }
149
150    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
151        writer.write_u128::<LittleEndian>(*self).map_err(ProtoError::from)
152    }
153}
154
155impl Decode<'_> for u128 {
156    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
157        cursor.read_u128::<LittleEndian>().map_err(ProtoError::from)
158    }
159}
160
161impl Encode for i8 {
162    fn encoded_len(&self) -> usize {
163        std::mem::size_of::<Self>()
164    }
165
166    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
167        writer.write_i8(*self).map_err(ProtoError::from)
168    }
169}
170
171impl Decode<'_> for i8 {
172    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
173        cursor.read_i8().map_err(ProtoError::from)
174    }
175}
176
177impl Encode for i16 {
178    fn encoded_len(&self) -> usize {
179        std::mem::size_of::<Self>()
180    }
181
182    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
183        writer.write_i16::<LittleEndian>(*self).map_err(ProtoError::from)
184    }
185}
186
187impl Decode<'_> for i16 {
188    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
189        cursor.read_i16::<LittleEndian>().map_err(ProtoError::from)
190    }
191}
192
193impl Encode for i32 {
194    fn encoded_len(&self) -> usize {
195        std::mem::size_of::<Self>()
196    }
197
198    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
199        writer.write_i32::<LittleEndian>(*self).map_err(ProtoError::from)
200    }
201}
202
203impl Decode<'_> for i32 {
204    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
205        cursor.read_i32::<LittleEndian>().map_err(ProtoError::from)
206    }
207}
208
209impl Encode for i64 {
210    fn encoded_len(&self) -> usize {
211        std::mem::size_of::<Self>()
212    }
213
214    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
215        writer.write_i64::<LittleEndian>(*self).map_err(ProtoError::from)
216    }
217}
218
219impl Decode<'_> for i64 {
220    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
221        cursor.read_i64::<LittleEndian>().map_err(ProtoError::from)
222    }
223}
224
225impl Encode for i128 {
226    fn encoded_len(&self) -> usize {
227        std::mem::size_of::<Self>()
228    }
229
230    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
231        writer.write_i128::<LittleEndian>(*self).map_err(ProtoError::from)
232    }
233}
234
235impl Decode<'_> for i128 {
236    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
237        cursor.read_i128::<LittleEndian>().map_err(ProtoError::from)
238    }
239}
240
241impl Encode for [u32; 4] {
242    fn encoded_len(&self) -> usize {
243        std::mem::size_of::<Self>()
244    }
245
246    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
247        for element in self {
248            element.encode_into(writer)?;
249        }
250        Ok(())
251    }
252}
253
254impl Decode<'_> for [u32; 4] {
255    fn decode_from(cursor: &mut Cursor<&[u8]>) -> Result<Self, ProtoError> {
256        Ok([
257            cursor.read_u32::<LittleEndian>()?,
258            cursor.read_u32::<LittleEndian>()?,
259            cursor.read_u32::<LittleEndian>()?,
260            cursor.read_u32::<LittleEndian>()?,
261        ])
262    }
263}
264
265impl Encode for &[u8] {
266    fn encoded_len(&self) -> usize {
267        self.len()
268    }
269
270    fn encode_into<W: Write>(&self, writer: &mut W) -> Result<(), ProtoError> {
271        writer.write_all(self)?;
272        Ok(())
273    }
274}
275
276impl<'dec: 'a, 'a, T: 'a> Decode<'dec> for Box<T>
277where
278    T: Decode<'dec>,
279{
280    fn decode_from(cursor: &mut Cursor<&'dec [u8]>) -> Result<Self, ProtoError> {
281        T::decode_from(cursor).map(Box::new)
282    }
283}
284
285#[cfg(test)]
286mod tests {
287    use super::*;
288    use crate::container::Bytes8;
289
290    #[derive(Encode, Decode)]
291    struct StructDerive<'a> {
292        pub a: u8,
293        b: u8,
294        pub c: u16,
295        update_data: Bytes8<'a>,
296    }
297
298    const STRUCT_DERIVE_ENCODED: [u8; 8] = [0x10, 0x20, 0x30, 0x40, 0x03, 0x01, 0x02, 0x03];
299
300    #[test]
301    fn struct_derive_decode() {
302        let s = StructDerive::decode(&STRUCT_DERIVE_ENCODED).unwrap();
303        assert_eq!(s.a, 0x10);
304        assert_eq!(s.b, 0x20);
305        assert_eq!(s.c, 0x4030);
306        assert_eq!(s.update_data, &[0x01, 0x02, 0x03][0..]);
307    }
308
309    #[test]
310    fn struct_derive_encode() {
311        let s = StructDerive {
312            a: 0x10,
313            b: 0x20,
314            c: 0x4030,
315            update_data: Bytes8(&[0x01, 0x02, 0x03]),
316        };
317        assert_eq!(s.encode().unwrap(), STRUCT_DERIVE_ENCODED.to_vec());
318    }
319}