Coverage Report

Created: 2026-07-13 08:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rmp-0.8.15/src/decode/mod.rs
Line
Count
Source
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
12
mod dec;
13
mod ext;
14
mod sint;
15
mod str;
16
mod uint;
17
18
#[cfg(feature = "std")]
19
mod est;
20
#[cfg(feature = "std")]
21
pub use est::{MessageLen, LenError};
22
23
pub use self::dec::{read_f32, read_f64};
24
pub use self::ext::{
25
    read_ext_meta, read_fixext1, read_fixext16, read_fixext2, read_fixext4, read_fixext8, ExtMeta,
26
};
27
pub 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
30
pub use self::str::{read_str, read_str_from_slice, read_str_len, read_str_ref, DecodeStringError};
31
pub use self::uint::{read_pfix, read_u16, read_u32, read_u64, read_u8};
32
33
use core::fmt::{self, Debug, Display, Formatter};
34
#[cfg(feature = "std")]
35
use std::error;
36
37
use num_traits::cast::FromPrimitive;
38
39
use crate::Marker;
40
41
pub mod bytes;
42
pub use bytes::Bytes;
43
44
#[doc(inline)]
45
#[allow(deprecated)]
46
pub 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`]
51
pub trait RmpReadErr: Display + Debug + crate::errors::MaybeErrBound + 'static {}
52
#[cfg(feature = "std")]
53
impl RmpReadErr for std::io::Error {}
54
impl RmpReadErr for core::convert::Infallible {}
55
56
macro_rules! read_byteorder_utils {
57
    ($($name:ident => $tp:ident),* $(,)?) => {
58
        $(
59
            #[inline]
60
            #[doc(hidden)]
61
0
            fn $name(&mut self) -> Result<$tp, ValueReadError<Self::Error>> where Self: Sized {
62
                const SIZE: usize = core::mem::size_of::<$tp>();
63
0
                let mut buf: [u8; SIZE] = [0u8; SIZE];
64
0
                self.read_exact_buf(&mut buf).map_err(ValueReadError::InvalidDataRead)?;
65
0
                Ok($tp::from_be_bytes(buf))
66
0
            }
Unexecuted instantiation: <rmp::decode::bytes::Bytes as rmp::decode::RmpRead>::read_data_u16
Unexecuted instantiation: <rmp::decode::bytes::Bytes as rmp::decode::RmpRead>::read_data_u32
Unexecuted instantiation: <_ as rmp::decode::RmpRead>::read_data_f32
Unexecuted instantiation: <_ as rmp::decode::RmpRead>::read_data_f64
Unexecuted instantiation: <_ as rmp::decode::RmpRead>::read_data_i16
Unexecuted instantiation: <_ as rmp::decode::RmpRead>::read_data_i32
Unexecuted instantiation: <_ as rmp::decode::RmpRead>::read_data_i64
Unexecuted instantiation: <_ as rmp::decode::RmpRead>::read_data_u64
67
        )*
68
    };
69
}
70
mod 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].
85
pub trait RmpRead: sealed::Sealed {
86
    type Error: RmpReadErr;
87
    /// Read a single (unsigned) byte from this stream
88
    #[inline]
89
0
    fn read_u8(&mut self) -> Result<u8, Self::Error> {
90
0
        let mut buf = [0; 1];
91
0
        self.read_exact_buf(&mut buf)?;
92
0
        Ok(buf[0])
93
0
    }
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
0
    fn read_data_u8(&mut self) -> Result<u8, ValueReadError<Self::Error>> {
108
0
        self.read_u8().map_err(ValueReadError::InvalidDataRead)
109
0
    }
110
    /// Read a single (signed) byte from this stream.
111
    #[inline]
112
    #[doc(hidden)]
113
0
    fn read_data_i8(&mut self) -> Result<i8, ValueReadError<Self::Error>> {
114
0
        self.read_data_u8().map(|b| b as i8)
115
0
    }
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")]
130
impl<T: std::io::Read> RmpRead for T {
131
    type Error = std::io::Error;
132
133
    #[inline]
134
0
    fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
135
0
        std::io::Read::read_exact(self, buf)
136
0
    }
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
142
pub 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
147
pub 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")]
157
impl error::Error for ValueReadError {
158
    #[cold]
159
0
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
160
0
        match *self {
161
0
            Self::InvalidMarkerRead(ref err) |
162
0
            Self::InvalidDataRead(ref err) => Some(err),
163
0
            Self::TypeMismatch(..) => None,
164
        }
165
0
    }
166
}
167
168
impl Display for ValueReadError {
169
    #[cold]
170
0
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
171
        // TODO: This should probably use formatting
172
0
        f.write_str(match *self {
173
0
            Self::InvalidMarkerRead(..) => "failed to read MessagePack marker",
174
0
            Self::InvalidDataRead(..) => "failed to read MessagePack data",
175
0
            Self::TypeMismatch(..) => "the type decoded isn't match with the expected one",
176
        })
177
0
    }
178
}
179
180
impl<E: RmpReadErr> From<MarkerReadError<E>> for ValueReadError<E> {
181
    #[cold]
182
0
    fn from(err: MarkerReadError<E>) -> Self {
183
0
        match err {
184
0
            MarkerReadError(err) => Self::InvalidMarkerRead(err),
185
        }
186
0
    }
187
}
188
189
impl<E: RmpReadErr> From<E> for MarkerReadError<E> {
190
    #[cold]
191
0
    fn from(err: E) -> Self {
192
0
        Self(err)
193
0
    }
194
}
195
196
/// Attempts to read a single byte from the given reader and to decode it as a MessagePack marker.
197
#[inline]
198
0
pub fn read_marker<R: RmpRead>(rd: &mut R) -> Result<Marker, MarkerReadError<R::Error>> {
199
0
    Ok(Marker::from_u8(rd.read_u8()?))
200
0
}
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.
218
0
pub fn read_nil<R: RmpRead>(rd: &mut R) -> Result<(), ValueReadError<R::Error>> {
219
0
    match read_marker(rd)? {
220
0
        Marker::Null => Ok(()),
221
0
        marker => Err(ValueReadError::TypeMismatch(marker)),
222
    }
223
0
}
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.
242
0
pub fn read_bool<R: RmpRead>(rd: &mut R) -> Result<bool, ValueReadError<R::Error>> {
243
0
    match read_marker(rd)? {
244
0
        Marker::True => Ok(true),
245
0
        Marker::False => Ok(false),
246
0
        marker => Err(ValueReadError::TypeMismatch(marker)),
247
    }
248
0
}
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
253
pub 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")]
265
impl error::Error for NumValueReadError {
266
0
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
267
0
        match *self {
268
0
            Self::InvalidMarkerRead(ref err) |
269
0
            Self::InvalidDataRead(ref err) => Some(err),
270
0
            Self::TypeMismatch(..) |
271
0
            Self::OutOfRange => None,
272
        }
273
0
    }
274
}
275
276
impl<E: RmpReadErr> Display for NumValueReadError<E> {
277
0
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
278
0
        f.write_str(match *self {
279
0
            Self::InvalidMarkerRead(..) => "failed to read MessagePack marker",
280
0
            Self::InvalidDataRead(..) => "failed to read MessagePack data",
281
0
            Self::TypeMismatch(..) => "the type decoded isn't match with the expected one",
282
0
            Self::OutOfRange => "out of range integral type conversion attempted",
283
        })
284
0
    }
285
}
286
287
impl<E: RmpReadErr> From<MarkerReadError<E>> for NumValueReadError<E> {
288
    #[cold]
289
0
    fn from(err: MarkerReadError<E>) -> Self {
290
0
        match err {
291
0
            MarkerReadError(err) => Self::InvalidMarkerRead(err),
292
        }
293
0
    }
294
}
295
296
impl<E: RmpReadErr> From<ValueReadError<E>> for NumValueReadError<E> {
297
    #[cold]
298
0
    fn from(err: ValueReadError<E>) -> Self {
299
0
        match err {
300
0
            ValueReadError::InvalidMarkerRead(err) => Self::InvalidMarkerRead(err),
301
0
            ValueReadError::InvalidDataRead(err) => Self::InvalidDataRead(err),
302
0
            ValueReadError::TypeMismatch(err) => Self::TypeMismatch(err),
303
        }
304
0
    }
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
/// ```
337
0
pub fn read_int<T: FromPrimitive, R: RmpRead>(rd: &mut R) -> Result<T, NumValueReadError<R::Error>> {
338
0
    let val = match read_marker(rd)? {
339
0
        Marker::FixPos(val) => T::from_u8(val),
340
0
        Marker::FixNeg(val) => T::from_i8(val),
341
0
        Marker::U8 => T::from_u8(rd.read_data_u8()?),
342
0
        Marker::U16 => T::from_u16(rd.read_data_u16()?),
343
0
        Marker::U32 => T::from_u32(rd.read_data_u32()?),
344
0
        Marker::U64 => T::from_u64(rd.read_data_u64()?),
345
0
        Marker::I8 => T::from_i8(rd.read_data_i8()?),
346
0
        Marker::I16 => T::from_i16(rd.read_data_i16()?),
347
0
        Marker::I32 => T::from_i32(rd.read_data_i32()?),
348
0
        Marker::I64 => T::from_i64(rd.read_data_i64()?),
349
0
        marker => return Err(NumValueReadError::TypeMismatch(marker)),
350
    };
351
352
0
    val.ok_or(NumValueReadError::OutOfRange)
353
0
}
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.
367
0
pub fn read_array_len<R>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>>
368
0
where
369
0
    R: RmpRead,
370
{
371
0
    match read_marker(rd)? {
372
0
        Marker::FixArray(size) => Ok(u32::from(size)),
373
0
        Marker::Array16 => Ok(u32::from(rd.read_data_u16()?)),
374
0
        Marker::Array32 => Ok(rd.read_data_u32()?),
375
0
        marker => Err(ValueReadError::TypeMismatch(marker)),
376
    }
377
0
}
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.
390
0
pub fn read_map_len<R: RmpRead>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>> {
391
0
    let marker = read_marker(rd)?;
392
0
    marker_to_len(rd, marker)
393
0
}
394
395
0
pub fn marker_to_len<R: RmpRead>(rd: &mut R, marker: Marker) -> Result<u32, ValueReadError<R::Error>> {
396
0
    match marker {
397
0
        Marker::FixMap(size) => Ok(u32::from(size)),
398
0
        Marker::Map16 => Ok(u32::from(rd.read_data_u16()?)),
399
0
        Marker::Map32 => Ok(rd.read_data_u32()?),
400
0
        marker => Err(ValueReadError::TypeMismatch(marker)),
401
    }
402
0
}
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.
411
0
pub fn read_bin_len<R: RmpRead>(rd: &mut R) -> Result<u32, ValueReadError<R::Error>> {
412
0
    match read_marker(rd)? {
413
0
        Marker::Bin8 => Ok(u32::from(rd.read_data_u8()?)),
414
0
        Marker::Bin16 => Ok(u32::from(rd.read_data_u16()?)),
415
0
        Marker::Bin32 => Ok(rd.read_data_u32()?),
416
0
        marker => Err(ValueReadError::TypeMismatch(marker)),
417
    }
418
0
}