tinycbor/
bytes.rs

1use crate::{
2    BYTES, CborLen, Decode, Decoder, Encode, Encoder, InvalidHeader, Write,
3    collections::{self, fixed},
4    info_of,
5    primitive::Error,
6    type_of,
7};
8
9/// Decodes a definite-length byte string.
10///
11/// If you need to also support indefinite-length byte strings, consider using an allocated type
12/// such as `Vec<u8>` or `Box<[u8]>`.
13impl<'a, 'b> Decode<'b> for &'a [u8]
14where
15    'b: 'a,
16{
17    type Error = Error;
18
19    fn decode(d: &mut Decoder<'b>) -> Result<Self, Self::Error> {
20        let b = d.peek()?;
21        if BYTES != type_of(b) || info_of(b) == 31 {
22            return Err(Error::InvalidHeader(InvalidHeader));
23        }
24        let n = d.length()?;
25        Ok(d.read_slice(n)?)
26    }
27}
28
29impl Encode for [u8] {
30    fn encode<W: Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
31        e.type_len(BYTES, self.len() as u64)?;
32        e.put(self)
33    }
34}
35
36impl CborLen for [u8] {
37    fn cbor_len(&self) -> usize {
38        let n = self.len();
39        n.cbor_len() + n
40    }
41}
42
43/// Decodes a byte string, supporting both definite-length and indefinite-length encodings.
44#[cfg(feature = "alloc")]
45impl<'a> Decode<'a> for alloc::vec::Vec<u8> {
46    type Error = Error;
47
48    fn decode(d: &mut Decoder<'a>) -> Result<Self, Self::Error> {
49        let mut vec = alloc::vec::Vec::new();
50        for slice in d.bytes_iter()? {
51            let slice = slice?;
52            vec.extend_from_slice(slice);
53        }
54        Ok(vec)
55    }
56}
57
58#[cfg(feature = "alloc")]
59impl Encode for alloc::vec::Vec<u8> {
60    fn encode<W: Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
61        self.as_slice().encode(e)
62    }
63}
64
65#[cfg(feature = "alloc")]
66impl CborLen for alloc::vec::Vec<u8> {
67    fn cbor_len(&self) -> usize {
68        self.as_slice().cbor_len()
69    }
70}
71
72/// Decodes a byte string, supporting both definite-length and indefinite-length encodings.
73#[cfg(feature = "alloc")]
74impl<'a> Decode<'a> for alloc::boxed::Box<[u8]> {
75    type Error = Error;
76    fn decode(d: &mut Decoder<'a>) -> Result<Self, Self::Error> {
77        alloc::vec::Vec::<u8>::decode(d).map(|v| v.into_boxed_slice())
78    }
79}
80
81/// Decodes a byte string, supporting only definite-length encodings.
82impl<const N: usize> Decode<'_> for [u8; N] {
83    type Error = fixed::Error<core::convert::Infallible>;
84
85    fn decode(d: &mut Decoder<'_>) -> Result<Self, Self::Error> {
86        let slice: &[u8] = Decode::decode(d).map_err(collections::Error::Malformed)?;
87        if slice.len() < N {
88            return Err(fixed::Error::Missing);
89        } else if slice.len() > N {
90            return Err(fixed::Error::Surplus);
91        }
92        let mut array = [0u8; N];
93        array.copy_from_slice(slice);
94        Ok(array)
95    }
96}
97
98impl<const N: usize> Encode for [u8; N] {
99    fn encode<W: Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
100        self.as_slice().encode(e)
101    }
102}
103
104impl<const N: usize> CborLen for [u8; N] {
105    fn cbor_len(&self) -> usize {
106        self.as_slice().cbor_len()
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use crate::{
113        InvalidHeader,
114        collections::{self, fixed},
115        test,
116    };
117
118    #[test]
119    fn empty() {
120        assert!(test::<&[u8]>(&[], &[0x40]).unwrap());
121        assert!(test::<[u8; _]>([], &[0x40]).unwrap());
122        #[cfg(feature = "alloc")]
123        {
124            use alloc::{boxed::Box, vec::Vec};
125
126            assert!(test::<Vec<u8>>(Vec::new(), &[0x40]).unwrap());
127            assert!(test::<Box<[u8]>>(Box::new([]), &[0x40]).unwrap());
128        }
129    }
130
131    #[test]
132    fn definite() {
133        let cbor = [0x45, 99, 243, 111, 255, 9];
134        let result = [99, 243, 111, 255, 9];
135
136        assert!(test::<&[u8]>(&result, &cbor).unwrap());
137        assert!(test(result, &cbor).unwrap());
138
139        #[cfg(feature = "alloc")]
140        {
141            use alloc::{boxed::Box, vec::Vec};
142
143            assert!(test(Vec::from(result), &cbor).unwrap());
144            assert!(test(Box::<[u8]>::from(result), &cbor).unwrap());
145        }
146    }
147
148    #[test]
149    fn indefinite() {
150        let err = test::<&[u8]>(&[], &[0x5F, 0x40, 0xFF]).unwrap_err();
151        assert_eq!(err, crate::primitive::Error::InvalidHeader(InvalidHeader));
152        let err = test::<[u8; 0]>([], &[0x5F, 0x40, 0xFF]).unwrap_err();
153        assert_eq!(
154            err,
155            fixed::Error::Collection(collections::Error::Malformed(
156                crate::primitive::Error::InvalidHeader(InvalidHeader)
157            ))
158        );
159
160        #[cfg(feature = "alloc")]
161        {
162            use alloc::{boxed::Box, vec::Vec};
163            let cbor = [0x5f, 0x44, 1, 110, 255, 3, 0xff];
164            let result = [1, 110, 255, 3];
165
166            assert!(!test(Vec::from(result), &cbor).unwrap());
167            assert!(!test(Box::<[u8]>::from(result), &cbor).unwrap());
168
169            let cbor = [0x5f, 0x40, 0x40, 0x40, 0x40, 0xff];
170
171            assert!(!test::<Vec<u8>>(Vec::new(), &cbor).unwrap());
172            assert!(!test::<Box<[u8]>>(Box::new([]), &cbor).unwrap());
173
174            let cbor = [0x5f, 0xff];
175
176            assert!(!test::<Vec<u8>>(Vec::new(), &cbor).unwrap());
177            assert!(!test::<Box<[u8]>>(Box::new([]), &cbor).unwrap());
178        }
179    }
180
181    #[test]
182    fn length_mismatch() {
183        let err = test::<[u8; 3]>([1, 2, 3], &[0x42, 1, 2]).unwrap_err();
184        assert_eq!(err, fixed::Error::Missing);
185        let err = test::<[u8; 2]>([1, 2], &[0x43, 1, 2, 3]).unwrap_err();
186        assert_eq!(err, fixed::Error::Surplus);
187    }
188}