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::{varint, Config, EncodeSize, Error, RangeConfig, Read, Write};
7use bytes::{Buf, BufMut};
8
9impl<T: Write> Write for Vec<T> {
10    #[inline]
11    fn write(&self, buf: &mut impl BufMut) {
12        let len = u32::try_from(self.len()).expect("Vec length exceeds u32");
13        varint::write(len, buf);
14        for item in self {
15            item.write(buf);
16        }
17    }
18}
19
20impl<T: EncodeSize> EncodeSize for Vec<T> {
21    #[inline]
22    fn encode_size(&self) -> usize {
23        let len = u32::try_from(self.len()).expect("Vec length exceeds u32");
24        varint::size(len) + self.iter().map(EncodeSize::encode_size).sum::<usize>()
25    }
26}
27
28impl<R: RangeConfig, Cfg: Config, T: Read<Cfg>> Read<(R, Cfg)> for Vec<T> {
29    #[inline]
30    fn read_cfg(buf: &mut impl Buf, (range, cfg): &(R, Cfg)) -> Result<Self, Error> {
31        let len32 = varint::read::<u32>(buf)?;
32        let len = usize::try_from(len32).map_err(|_| Error::InvalidVarint)?;
33        if !range.contains(&len) {
34            return Err(Error::InvalidLength(len));
35        }
36        let mut vec = Vec::with_capacity(len);
37        for _ in 0..len {
38            vec.push(T::read_cfg(buf, cfg)?);
39        }
40        Ok(vec)
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use crate::{DecodeRangeExt, Encode};
48
49    #[test]
50    fn test_vec() {
51        let vec_values = [vec![], vec![1u8], vec![1u8, 2u8, 3u8]];
52        for value in vec_values {
53            let encoded = value.encode();
54            assert_eq!(encoded.len(), value.len() * std::mem::size_of::<u8>() + 1);
55
56            // Valid decoding
57            let len = value.len();
58            let decoded = Vec::<u8>::decode_range(encoded, len..=len).unwrap();
59            assert_eq!(value, decoded);
60
61            // Failure for too long
62            matches!(
63                Vec::<u8>::decode_range(value.encode(), 0..len),
64                Err(Error::InvalidLength(_))
65            );
66
67            // Failure for too short
68            matches!(
69                Vec::<u8>::decode_range(value.encode(), len + 1..),
70                Err(Error::InvalidLength(_))
71            );
72        }
73    }
74}