Skip to main content

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/// Trait for decoding MessagePack binary data.
70///
71/// Used by the derive macro for `#[msgpack(bytes)]` fields.
72/// Implement this trait for types that can be decoded from a MessagePack bin format.
73pub trait DecodeBytes<'de>: Sized {
74    /// Decode binary data from the reader.
75    fn decode_bytes<R>(reader: &mut R) -> Result<Self, Error<R::Error>>
76    where
77        R: IoRead<'de>,
78    {
79        let format = Format::decode(reader)?;
80        Self::decode_bytes_with_format(format, reader)
81    }
82
83    /// Decode binary data from the reader, given the initial format.
84    fn decode_bytes_with_format<R>(format: Format, reader: &mut R) -> Result<Self, Error<R::Error>>
85    where
86        R: IoRead<'de>;
87}
88
89impl<'de> DecodeBytes<'de> for &'de [u8] {
90    fn decode_bytes_with_format<R>(format: Format, reader: &mut R) -> Result<Self, Error<R::Error>>
91    where
92        R: IoRead<'de>,
93    {
94        <&'de [u8] as DecodeBorrowed<'de>>::decode_borrowed_with_format(format, reader)
95    }
96}
97
98impl<'de, const N: usize> DecodeBytes<'de> for [u8; N] {
99    fn decode_bytes_with_format<R>(format: Format, reader: &mut R) -> Result<Self, Error<R::Error>>
100    where
101        R: IoRead<'de>,
102    {
103        let reference = ReferenceDecoder::decode_with_format(format, reader)?;
104        let bytes = reference.as_bytes();
105        bytes.try_into().map_err(|_| Error::InvalidData)
106    }
107}
108
109impl<'de, T> DecodeBytes<'de> for Option<T>
110where
111    T: DecodeBytes<'de>,
112{
113    fn decode_bytes_with_format<R>(format: Format, reader: &mut R) -> Result<Self, Error<R::Error>>
114    where
115        R: IoRead<'de>,
116    {
117        match format {
118            Format::Nil => Ok(None),
119            _ => T::decode_bytes_with_format(format, reader).map(Some),
120        }
121    }
122}
123
124#[cfg(feature = "alloc")]
125mod alloc_impl {
126    use super::*;
127    /// Owned `Vec<u8>` decoder for MessagePack bin8/16/32.
128    pub struct BinOwnedDecoder;
129
130    impl<'de> super::DecodeBorrowed<'de> for BinOwnedDecoder {
131        type Value = alloc::vec::Vec<u8>;
132
133        fn decode_borrowed_with_format<R>(
134            format: Format,
135            reader: &mut R,
136        ) -> Result<<Self as DecodeBorrowed<'de>>::Value, Error<R::Error>>
137        where
138            R: IoRead<'de>,
139        {
140            let val = ReferenceDecoder::decode_with_format(format, reader)?;
141            Ok(val.as_bytes().to_vec())
142        }
143    }
144
145    impl<'de> DecodeBytes<'de> for alloc::vec::Vec<u8> {
146        fn decode_bytes_with_format<R>(
147            format: Format,
148            reader: &mut R,
149        ) -> Result<Self, Error<R::Error>>
150        where
151            R: IoRead<'de>,
152        {
153            ReferenceDecoder::decode_with_format(format, reader).map(|b| b.as_bytes().into())
154        }
155    }
156
157    impl<'de> DecodeBytes<'de> for alloc::boxed::Box<[u8]> {
158        fn decode_bytes_with_format<R>(
159            format: Format,
160            reader: &mut R,
161        ) -> Result<Self, Error<R::Error>>
162        where
163            R: IoRead<'de>,
164        {
165            ReferenceDecoder::decode_with_format(format, reader).map(|b| b.as_bytes().into())
166        }
167    }
168}
169#[cfg(feature = "alloc")]
170pub use alloc_impl::BinOwnedDecoder;
171
172#[cfg(test)]
173mod tests {
174    use super::*;
175    use crate::decode::Decode;
176    #[test]
177    fn decode_bin8() {
178        let expect = r#"
179MessagePack
180"#
181        .as_bytes();
182        let len = u8::try_from(expect.len()).unwrap();
183        let buf = [0xc4_u8]
184            .into_iter()
185            .chain(len.to_be_bytes())
186            .chain(expect.iter().cloned())
187            .collect::<Vec<_>>();
188
189        let mut r = crate::io::SliceReader::new(&buf);
190        let decoded = BinDecoder::decode(&mut r).unwrap();
191        assert_eq!(decoded, expect);
192        assert_eq!(r.rest().len(), 0);
193    }
194
195    #[test]
196    fn decode_bin16() {
197        let expect = r#"
198MessagePack is an object serialization specification like JSON.
199
200MessagePack has two concepts: type system and formats.
201
202Serialization is conversion from application objects into MessagePack formats via MessagePack type system.
203
204Deserialization is conversion from MessagePack formats into application objects via MessagePack type system.
205"#.as_bytes();
206        let len = u16::try_from(expect.len()).unwrap();
207        let buf = [0xc5_u8]
208            .into_iter()
209            .chain(len.to_be_bytes())
210            .chain(expect.iter().cloned())
211            .collect::<Vec<_>>();
212
213        let mut r = crate::io::SliceReader::new(&buf);
214        let decoded = BinDecoder::decode(&mut r).unwrap();
215        assert_eq!(decoded, expect);
216        assert_eq!(r.rest().len(), 0);
217    }
218
219    #[test]
220    fn decode_bin32() {
221        let expect = include_str!("bin.rs").as_bytes();
222        let len = u32::try_from(expect.len()).unwrap();
223        let buf = [0xc6_u8]
224            .into_iter()
225            .chain(len.to_be_bytes())
226            .chain(expect.iter().cloned())
227            .collect::<Vec<_>>();
228
229        let mut r = crate::io::SliceReader::new(&buf);
230        let decoded = BinDecoder::decode(&mut r).unwrap();
231        assert_eq!(decoded, expect);
232        assert_eq!(r.rest().len(), 0);
233    }
234
235    #[cfg(feature = "alloc")]
236    #[test]
237    fn decode_vec_u8_owned() {
238        // bin8 with 3 bytes
239        let buf = [0xc4, 0x03, 0x01, 0x02, 0x03];
240        let mut r = crate::io::SliceReader::new(&buf);
241        let v = <BinOwnedDecoder as Decode>::decode(&mut r).unwrap();
242        assert_eq!(v, alloc::vec![1u8, 2, 3]);
243        assert!(r.rest().is_empty());
244    }
245}