Skip to main content

commonware_codec/types/
vec.rs

1//! Codec implementation for [`Vec<T>`].
2//!
3//! For portability and consistency between architectures,
4//! the length of the vector must fit within a [u32].
5
6use crate::{EncodeSize, Error, RangeCfg, Read, Write};
7#[cfg(not(feature = "std"))]
8use alloc::vec::Vec;
9use bytes::{Buf, BufMut};
10
11impl<T: Write> Write for Vec<T> {
12    #[inline]
13    fn write(&self, buf: &mut impl BufMut) {
14        self.as_slice().write(buf)
15    }
16}
17
18impl<T: EncodeSize> EncodeSize for Vec<T> {
19    #[inline]
20    fn encode_size(&self) -> usize {
21        self.as_slice().encode_size()
22    }
23}
24
25impl<T: Write> Write for &[T] {
26    #[inline]
27    fn write(&self, buf: &mut impl BufMut) {
28        self.len().write(buf);
29        for item in self.iter() {
30            item.write(buf);
31        }
32    }
33}
34
35impl<T: EncodeSize> EncodeSize for &[T] {
36    #[inline]
37    fn encode_size(&self) -> usize {
38        self.len().encode_size() + self.iter().map(EncodeSize::encode_size).sum::<usize>()
39    }
40}
41
42impl<T: Read> Read for Vec<T> {
43    type Cfg = (RangeCfg<usize>, T::Cfg);
44
45    #[inline]
46    fn read_cfg(buf: &mut impl Buf, (range, cfg): &Self::Cfg) -> Result<Self, Error> {
47        let len = usize::read_cfg(buf, range)?;
48        let mut vec = Self::with_capacity(len);
49        for _ in 0..len {
50            vec.push(T::read_cfg(buf, cfg)?);
51        }
52        Ok(vec)
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use crate::{DecodeRangeExt, Encode};
60
61    #[test]
62    fn test_vec() {
63        let vec_values = [vec![], vec![1u8], vec![1u8, 2u8, 3u8]];
64        for value in vec_values {
65            let encoded = value.encode();
66            assert_eq!(encoded.len(), value.len() * core::mem::size_of::<u8>() + 1);
67
68            // Valid decoding
69            let len = value.len();
70            let decoded = Vec::<u8>::decode_range(encoded, len..=len).unwrap();
71            assert_eq!(value, decoded);
72
73            // Failure for too long
74            assert!(matches!(
75                Vec::<u8>::decode_range(value.encode(), 0..len),
76                Err(Error::InvalidLength(_))
77            ));
78
79            // Failure for too short
80            assert!(matches!(
81                Vec::<u8>::decode_range(value.encode(), len + 1..),
82                Err(Error::InvalidLength(_))
83            ));
84        }
85    }
86
87    #[test]
88    fn test_slice() {
89        let slice_values: [&[u8]; 3] =
90            [[].as_slice(), [1u8].as_slice(), [1u8, 2u8, 3u8].as_slice()];
91        for value in slice_values {
92            let encoded = value.encode();
93            assert_eq!(encoded.len(), core::mem::size_of_val(value) + 1);
94
95            // Valid decoding
96            let len = value.len();
97            let decoded = Vec::<u8>::decode_range(encoded, len..=len).unwrap();
98            assert_eq!(value, decoded);
99
100            // Failure for too long
101            assert!(matches!(
102                Vec::<u8>::decode_range(value.encode(), 0..len),
103                Err(Error::InvalidLength(_))
104            ));
105
106            // Failure for too short
107            assert!(matches!(
108                Vec::<u8>::decode_range(value.encode(), len + 1..),
109                Err(Error::InvalidLength(_))
110            ));
111        }
112    }
113
114    #[test]
115    fn test_conformity() {
116        assert_eq!(Vec::<u8>::new().encode(), &[0x00][..]);
117        assert_eq!(
118            vec![0x01u8, 0x02u8, 0x03u8].encode(),
119            &[0x03, 0x01, 0x02, 0x03][..]
120        );
121
122        let v_u16: Vec<u16> = vec![0x1234, 0xABCD];
123        assert_eq!(v_u16.encode(), &[0x02, 0x12, 0x34, 0xAB, 0xCD][..]);
124
125        let v_bool: Vec<bool> = vec![true, false, true];
126        assert_eq!(v_bool.encode(), &[0x03, 0x01, 0x00, 0x01][..]);
127
128        let v_empty_u32: Vec<u32> = Vec::new();
129        assert_eq!(v_empty_u32.encode(), &[0x00][..]);
130
131        // Test with a length that requires a multi-byte varint
132        let v_long_u8: Vec<u8> = vec![0xCC; 200]; // 200 = 0xC8 = 0x80 + 0x48 -> 0xC8 0x01
133        let mut expected_long_u8 = vec![0xC8, 0x01];
134        expected_long_u8.extend_from_slice(&[0xCC; 200]);
135        assert_eq!(v_long_u8.encode(), expected_long_u8.as_slice());
136    }
137
138    #[cfg(feature = "arbitrary")]
139    mod conformance {
140        use crate::conformance::CodecConformance;
141
142        commonware_conformance::conformance_tests! {
143            CodecConformance<Vec<u8>>,
144            CodecConformance<Vec<u16>>,
145            CodecConformance<Vec<u32>>,
146        }
147    }
148}