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