messagepack_core/decode/
bin.rs

1//! Binary (bin8/16/32) decoding helpers.
2
3use super::{Error, NbyteReader};
4use crate::{Decode, decode::DecodeBorrowed, formats::Format, io::IoRead};
5
6/// Decode a MessagePack binary blob and return a borrowed byte slice.
7pub struct BinDecoder;
8
9impl<'de> DecodeBorrowed<'de> for BinDecoder {
10    type Value = &'de [u8];
11
12    fn decode_borrowed_with_format<R>(
13        format: Format,
14        reader: &mut R,
15    ) -> core::result::Result<Self::Value, Error<R::Error>>
16    where
17        R: IoRead<'de>,
18    {
19        let data = ReferenceDecoder::decode_with_format(format, reader)?;
20        match data {
21            crate::io::Reference::Borrowed(b) => Ok(b),
22            crate::io::Reference::Copied(_) => Err(Error::InvalidData),
23        }
24    }
25}
26
27impl<'de> DecodeBorrowed<'de> for &'de [u8] {
28    type Value = &'de [u8];
29
30    fn decode_borrowed_with_format<R>(
31        format: Format,
32        reader: &mut R,
33    ) -> core::result::Result<Self::Value, Error<R::Error>>
34    where
35        R: IoRead<'de>,
36    {
37        BinDecoder::decode_borrowed_with_format(format, reader)
38    }
39}
40
41/// Decode a MessagePack binary and return a `Reference` to its bytes
42pub struct ReferenceDecoder;
43
44impl<'de> super::Decode<'de> for ReferenceDecoder {
45    type Value<'a>
46        = crate::io::Reference<'de, 'a>
47    where
48        Self: 'a,
49        'de: 'a;
50    fn decode_with_format<'a, R>(
51        format: Format,
52        reader: &'a mut R,
53    ) -> Result<Self::Value<'a>, Error<R::Error>>
54    where
55        R: IoRead<'de>,
56        'de: 'a,
57    {
58        let len = match format {
59            Format::Bin8 => NbyteReader::<1>::read(reader)?,
60            Format::Bin16 => NbyteReader::<2>::read(reader)?,
61            Format::Bin32 => NbyteReader::<4>::read(reader)?,
62            _ => return Err(Error::UnexpectedFormat),
63        };
64        let data = reader.read_slice(len).map_err(Error::Io)?;
65        Ok(data)
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72    use crate::decode::Decode;
73    #[test]
74    fn decode_bin8() {
75        let expect = r#"
76MessagePack
77"#
78        .as_bytes();
79        let len = u8::try_from(expect.len()).unwrap();
80        let buf = [0xc4_u8]
81            .into_iter()
82            .chain(len.to_be_bytes())
83            .chain(expect.iter().cloned())
84            .collect::<Vec<_>>();
85
86        let mut r = crate::io::SliceReader::new(&buf);
87        let decoded = BinDecoder::decode(&mut r).unwrap();
88        assert_eq!(decoded, expect);
89        assert_eq!(r.rest().len(), 0);
90    }
91
92    #[test]
93    fn decode_bin16() {
94        let expect = r#"
95MessagePack is an object serialization specification like JSON.
96
97MessagePack has two concepts: type system and formats.
98
99Serialization is conversion from application objects into MessagePack formats via MessagePack type system.
100
101Deserialization is conversion from MessagePack formats into application objects via MessagePack type system.
102"#.as_bytes();
103        let len = u16::try_from(expect.len()).unwrap();
104        let buf = [0xc5_u8]
105            .into_iter()
106            .chain(len.to_be_bytes())
107            .chain(expect.iter().cloned())
108            .collect::<Vec<_>>();
109
110        let mut r = crate::io::SliceReader::new(&buf);
111        let decoded = BinDecoder::decode(&mut r).unwrap();
112        assert_eq!(decoded, expect);
113        assert_eq!(r.rest().len(), 0);
114    }
115
116    #[test]
117    fn decode_bin32() {
118        let expect = include_str!("bin.rs").as_bytes();
119        let len = u32::try_from(expect.len()).unwrap();
120        let buf = [0xc6_u8]
121            .into_iter()
122            .chain(len.to_be_bytes())
123            .chain(expect.iter().cloned())
124            .collect::<Vec<_>>();
125
126        let mut r = crate::io::SliceReader::new(&buf);
127        let decoded = BinDecoder::decode(&mut r).unwrap();
128        assert_eq!(decoded, expect);
129        assert_eq!(r.rest().len(), 0);
130    }
131}