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::{BufsMut, 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    #[inline]
18    fn write_bufs(&self, buf: &mut impl BufsMut) {
19        self.as_slice().write_bufs(buf)
20    }
21}
22
23impl<T: EncodeSize> EncodeSize for Vec<T> {
24    #[inline]
25    fn encode_size(&self) -> usize {
26        self.as_slice().encode_size()
27    }
28
29    #[inline]
30    fn encode_inline_size(&self) -> usize {
31        self.as_slice().encode_inline_size()
32    }
33}
34
35impl<T: Write> Write for &[T] {
36    #[inline]
37    fn write(&self, buf: &mut impl BufMut) {
38        self.len().write(buf);
39        for item in self.iter() {
40            item.write(buf);
41        }
42    }
43
44    #[inline]
45    fn write_bufs(&self, buf: &mut impl BufsMut) {
46        self.len().write(buf);
47        for item in self.iter() {
48            item.write_bufs(buf);
49        }
50    }
51}
52
53impl<T: EncodeSize> EncodeSize for &[T] {
54    #[inline]
55    fn encode_size(&self) -> usize {
56        self.len().encode_size() + self.iter().map(EncodeSize::encode_size).sum::<usize>()
57    }
58
59    #[inline]
60    fn encode_inline_size(&self) -> usize {
61        self.len().encode_size()
62            + self
63                .iter()
64                .map(EncodeSize::encode_inline_size)
65                .sum::<usize>()
66    }
67}
68
69impl<T: Read> Read for Vec<T> {
70    type Cfg = (RangeCfg<usize>, T::Cfg);
71
72    #[inline]
73    fn read_cfg(buf: &mut impl Buf, (range, cfg): &Self::Cfg) -> Result<Self, Error> {
74        let len = usize::read_cfg(buf, range)?;
75        let mut vec = Self::with_capacity(len);
76        for _ in 0..len {
77            vec.push(T::read_cfg(buf, cfg)?);
78        }
79        Ok(vec)
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use crate::{DecodeRangeExt, Encode};
87
88    #[test]
89    fn test_vec() {
90        let vec_values = [vec![], vec![1u8], vec![1u8, 2u8, 3u8]];
91        for value in vec_values {
92            let encoded = value.encode();
93            assert_eq!(encoded.len(), value.len() * core::mem::size_of::<u8>() + 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_slice() {
116        let slice_values: [&[u8]; 3] =
117            [[].as_slice(), [1u8].as_slice(), [1u8, 2u8, 3u8].as_slice()];
118        for value in slice_values {
119            let encoded = value.encode();
120            assert_eq!(encoded.len(), core::mem::size_of_val(value) + 1);
121
122            // Valid decoding
123            let len = value.len();
124            let decoded = Vec::<u8>::decode_range(encoded, len..=len).unwrap();
125            assert_eq!(value, decoded);
126
127            // Failure for too long
128            assert!(matches!(
129                Vec::<u8>::decode_range(value.encode(), 0..len),
130                Err(Error::InvalidLength(_))
131            ));
132
133            // Failure for too short
134            assert!(matches!(
135                Vec::<u8>::decode_range(value.encode(), len + 1..),
136                Err(Error::InvalidLength(_))
137            ));
138        }
139    }
140
141    #[test]
142    fn test_conformity() {
143        assert_eq!(Vec::<u8>::new().encode(), &[0x00][..]);
144        assert_eq!(
145            vec![0x01u8, 0x02u8, 0x03u8].encode(),
146            &[0x03, 0x01, 0x02, 0x03][..]
147        );
148
149        let v_u16: Vec<u16> = vec![0x1234, 0xABCD];
150        assert_eq!(v_u16.encode(), &[0x02, 0x12, 0x34, 0xAB, 0xCD][..]);
151
152        let v_bool: Vec<bool> = vec![true, false, true];
153        assert_eq!(v_bool.encode(), &[0x03, 0x01, 0x00, 0x01][..]);
154
155        let v_empty_u32: Vec<u32> = Vec::new();
156        assert_eq!(v_empty_u32.encode(), &[0x00][..]);
157
158        // Test with a length that requires a multi-byte varint
159        let v_long_u8: Vec<u8> = vec![0xCC; 200]; // 200 = 0xC8 = 0x80 + 0x48 -> 0xC8 0x01
160        let mut expected_long_u8 = vec![0xC8, 0x01];
161        expected_long_u8.extend_from_slice(&[0xCC; 200]);
162        assert_eq!(v_long_u8.encode(), expected_long_u8.as_slice());
163    }
164
165    #[cfg(feature = "arbitrary")]
166    mod conformance {
167        use crate::conformance::CodecConformance;
168
169        commonware_conformance::conformance_tests! {
170            CodecConformance<Vec<u8>>,
171            CodecConformance<Vec<u16>>,
172            CodecConformance<Vec<u32>>,
173        }
174    }
175}