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