rmp/decode/
mod.rs

1//! Provides various functions and structs for MessagePack decoding.
2//!
3//! Most of the function defined in this module will silently handle interruption error (EINTR)
4//! received from the given `Read` to be in consistent state with the `Write::write_all` method in
5//! the standard library.
6//!
7//! Any other error would immediately interrupt the parsing process. If your reader can results in
8//! I/O error and simultaneously be a recoverable state (for example, when reading from
9//! non-blocking socket and it returns EWOULDBLOCK) be sure that you buffer the data externally
10//! to avoid data loss (using `BufRead` readers with manual consuming or some other way).
11
12mod dec;
13mod ext;
14mod sint;
15mod str;
16mod uint;
17
18#[cfg(feature = "std")]
19mod est;
20#[cfg(feature = "std")]
21pub use est::{MessageLen, LenError};
22
23pub use self::dec::{read_f32, read_f64};
24pub use self::ext::{
25    read_ext_meta, read_fixext1, read_fixext16, read_fixext2, read_fixext4, read_fixext8, ExtMeta,
26};
27pub use self::sint::{read_i16, read_i32, read_i64, read_i8, read_nfix};
28#[allow(deprecated)]
29// While we re-export deprecated items, we don't want to trigger warnings while compiling this crate
30pub use self::str::{read_str, read_str_from_slice, read_str_len, read_str_ref, DecodeStringError};
31pub use self::uint::{read_pfix, read_u16, read_u32, read_u64, read_u8};
32
33use core::fmt::{self, Debug, Display, Formatter};
34#[cfg(feature = "std")]
35use std::error;
36
37use num_traits::cast::FromPrimitive;
38
39use crate::Marker;
40
41pub mod bytes;
42pub use bytes::Bytes;
43
44#[doc(inline)]
45#[allow(deprecated)]
46pub use crate::errors::Error;
47
48/// The error type for I/O operations on `RmpRead` and associated traits.
49///
50/// For [`std::io::Read`], this is [`std::io::Error`]
51pub trait RmpReadErr: Display + Debug + crate::errors::MaybeErrBound + 'static {}
52#[cfg(feature = "std")]
53impl RmpReadErr for std::io::Error {}
54impl RmpReadErr for core::convert::Infallible {}
55
56macro_rules! read_byteorder_utils {
57    ($($name:ident => $tp:ident),* $(,)?) => {
58        $(
59            #[inline]
60            #[doc(hidden)]
61            fn $name(&mut self) -> Result<$tp, ValueReadError<Self::Error>> where Self: Sized {
62                const SIZE: usize = core::mem::size_of::<$tp>();
63                let mut buf: [u8; SIZE] = [0u8; SIZE];
64                self.read_exact_buf(&mut buf).map_err(ValueReadError::InvalidDataRead)?;
65                Ok($tp::from_be_bytes(buf))
66            }
67        )*
68    };
69}
70mod sealed {
71    pub trait Sealed {}
72    #[cfg(feature = "std")]
73    impl<T: ?Sized + std::io::Read> Sealed for T {}
74    #[cfg(not(feature = "std"))]
75    impl<'a> Sealed for &'a [u8] {}
76    impl Sealed for super::Bytes<'_> {}
77}
78
79/// A type that `rmp` supports reading from.
80///
81/// The methods of this trait should be considered an implementation detail (for now).
82/// It is currently sealed (can not be implemented by the user).
83///
84/// Its primary implementations are [`std::io::Read`] and [Bytes].
85pub trait RmpRead: sealed::Sealed {
86    type Error: RmpReadErr;
87    /// Read a single (unsigned) byte from this stream
88    #[inline]
89    fn read_u8(&mut self) -> Result<u8, Self::Error> {
90        let mut buf = [0; 1];
91        self.read_exact_buf(&mut buf)?;
92        Ok(buf[0])
93    }
94
95    /// Read the exact number of bytes needed to fill the specified buffer.
96    ///
97    /// If there are not enough bytes, this will return an error.
98    ///
99    /// See also [`std::io::Read::read_exact`]
100    fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>;
101
102    // Internal helper functions to map I/O error into the `InvalidDataRead` error.
103
104    /// Read a single (unsigned) byte from this stream.
105    #[inline]
106    #[doc(hidden)]
107    fn read_data_u8(&mut self) -> Result<u8, ValueReadError<Self::Error>> {
108        self.read_u8().map_err(ValueReadError::InvalidDataRead)
109    }
110    /// Read a single (signed) byte from this stream.
111    #[inline]
112    #[doc(hidden)]
113    fn read_data_i8(&mut self) -> Result<i8, ValueReadError<Self::Error>> {
114        self.read_data_u8().map(|b| b as i8)
115    }
116
117    read_byteorder_utils!(
118        read_data_u16 => u16,
119        read_data_u32 => u32,
120        read_data_u64 => u64,
121        read_data_i16 => i16,
122        read_data_i32 => i32,
123        read_data_i64 => i64,
124        read_data_f32 => f32,
125        read_data_f64 => f64
126    );
127}
128
129#[cfg(feature = "std")]
130impl<T: std::io::Read> RmpRead for T {
131    type Error = std::io::Error;
132
133    #[inline]
134    fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
135        std::io::Read::read_exact(self, buf)
136    }
137}
138
139/// An error that can occur when attempting to read a MessagePack marker from the reader.
140#[derive(Debug)]
141#[allow(deprecated)] // Needed for backwards compat
142pub struct MarkerReadError<E: RmpReadErr = Error>(pub E);
143
144/// An error which can occur when attempting to read a MessagePack value from the reader.
145#[derive(Debug)]
146#[allow(deprecated)] // Needed for backwards compat
147pub enum ValueReadError<E: RmpReadErr = Error> {
148    /// Failed to read the marker.
149    InvalidMarkerRead(E),
150    /// Failed to read the data.
151    InvalidDataRead(E),
152    /// The type decoded isn't match with the expected one.
153    TypeMismatch(Marker),
154}
155
156#[cfg(feature = "std")]
157impl error::Error for ValueReadError {
158    #[cold]
159    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
160        match *self {
161            Self::InvalidMarkerRead(ref err) |
162            Self::InvalidDataRead(ref err) => Some(err),
163            Self::TypeMismatch(..) => None,
164        }
165    }
166}
167
168impl Display for ValueReadError {
169    #[cold]
170    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
171        // TODO: This should probably use formatting
172        f.write_str(match *self {
173            Self::InvalidMarkerRead(..) => "failed to read MessagePack marker",
174            Self::InvalidDataRead(..) => "failed to read MessagePack data",
175            Self::TypeMismatch(..) => "the type decoded isn't match with the expected one",
176        })
177    }
178}
179
180impl<E: RmpReadErr> From<MarkerReadError<E>> for ValueReadError<E> {
181    #[cold]
182    fn from(err: MarkerReadError<E>) -> Self {
183        match err {
184            MarkerReadError(err) => Self::InvalidMarkerRead(err),
185        }
186    }
187}
188
189impl<E: RmpReadErr> From<E> for MarkerReadError<E> {
190    #[cold]
191    fn from(err: E) -> Self {
192        Self(err)
193    }
194}
195
196/// Attempts to read a single byte from the given reader and to decode it as a MessagePack marker.
197#[inline]
198pub fn read_marker<R: RmpRead>(rd: &mut R) -> Result<Marker, MarkerReadError<R::Error>> {
199    Ok(Marker::from_u8(rd.read_u8()?))
200}
201
202/// Attempts to read a single byte from the given reader and to decode it as a nil value.
203///
204/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
205///
206/// # Errors
207///
208/// This function will return `ValueReadError` on any I/O error while reading the nil marker,
209/// except the EINTR, which is handled internally.
210///
211/// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the
212/// expected one, indicating you with the actual type.
213///
214/// # Note
215///
216/// This function will silently retry on every EINTR received from the underlying `Read` until
217/// successful read.
218pub fn read_nil<R: RmpRead>(rd: &mut R) -> Result<(), ValueReadError<R::Error>> {
219    match read_marker(rd)? {
220        Marker::Null => Ok(()),
221        marker => Err(ValueReadError::TypeMismatch(marker)),
222    }
223}
224
225/// Attempts to read a single byte from the given reader and to decode it as a boolean value.
226///
227/// According to the MessagePack specification, an encoded boolean value is represented as a single
228/// byte.
229///
230/// # Errors
231///
232/// This function will return `ValueReadError` on any I/O error while reading the bool marker,
233/// except the EINTR, which is handled internally.
234///
235/// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the
236/// expected one, indicating you with the actual type.
237///
238/// # Note
239///
240/// This function will silently retry on every EINTR received from the underlying `Read` until
241/// successful read.
242pub fn read_bool<R: RmpRead>(rd: &mut R) -> Result<bool, ValueReadError<R::Error>> {
243    match read_marker(rd)? {
244        Marker::True => Ok(true),
245        Marker::False => Ok(false),
246        marker => Err(ValueReadError::TypeMismatch(marker)),
247    }
248}
249
250/// An error which can occur when attempting to read a MessagePack numeric value from the reader.
251#[derive(Debug)]
252#[allow(deprecated)] // Used for compatibility
253pub enum NumValueReadError<E: RmpReadErr = Error> {
254    /// Failed to read the marker.
255    InvalidMarkerRead(E),
256    /// Failed to read the data.
257    InvalidDataRead(E),
258    /// The type decoded isn't match with the expected one.
259    TypeMismatch(Marker),
260    /// Out of range integral type conversion attempted.
261    OutOfRange,
262}
263
264#[cfg(feature = "std")]
265impl error::Error for NumValueReadError {
266    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
267        match *self {
268            Self::InvalidMarkerRead(ref err) |
269            Self::InvalidDataRead(ref err) => Some(err),
270            Self::TypeMismatch(..) |
271            Self::OutOfRange => None,
272        }
273    }
274}
275
276impl<E: RmpReadErr> Display for NumValueReadError<E> {
277    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
278        f.write_str(match *self {
279            Self::InvalidMarkerRead(..) => "failed to read MessagePack marker",
280            Self::InvalidDataRead(..) => "failed to read MessagePack data",
281            Self::TypeMismatch(..) => "the type decoded isn't match with the expected one",
282            Self::OutOfRange => "out of range integral type conversion attempted",
283        })
284    }
285}
286
287impl<E: RmpReadErr> From<MarkerReadError<E>> for NumValueReadError<E> {
288    #[cold]
289    fn from(err: MarkerReadError<E>) -> Self {
290        match err {
291            MarkerReadError(err) => Self::InvalidMarkerRead(err),
292        }
293    }
294}
295
296impl<E: RmpReadErr> From<ValueReadError<E>> for NumValueReadError<E> {
297    #[cold]
298    fn from(err: ValueReadError<E>) -> Self {
299        match err {
300            ValueReadError::InvalidMarkerRead(err) => Self::InvalidMarkerRead(err),
301            ValueReadError::InvalidDataRead(err) => Self::InvalidDataRead(err),
302            ValueReadError::TypeMismatch(err) => Self::TypeMismatch(err),
303        }
304    }
305}
306
307/// Attempts to read up to 9 bytes from the given reader and to decode them as integral `T` value.
308///
309/// This function will try to read up to 9 bytes from the reader (1 for marker and up to 8 for data)
310/// and interpret them as a big-endian `T`.
311///
312/// Unlike `read_*`, this function weakens type restrictions, allowing you to safely decode packed
313/// values even if you aren't sure about the actual integral type.
314///
315/// # Errors
316///
317/// This function will return `NumValueReadError` on any I/O error while reading either the marker
318/// or the data.
319///
320/// It also returns `NumValueReadError::OutOfRange` if the actual type is not an integer or it does
321/// not fit in the given numeric range.
322///
323/// # Examples
324///
325/// ```
326/// let buf = [0xcd, 0x1, 0x2c];
327///
328/// assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap());
329/// assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap());
330/// assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap());
331/// assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap());
332/// assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap());
333/// assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap());
334/// assert_eq!(300usize, rmp::decode::read_int(&mut &buf[..]).unwrap());
335/// assert_eq!(300isize, rmp::decode::read_int(&mut &buf[..]).unwrap());
336/// ```
337pub fn read_int<T: FromPrimitive, R: RmpRead>(rd: &mut R) -> Result<T, NumValueReadError<R::Error>> {
338    let val = match read_marker(rd)? {
339        Marker::FixPos(val) => T::from_u8(val),
340        Marker::FixNeg(val) => T::from_i8(val),
341        Marker::U8 => T::from_u8(rd.read_data_u8()?),
342        Marker::U16 => T::from_u16(rd.read_data_u16()?),
343        Marker::U32 => T::from_u32(rd.read_data_u32()?),
344        Marker::U64 => T::from_u64(rd.read_data_u64()?),
345        Marker::I8 => T::from_i8(rd.read_data_i8()?),
346        Marker::I16 => T::from_i16(rd.read_data_i16()?),
347        Marker::I32 => T::from_i32(rd.read_data_i32()?),
348        Marker::I64 => T::from_i64(rd.read_data_i64()?),
349        marker => return Err(NumValueReadError::TypeMismatch(marker)),
350    };
351
352    val.ok_or(NumValueReadError::OutOfRange)
353}
354
355/// Attempts to read up to 5 bytes from the given reader and to decode them as a big-endian u32
356/// array size.
357///
358/// Array format family stores a sequence of elements in 1, 3, or 5 bytes of extra bytes in addition
359/// to the elements.
360///
361/// # Note
362///
363/// This function will silently retry on every EINTR received from the underlying `Read` until
364/// successful read.
365// TODO: Docs.
366// NOTE: EINTR is managed internally.
367pub fn read_array_len<R>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>>
368where
369    R: RmpRead,
370{
371    match read_marker(rd)? {
372        Marker::FixArray(size) => Ok(u32::from(size)),
373        Marker::Array16 => Ok(u32::from(rd.read_data_u16()?)),
374        Marker::Array32 => Ok(rd.read_data_u32()?),
375        marker => Err(ValueReadError::TypeMismatch(marker)),
376    }
377}
378
379/// Attempts to read up to 5 bytes from the given reader and to decode them as a big-endian u32
380/// map size.
381///
382/// Map format family stores a sequence of elements in 1, 3, or 5 bytes of extra bytes in addition
383/// to the elements.
384///
385/// # Note
386///
387/// This function will silently retry on every EINTR received from the underlying `Read` until
388/// successful read.
389// TODO: Docs.
390pub fn read_map_len<R: RmpRead>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>> {
391    let marker = read_marker(rd)?;
392    marker_to_len(rd, marker)
393}
394
395pub fn marker_to_len<R: RmpRead>(rd: &mut R, marker: Marker) -> Result<u32, ValueReadError<R::Error>> {
396    match marker {
397        Marker::FixMap(size) => Ok(u32::from(size)),
398        Marker::Map16 => Ok(u32::from(rd.read_data_u16()?)),
399        Marker::Map32 => Ok(rd.read_data_u32()?),
400        marker => Err(ValueReadError::TypeMismatch(marker)),
401    }
402}
403
404/// Attempts to read up to 5 bytes from the given reader and to decode them as Binary array length.
405///
406/// # Note
407///
408/// This function will silently retry on every EINTR received from the underlying `Read` until
409/// successful read.
410// TODO: Docs.
411pub fn read_bin_len<R: RmpRead>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>> {
412    match read_marker(rd)? {
413        Marker::Bin8 => Ok(u32::from(rd.read_data_u8()?)),
414        Marker::Bin16 => Ok(u32::from(rd.read_data_u16()?)),
415        Marker::Bin32 => Ok(rd.read_data_u32()?),
416        marker => Err(ValueReadError::TypeMismatch(marker)),
417    }
418}