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 sint;
13mod uint;
14mod dec;
15mod str;
16mod ext;
17
18pub use self::sint::{read_nfix, read_i8, read_i16, read_i32, read_i64};
19pub use self::uint::{read_pfix, read_u8, read_u16, read_u32, read_u64};
20pub use self::dec::{read_f32, read_f64};
21pub use self::str::{read_str_len, read_str, read_str_from_slice, read_str_ref, DecodeStringError};
22pub use self::ext::{read_fixext1, read_fixext2, read_fixext4, read_fixext8, read_fixext16,
23                    read_ext_meta, ExtMeta};
24
25use std::error;
26use std::fmt::{self, Display, Formatter};
27use std::io::Read;
28
29use byteorder::{self, ReadBytesExt};
30
31use num_traits::cast::FromPrimitive;
32
33use Marker;
34
35/// An error that can occur when attempting to read bytes from the reader.
36pub type Error = ::std::io::Error;
37
38/// An error that can occur when attempting to read a MessagePack marker from the reader.
39#[derive(Debug)]
40pub struct MarkerReadError(pub Error);
41
42/// An error which can occur when attempting to read a MessagePack value from the reader.
43#[derive(Debug)]
44pub enum ValueReadError {
45    /// Failed to read the marker.
46    InvalidMarkerRead(Error),
47    /// Failed to read the data.
48    InvalidDataRead(Error),
49    /// The type decoded isn't match with the expected one.
50    TypeMismatch(Marker),
51}
52
53impl error::Error for ValueReadError {
54    fn description(&self) -> &str {
55        match *self {
56            ValueReadError::InvalidMarkerRead(..) => "failed to read MessagePack marker",
57            ValueReadError::InvalidDataRead(..) => "failed to read MessagePack data",
58            ValueReadError::TypeMismatch(..) => {
59                "the type decoded isn't match with the expected one"
60            }
61        }
62    }
63
64    fn cause(&self) -> Option<&error::Error> {
65        match *self {
66            ValueReadError::InvalidMarkerRead(ref err) |
67            ValueReadError::InvalidDataRead(ref err) => Some(err),
68            ValueReadError::TypeMismatch(..) => None,
69        }
70    }
71}
72
73impl Display for ValueReadError {
74    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
75        error::Error::description(self).fmt(f)
76    }
77}
78
79impl From<MarkerReadError> for ValueReadError {
80    fn from(err: MarkerReadError) -> ValueReadError {
81        match err {
82            MarkerReadError(err) => ValueReadError::InvalidMarkerRead(err),
83        }
84    }
85}
86
87impl From<Error> for MarkerReadError {
88    fn from(err: Error) -> MarkerReadError {
89        MarkerReadError(err)
90    }
91}
92
93/// Attempts to read a single byte from the given reader and to decode it as a MessagePack marker.
94pub fn read_marker<R: Read>(rd: &mut R) -> Result<Marker, MarkerReadError> {
95    Ok(Marker::from_u8(try!(rd.read_u8())))
96}
97
98/// Attempts to read a single byte from the given reader and to decode it as a nil value.
99///
100/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
101///
102/// # Errors
103///
104/// This function will return `ValueReadError` on any I/O error while reading the nil marker,
105/// except the EINTR, which is handled internally.
106///
107/// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the
108/// expected one, indicating you with the actual type.
109///
110/// # Note
111///
112/// This function will silently retry on every EINTR received from the underlying `Read` until
113/// successful read.
114pub fn read_nil<R: Read>(rd: &mut R) -> Result<(), ValueReadError> {
115    match try!(read_marker(rd)) {
116        Marker::Null => Ok(()),
117        marker => Err(ValueReadError::TypeMismatch(marker)),
118    }
119}
120
121/// Attempts to read a single byte from the given reader and to decode it as a boolean value.
122///
123/// According to the MessagePack specification, an encoded boolean value is represented as a single
124/// byte.
125///
126/// # Errors
127///
128/// This function will return `ValueReadError` on any I/O error while reading the bool marker,
129/// except the EINTR, which is handled internally.
130///
131/// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the
132/// expected one, indicating you with the actual type.
133///
134/// # Note
135///
136/// This function will silently retry on every EINTR received from the underlying `Read` until
137/// successful read.
138pub fn read_bool<R: Read>(rd: &mut R) -> Result<bool, ValueReadError> {
139    match try!(read_marker(rd)) {
140        Marker::True => Ok(true),
141        Marker::False => Ok(false),
142        marker => Err(ValueReadError::TypeMismatch(marker)),
143    }
144}
145
146/// An error which can occur when attempting to read a MessagePack numeric value from the reader.
147#[derive(Debug)]
148pub enum NumValueReadError {
149    /// Failed to read the marker.
150    InvalidMarkerRead(Error),
151    /// Failed to read the data.
152    InvalidDataRead(Error),
153    /// The type decoded isn't match with the expected one.
154    TypeMismatch(Marker),
155    /// Out of range integral type conversion attempted.
156    OutOfRange,
157}
158
159impl error::Error for NumValueReadError {
160    fn description(&self) -> &str {
161        match *self {
162            NumValueReadError::InvalidMarkerRead(..) => "failed to read MessagePack marker",
163            NumValueReadError::InvalidDataRead(..) => "failed to read MessagePack data",
164            NumValueReadError::TypeMismatch(..) => {
165                "the type decoded isn't match with the expected one"
166            }
167            NumValueReadError::OutOfRange => "out of range integral type conversion attempted",
168        }
169    }
170
171    fn cause(&self) -> Option<&error::Error> {
172        match *self {
173            NumValueReadError::InvalidMarkerRead(ref err) |
174            NumValueReadError::InvalidDataRead(ref err) => Some(err),
175            NumValueReadError::TypeMismatch(..) |
176            NumValueReadError::OutOfRange => None,
177        }
178    }
179}
180
181impl Display for NumValueReadError {
182    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
183        error::Error::description(self).fmt(f)
184    }
185}
186
187impl From<MarkerReadError> for NumValueReadError {
188    fn from(err: MarkerReadError) -> NumValueReadError {
189        match err {
190            MarkerReadError(err) => NumValueReadError::InvalidMarkerRead(err),
191        }
192    }
193}
194
195impl From<ValueReadError> for NumValueReadError {
196    fn from(err: ValueReadError) -> NumValueReadError {
197        match err {
198            ValueReadError::InvalidMarkerRead(err) => NumValueReadError::InvalidMarkerRead(err),
199            ValueReadError::InvalidDataRead(err) => NumValueReadError::InvalidDataRead(err),
200            ValueReadError::TypeMismatch(err) => NumValueReadError::TypeMismatch(err),
201        }
202    }
203}
204
205// Helper functions to map I/O error into the `InvalidDataRead` error.
206
207#[doc(hidden)]
208pub fn read_data_u8<R: Read>(rd: &mut R) -> Result<u8, ValueReadError> {
209    rd.read_u8().map_err(ValueReadError::InvalidDataRead)
210}
211
212#[doc(hidden)]
213pub fn read_data_u16<R: Read>(rd: &mut R) -> Result<u16, ValueReadError> {
214    rd.read_u16::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
215}
216
217#[doc(hidden)]
218pub fn read_data_u32<R: Read>(rd: &mut R) -> Result<u32, ValueReadError> {
219    rd.read_u32::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
220}
221
222#[doc(hidden)]
223pub fn read_data_u64<R: Read>(rd: &mut R) -> Result<u64, ValueReadError> {
224    rd.read_u64::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
225}
226
227#[doc(hidden)]
228pub fn read_data_i8<R: Read>(rd: &mut R) -> Result<i8, ValueReadError> {
229    rd.read_i8().map_err(ValueReadError::InvalidDataRead)
230}
231
232#[doc(hidden)]
233pub fn read_data_i16<R: Read>(rd: &mut R) -> Result<i16, ValueReadError> {
234    rd.read_i16::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
235}
236
237#[doc(hidden)]
238pub fn read_data_i32<R: Read>(rd: &mut R) -> Result<i32, ValueReadError> {
239    rd.read_i32::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
240}
241
242#[doc(hidden)]
243pub fn read_data_i64<R: Read>(rd: &mut R) -> Result<i64, ValueReadError> {
244    rd.read_i64::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
245}
246
247#[doc(hidden)]
248pub fn read_data_f32<R: Read>(rd: &mut R) -> Result<f32, ValueReadError> {
249    rd.read_f32::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
250}
251
252#[doc(hidden)]
253pub fn read_data_f64<R: Read>(rd: &mut R) -> Result<f64, ValueReadError> {
254    rd.read_f64::<byteorder::BigEndian>().map_err(ValueReadError::InvalidDataRead)
255}
256
257/// Attempts to read up to 9 bytes from the given reader and to decode them as integral `T` value.
258///
259/// This function will try to read up to 9 bytes from the reader (1 for marker and up to 8 for data)
260/// and interpret them as a big-endian `T`.
261///
262/// Unlike `read_*`, this function weakens type restrictions, allowing you to safely decode packed
263/// values even if you aren't sure about the actual integral type.
264///
265/// # Errors
266///
267/// This function will return `NumValueReadError` on any I/O error while reading either the marker
268/// or the data.
269///
270/// It also returns `NumValueReadError::OutOfRange` if the actual type is not an integer or it does
271/// not fit in the given numeric range.
272///
273/// # Examples
274///
275/// ```
276/// let buf = [0xcd, 0x1, 0x2c];
277///
278/// assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap());
279/// assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap());
280/// assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap());
281/// assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap());
282/// assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap());
283/// assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap());
284/// assert_eq!(300usize, rmp::decode::read_int(&mut &buf[..]).unwrap());
285/// assert_eq!(300isize, rmp::decode::read_int(&mut &buf[..]).unwrap());
286/// ```
287pub fn read_int<T: FromPrimitive, R: Read>(rd: &mut R) -> Result<T, NumValueReadError> {
288    let val = match try!(read_marker(rd)) {
289        Marker::FixPos(val) => T::from_u8(val),
290        Marker::FixNeg(val) => T::from_i8(val),
291        Marker::U8 => T::from_u8(try!(read_data_u8(rd))),
292        Marker::U16 => T::from_u16(try!(read_data_u16(rd))),
293        Marker::U32 => T::from_u32(try!(read_data_u32(rd))),
294        Marker::U64 => T::from_u64(try!(read_data_u64(rd))),
295        Marker::I8 => T::from_i8(try!(read_data_i8(rd))),
296        Marker::I16 => T::from_i16(try!(read_data_i16(rd))),
297        Marker::I32 => T::from_i32(try!(read_data_i32(rd))),
298        Marker::I64 => T::from_i64(try!(read_data_i64(rd))),
299        marker => return Err(NumValueReadError::TypeMismatch(marker)),
300    };
301
302    val.ok_or(NumValueReadError::OutOfRange)
303}
304
305/// Attempts to read up to 5 bytes from the given reader and to decode them as a big-endian u32
306/// array size.
307///
308/// Array format family stores a sequence of elements in 1, 3, or 5 bytes of extra bytes in addition
309/// to the elements.
310///
311/// # Note
312///
313/// This function will silently retry on every EINTR received from the underlying `Read` until
314/// successful read.
315// TODO: Docs.
316// NOTE: EINTR is managed internally.
317pub fn read_array_len<R>(rd: &mut R) -> Result<u32, ValueReadError>
318    where R: Read
319{
320    match try!(read_marker(rd)) {
321        Marker::FixArray(size) => Ok(size as u32),
322        Marker::Array16 => Ok(try!(read_data_u16(rd)) as u32),
323        Marker::Array32 => Ok(try!(read_data_u32(rd))),
324        marker => Err(ValueReadError::TypeMismatch(marker)),
325    }
326}
327
328/// Attempts to read up to 5 bytes from the given reader and to decode them as a big-endian u32
329/// map size.
330///
331/// Map format family stores a sequence of elements in 1, 3, or 5 bytes of extra bytes in addition
332/// to the elements.
333///
334/// # Note
335///
336/// This function will silently retry on every EINTR received from the underlying `Read` until
337/// successful read.
338// TODO: Docs.
339pub fn read_map_len<R: Read>(rd: &mut R) -> Result<u32, ValueReadError> {
340    let marker = read_marker(rd)?;
341    marker_to_len(rd, marker)
342}
343
344pub fn marker_to_len<R: Read>(rd: &mut R, marker: Marker) -> Result<u32, ValueReadError> {
345    match marker {
346        Marker::FixMap(size) => Ok(size as u32),
347        Marker::Map16 => Ok(try!(read_data_u16(rd)) as u32),
348        Marker::Map32 => Ok(try!(read_data_u32(rd))),
349        marker => Err(ValueReadError::TypeMismatch(marker)),
350    }
351}
352
353/// Attempts to read up to 5 bytes from the given reader and to decode them as Binary array length.
354///
355/// # Note
356///
357/// This function will silently retry on every EINTR received from the underlying `Read` until
358/// successful read.
359// TODO: Docs.
360pub fn read_bin_len<R: Read>(rd: &mut R) -> Result<u32, ValueReadError> {
361    match try!(read_marker(rd)) {
362        Marker::Bin8 => Ok(try!(read_data_u8(rd)) as u32),
363        Marker::Bin16 => Ok(try!(read_data_u16(rd)) as u32),
364        Marker::Bin32 => Ok(try!(read_data_u32(rd))),
365        marker => Err(ValueReadError::TypeMismatch(marker)),
366    }
367}