commonware_codec/
types.rs

1//! Implementations of Codec for common types
2
3use crate::{
4    codec::{Codec, Reader, Writer},
5    varint, Error, SizedCodec,
6};
7use bytes::Bytes;
8use paste::paste;
9
10macro_rules! impl_primitive {
11    ($type:ty, $read_method:ident, $write_method:ident, $size:expr) => {
12        impl Codec for $type {
13            #[inline]
14            fn write(&self, writer: &mut impl Writer) {
15                writer.$write_method(*self);
16            }
17
18            #[inline]
19            fn len_encoded(&self) -> usize {
20                std::mem::size_of::<$type>()
21            }
22
23            #[inline]
24            fn read(reader: &mut impl Reader) -> Result<Self, Error> {
25                reader.$read_method()
26            }
27        }
28
29        impl SizedCodec for $type {
30            const LEN_ENCODED: usize = $size;
31        }
32    };
33}
34
35impl_primitive!(u8, read_u8, write_u8, 1);
36impl_primitive!(u16, read_u16, write_u16, 2);
37impl_primitive!(u32, read_u32, write_u32, 4);
38impl_primitive!(u64, read_u64, write_u64, 8);
39impl_primitive!(u128, read_u128, write_u128, 16);
40impl_primitive!(i8, read_i8, write_i8, 1);
41impl_primitive!(i16, read_i16, write_i16, 2);
42impl_primitive!(i32, read_i32, write_i32, 4);
43impl_primitive!(i64, read_i64, write_i64, 8);
44impl_primitive!(i128, read_i128, write_i128, 16);
45impl_primitive!(f32, read_f32, write_f32, 4);
46impl_primitive!(f64, read_f64, write_f64, 8);
47impl_primitive!(bool, read_bool, write_bool, 1);
48
49// Bytes implementation
50impl Codec for Bytes {
51    #[inline]
52    fn write(&self, writer: &mut impl Writer) {
53        writer.write_bytes(self);
54    }
55
56    #[inline]
57    fn len_encoded(&self) -> usize {
58        self.len() + varint::varint_size(self.len() as u64)
59    }
60
61    #[inline]
62    fn read(reader: &mut impl Reader) -> Result<Self, Error> {
63        reader.read_bytes()
64    }
65}
66
67// Constant-size array implementation
68impl<const N: usize> Codec for [u8; N] {
69    #[inline]
70    fn write(&self, writer: &mut impl Writer) {
71        writer.write_fixed(self);
72    }
73
74    #[inline]
75    fn len_encoded(&self) -> usize {
76        N
77    }
78
79    #[inline]
80    fn read(reader: &mut impl Reader) -> Result<Self, Error> {
81        reader.read_fixed()
82    }
83}
84
85impl<const N: usize> SizedCodec for [u8; N] {
86    const LEN_ENCODED: usize = N;
87}
88
89// Option implementation
90impl<T: Codec> Codec for Option<T> {
91    #[inline]
92    fn write(&self, writer: &mut impl Writer) {
93        writer.write_option(self);
94    }
95
96    #[inline]
97    fn len_encoded(&self) -> usize {
98        match self {
99            Some(inner) => 1 + inner.len_encoded(),
100            None => 1,
101        }
102    }
103
104    #[inline]
105    fn read(reader: &mut impl Reader) -> Result<Self, Error> {
106        reader.read_option()
107    }
108}
109
110// Tuple implementation
111macro_rules! impl_codec_for_tuple {
112    ($($index:literal),*) => {
113        paste! {
114            impl<$( [<T $index>]: Codec ),*> Codec for ( $( [<T $index>], )* ) {
115                fn write(&self, writer: &mut impl Writer) {
116                    $( self.$index.write(writer); )*
117                }
118
119                fn len_encoded(&self) -> usize {
120                    0 $( + self.$index.len_encoded() )*
121                }
122
123                fn read(reader: &mut impl Reader) -> Result<Self, Error> {
124                    Ok(( $( [<T $index>]::read(reader)?, )* ))
125                }
126            }
127        }
128    };
129}
130
131// Generate implementations for tuple sizes 1 through 12
132impl_codec_for_tuple!(0);
133impl_codec_for_tuple!(0, 1);
134impl_codec_for_tuple!(0, 1, 2);
135impl_codec_for_tuple!(0, 1, 2, 3);
136impl_codec_for_tuple!(0, 1, 2, 3, 4);
137impl_codec_for_tuple!(0, 1, 2, 3, 4, 5);
138impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6);
139impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7);
140impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8);
141impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
142impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
143impl_codec_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
144
145// Vec implementation
146impl<T: Codec> Codec for Vec<T> {
147    #[inline]
148    fn write(&self, writer: &mut impl Writer) {
149        writer.write_vec(self);
150    }
151
152    #[inline]
153    fn len_encoded(&self) -> usize {
154        let len = varint::varint_size(self.len() as u64);
155        self.iter().map(Codec::len_encoded).sum::<usize>() + len
156    }
157
158    #[inline]
159    fn read(reader: &mut impl Reader) -> Result<Self, Error> {
160        reader.read_vec()
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use super::*;
167    use crate::codec::{Codec, SizedCodec};
168    use bytes::Bytes;
169
170    // Float tests
171    macro_rules! impl_num_test {
172        ($type:ty, $size:expr) => {
173            paste! {
174                #[test]
175                fn [<test_ $type>]() {
176                    let expected_len = std::mem::size_of::<$type>();
177                    let values: [$type; 5] =
178                        [0 as $type, 1 as $type, 42 as $type, <$type>::MAX, <$type>::MIN];
179                    for value in values.iter() {
180                        let encoded = value.encode();
181                        assert_eq!(encoded.len(), expected_len);
182                        let decoded = <$type>::decode(encoded).unwrap();
183                        assert_eq!(*value, decoded);
184                        assert_eq!(Codec::len_encoded(value), expected_len);
185                        assert_eq!(SizedCodec::len_encoded(value), expected_len);
186
187                        let fixed: [u8; $size] = value.encode_fixed();
188                        assert_eq!(fixed.len(), expected_len);
189                        let decoded = <$type>::decode(Bytes::copy_from_slice(&fixed)).unwrap();
190                        assert_eq!(*value, decoded);
191                    }
192                }
193            }
194        };
195    }
196    impl_num_test!(u8, 1);
197    impl_num_test!(u16, 2);
198    impl_num_test!(u32, 4);
199    impl_num_test!(u64, 8);
200    impl_num_test!(u128, 16);
201    impl_num_test!(i8, 1);
202    impl_num_test!(i16, 2);
203    impl_num_test!(i32, 4);
204    impl_num_test!(i64, 8);
205    impl_num_test!(i128, 16);
206    impl_num_test!(f32, 4);
207    impl_num_test!(f64, 8);
208
209    #[test]
210    fn test_endianness() {
211        // u16
212        let encoded = 0x0102u16.encode();
213        assert_eq!(encoded, Bytes::from_static(&[0x01, 0x02]));
214
215        // u32
216        let encoded = 0x01020304u32.encode();
217        assert_eq!(encoded, Bytes::from_static(&[0x01, 0x02, 0x03, 0x04]));
218
219        // f32
220        let encoded = 1.0f32.encode();
221        assert_eq!(encoded, Bytes::from_static(&[0x3F, 0x80, 0x00, 0x00])); // Big-endian IEEE 754
222    }
223
224    #[test]
225    fn test_bool() {
226        let values = [true, false];
227        for value in values.iter() {
228            let encoded = value.encode();
229            assert_eq!(encoded.len(), 1);
230            let decoded = bool::decode(encoded).unwrap();
231            assert_eq!(*value, decoded);
232            assert_eq!(Codec::len_encoded(value), 1);
233            assert_eq!(SizedCodec::len_encoded(value), 1);
234        }
235    }
236
237    #[test]
238    fn test_bytes() {
239        let values = [
240            Bytes::new(),
241            Bytes::from_static(&[1, 2, 3]),
242            Bytes::from(vec![0; 300]),
243        ];
244        for value in values {
245            let encoded = value.encode();
246            assert_eq!(
247                encoded.len(),
248                varint::varint_size(value.len() as u64) + value.len()
249            );
250            let decoded = Bytes::decode(encoded).unwrap();
251            assert_eq!(value, decoded);
252        }
253    }
254
255    #[test]
256    fn test_array() {
257        let values = [1u8, 2, 3];
258        let encoded = values.encode();
259        let decoded = <[u8; 3]>::decode(encoded).unwrap();
260        assert_eq!(values, decoded);
261    }
262
263    #[test]
264    fn test_option() {
265        let option_values = [Some(42u32), None];
266        for value in option_values {
267            let encoded = value.encode();
268            let decoded = Option::<u32>::decode(encoded).unwrap();
269            assert_eq!(value, decoded);
270        }
271    }
272
273    #[test]
274    fn test_option_length() {
275        let some = Some(42u32);
276        assert_eq!(Codec::len_encoded(&some), 1 + 4);
277        assert_eq!(some.encode().len(), 1 + 4);
278        let none: Option<u32> = None;
279        assert_eq!(Codec::len_encoded(&none), 1);
280        assert_eq!(none.encode().len(), 1);
281    }
282
283    #[test]
284    fn test_tuple() {
285        let tuple_values = [(1u16, None), (1u16, Some(2u32))];
286        for value in tuple_values {
287            let encoded = value.encode();
288            let decoded = <(u16, Option<u32>)>::decode(encoded).unwrap();
289            assert_eq!(value, decoded);
290        }
291    }
292
293    #[test]
294    fn test_vec() {
295        let vec_values = [vec![], vec![1u8], vec![1u8, 2u8, 3u8]];
296        for value in vec_values {
297            let encoded = value.encode();
298            assert_eq!(encoded.len(), value.len() * std::mem::size_of::<u8>() + 1);
299            let decoded = Vec::<u8>::decode(encoded).unwrap();
300            assert_eq!(value, decoded);
301        }
302    }
303}