messagepack_core/decode/
mod.rs

1//! Decoding primitives for MessagePack.
2
3use crate::{Format, io::IoRead};
4
5mod array;
6pub use array::ArrayDecoder;
7mod bin;
8#[cfg(feature = "alloc")]
9pub use bin::BinOwnedDecoder;
10pub use bin::ReferenceDecoder;
11mod bool;
12mod float;
13mod int;
14mod map;
15pub use map::MapDecoder;
16mod nil;
17pub use nil::NilDecoder;
18mod str;
19pub use str::{ReferenceStr, ReferenceStrDecoder};
20
21/// MessagePack decode error
22#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
23pub enum Error<E> {
24    /// Invalid data
25    InvalidData,
26    /// Unexpected format
27    UnexpectedFormat,
28    /// Unexpected end of data
29    UnexpectedEof,
30    /// Io error while decode format
31    Io(E),
32}
33
34impl<E> core::fmt::Display for Error<E>
35where
36    E: core::fmt::Display,
37{
38    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39        match self {
40            Error::InvalidData => write!(f, "Cannot decode invalid data"),
41            Error::UnexpectedFormat => write!(f, "Unexpected format found"),
42            Error::UnexpectedEof => write!(f, "Unexpected end of data"),
43            Error::Io(e) => e.fmt(f),
44        }
45    }
46}
47
48impl<E> core::error::Error for Error<E>
49where
50    E: core::error::Error + 'static,
51{
52    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
53        match self {
54            Error::Io(e) => Some(e),
55            _ => None,
56        }
57    }
58}
59
60/// Decode a value from MessagePack.
61///
62/// Returned values may borrow from the reader's buffer with lifetime
63/// `'a` (bounded by `'de`).
64pub trait Decode<'de> {
65    /// The decoded value (may borrow for `'a`).
66    type Value<'a>: Sized
67    where
68        Self: 'a,
69        'de: 'a;
70    /// Decode the next value.
71    fn decode<'a, R>(reader: &'a mut R) -> Result<Self::Value<'a>, Error<R::Error>>
72    where
73        R: IoRead<'de>,
74        'de: 'a,
75    {
76        // Avoid recursive call when `Self = Format` by decoding the marker
77        // via `DecodeBorrowed` explicitly.
78        let format = <Format as DecodeBorrowed<'de>>::decode_borrowed(reader)?;
79        Self::decode_with_format(format, reader)
80    }
81
82    /// Decode with a previously read `Format`.
83    fn decode_with_format<'a, R>(
84        format: Format,
85        reader: &'a mut R,
86    ) -> Result<Self::Value<'a>, Error<R::Error>>
87    where
88        R: IoRead<'de>,
89        'de: 'a;
90}
91
92/// Decode a value whose borrows are bounded by `'de`.
93///
94/// Implementations must not return references to the reader's transient buffer.
95pub trait DecodeBorrowed<'de> {
96    /// The decoded value.
97    type Value;
98
99    /// Decode the next value.
100    fn decode_borrowed<R>(
101        reader: &mut R,
102    ) -> Result<<Self as DecodeBorrowed<'de>>::Value, Error<R::Error>>
103    where
104        R: IoRead<'de>,
105    {
106        let format = <Format as DecodeBorrowed<'de>>::decode_borrowed(reader)?;
107        Self::decode_borrowed_with_format(format, reader)
108    }
109
110    /// Decode with a previously read `Format`.
111    fn decode_borrowed_with_format<R>(
112        format: Format,
113        reader: &mut R,
114    ) -> Result<<Self as DecodeBorrowed<'de>>::Value, Error<R::Error>>
115    where
116        R: IoRead<'de>;
117}
118
119impl<'de, T> Decode<'de> for T
120where
121    T: DecodeBorrowed<'de>,
122    T: 'de,
123{
124    type Value<'a>
125        = <T as DecodeBorrowed<'de>>::Value
126    where
127        Self: 'a,
128        'de: 'a;
129
130    fn decode_with_format<'a, R>(
131        format: Format,
132        reader: &'a mut R,
133    ) -> Result<Self::Value<'a>, Error<R::Error>>
134    where
135        R: IoRead<'de>,
136        'de: 'a,
137    {
138        <T as DecodeBorrowed<'de>>::decode_borrowed_with_format(format, reader)
139    }
140}
141
142impl<'de> DecodeBorrowed<'de> for Format {
143    type Value = Self;
144    fn decode_borrowed<R>(reader: &mut R) -> Result<Self::Value, Error<R::Error>>
145    where
146        R: IoRead<'de>,
147    {
148        let b = reader.read_slice(1).map_err(Error::Io)?;
149        let byte: [u8; 1] = b.as_bytes().try_into().map_err(|_| Error::UnexpectedEof)?;
150
151        Ok(Self::from_byte(byte[0]))
152    }
153
154    fn decode_borrowed_with_format<R>(
155        format: Format,
156        _reader: &mut R,
157    ) -> Result<Self::Value, Error<R::Error>>
158    where
159        R: IoRead<'de>,
160    {
161        Ok(format)
162    }
163}
164
165/// Helper to read a fixed number of big‑endian bytes and return them as `usize`.
166pub struct NbyteReader<const NBYTE: usize>;
167
168macro_rules! impl_read {
169    ($ty:ty) => {
170        /// Read the next big‑endian integer of type `$ty` and return it as
171        /// `usize` from `reader`.
172        pub fn read<'de, R>(reader: &mut R) -> core::result::Result<usize, Error<R::Error>>
173        where
174            R: IoRead<'de>,
175        {
176            const SIZE: usize = core::mem::size_of::<$ty>();
177            let bytes = reader.read_slice(SIZE).map_err(Error::Io)?;
178            let slice = bytes.as_bytes();
179            let data: [u8; SIZE] = slice.try_into().map_err(|_| Error::UnexpectedEof)?;
180            let val =
181                usize::try_from(<$ty>::from_be_bytes(data)).map_err(|_| Error::InvalidData)?;
182            Ok(val)
183        }
184    };
185}
186
187impl NbyteReader<1> {
188    impl_read! {u8}
189}
190
191impl NbyteReader<2> {
192    impl_read! {u16}
193}
194impl NbyteReader<4> {
195    impl_read! {u32}
196}