Skip to main content

commonware_codec/types/
bytes.rs

1//! Implementations of Codec for byte types.
2//!
3//! For portability and consistency between architectures,
4//! the length of the [Bytes] must fit within a [u32].
5
6use crate::{util::at_least, BufsMut, EncodeSize, Error, RangeCfg, Read, Write};
7use bytes::{Buf, BufMut, Bytes};
8
9impl Write for Bytes {
10    #[inline]
11    fn write(&self, buf: &mut impl BufMut) {
12        self.len().write(buf);
13        buf.put_slice(self);
14    }
15
16    #[inline]
17    fn write_bufs(&self, buf: &mut impl BufsMut) {
18        self.len().write(buf);
19        buf.push(self.clone());
20    }
21}
22
23impl EncodeSize for Bytes {
24    #[inline]
25    fn encode_size(&self) -> usize {
26        self.len().encode_size() + self.len()
27    }
28
29    #[inline]
30    fn encode_inline_size(&self) -> usize {
31        self.len().encode_size()
32    }
33}
34
35impl Read for Bytes {
36    type Cfg = RangeCfg<usize>;
37
38    #[inline]
39    fn read_cfg(buf: &mut impl Buf, range: &Self::Cfg) -> Result<Self, Error> {
40        let len = usize::read_cfg(buf, range)?;
41        at_least(buf, len)?;
42        Ok(buf.copy_to_bytes(len))
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::{Decode, Encode};
50    use bytes::Bytes;
51
52    #[test]
53    fn test_bytes() {
54        let values = [
55            Bytes::new(),
56            Bytes::from_static(&[1, 2, 3]),
57            Bytes::from(vec![0; 300]),
58        ];
59        for value in values {
60            let encoded = value.encode();
61            let len = value.len();
62
63            // Valid decoding
64            let decoded = Bytes::decode_cfg(encoded, &(len..=len).into()).unwrap();
65            assert_eq!(value, decoded);
66
67            // Failure for too long
68            assert!(matches!(
69                Bytes::decode_cfg(value.encode(), &(0..len).into()),
70                Err(Error::InvalidLength(_))
71            ));
72
73            // Failure for too short
74            assert!(matches!(
75                Bytes::decode_cfg(value.encode(), &(len + 1..).into()),
76                Err(Error::InvalidLength(_))
77            ));
78        }
79    }
80
81    #[test]
82    fn test_conformity() {
83        assert_eq!(Bytes::new().encode(), &[0x00][..]);
84        assert_eq!(
85            Bytes::from_static(b"hello").encode(),
86            &[0x05, b'h', b'e', b'l', b'l', b'o'][..]
87        );
88        let long_bytes = Bytes::from(vec![0xAA; 150]);
89        let mut expected = vec![0x96, 0x01]; // Varint for 150
90        expected.extend_from_slice(&[0xAA; 150]);
91        assert_eq!(long_bytes.encode(), expected.as_slice());
92    }
93
94    #[cfg(feature = "arbitrary")]
95    mod conformance {
96        use super::*;
97        use crate::conformance::CodecConformance;
98        use arbitrary::Arbitrary;
99
100        /// Newtype wrapper to implement Arbitrary for [super::Bytes].
101        #[derive(Debug)]
102        struct Bytes(super::Bytes);
103
104        impl Write for Bytes {
105            fn write(&self, buf: &mut impl BufMut) {
106                self.0.write(buf);
107            }
108        }
109
110        impl EncodeSize for Bytes {
111            fn encode_size(&self) -> usize {
112                self.0.encode_size()
113            }
114        }
115
116        impl Read for Bytes {
117            type Cfg = RangeCfg<usize>;
118
119            fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
120                Ok(Self(super::Bytes::read_cfg(buf, cfg)?))
121            }
122        }
123
124        impl Arbitrary<'_> for Bytes {
125            fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
126                let len = u.arbitrary::<u8>()?;
127                let bytes: Vec<u8> = u
128                    .arbitrary_iter()?
129                    .take(len as usize)
130                    .collect::<Result<Vec<_>, _>>()
131                    .unwrap();
132                Ok(Self(super::Bytes::from(bytes)))
133            }
134        }
135
136        commonware_conformance::conformance_tests! {
137            CodecConformance<Bytes>
138        }
139    }
140}