rmpv/decode/
value_ref.rs

1use std;
2use std::io::{self, Cursor, ErrorKind, Read};
3use std::str;
4
5use rmp::Marker;
6use rmp::decode::{read_marker, read_data_u8, read_data_u16, read_data_u32, read_data_u64,
7                  read_data_i8, read_data_i16, read_data_i32, read_data_i64, read_data_f32,
8                  read_data_f64};
9
10use crate::{Utf8StringRef, ValueRef};
11use super::Error;
12
13fn read_str_data<'a, R>(rd: &mut R, len: usize) -> Result<Utf8StringRef<'a>, Error>
14    where R: BorrowRead<'a>
15{
16    let buf = read_bin_data(rd, len)?;
17    match str::from_utf8(buf) {
18        Ok(s) => Ok(Utf8StringRef::from(s)),
19        Err(err) => {
20            let s = Utf8StringRef {
21                s: Err((buf, err)),
22            };
23            Ok(s)
24        }
25    }
26}
27
28fn read_bin_data<'a, R>(rd: &mut R, len: usize) -> Result<&'a [u8], Error>
29    where R: BorrowRead<'a>
30{
31    let buf = rd.fill_buf();
32
33    if len > buf.len() {
34        return Err(Error::InvalidDataRead(io::Error::new(ErrorKind::UnexpectedEof, "unexpected EOF")));
35    }
36
37    // Take a slice.
38    let buf = &buf[..len];
39    rd.consume(len);
40
41    Ok(buf)
42}
43
44fn read_ext_body<'a, R>(rd: &mut R, len: usize) -> Result<(i8, &'a [u8]), Error>
45    where R: BorrowRead<'a>
46{
47    let ty = read_data_i8(rd)?;
48    let buf = read_bin_data(rd, len)?;
49
50    Ok((ty, buf))
51}
52
53fn read_array_data<'a, R>(rd: &mut R, mut len: usize) -> Result<Vec<ValueRef<'a>>, Error>
54    where R: BorrowRead<'a>
55{
56    // Note: Do not preallocate a Vec of size `len`.
57    // See https://github.com/3Hren/msgpack-rust/issues/151
58    let mut vec = Vec::new();
59
60    while len > 0 {
61        vec.push(read_value_ref(rd)?);
62        len -= 1;
63    }
64
65    Ok(vec)
66}
67
68fn read_map_data<'a, R>(rd: &mut R, mut len: usize) -> Result<Vec<(ValueRef<'a>, ValueRef<'a>)>, Error>
69    where R: BorrowRead<'a>
70{
71    // Note: Do not preallocate a Vec of size `len`.
72    // See https://github.com/3Hren/msgpack-rust/issues/151
73    let mut vec = Vec::new();
74
75    while len > 0 {
76        vec.push((read_value_ref(rd)?, read_value_ref(rd)?));
77        len -= 1;
78    }
79
80    Ok(vec)
81}
82
83/// A BorrowRead is a type of Reader which has an internal buffer.
84///
85/// This magic trait acts like a standard BufRead but unlike the standard this has an explicit
86/// internal buffer lifetime, which allows to borrow from underlying buffer while consuming bytes.
87pub trait BorrowRead<'a>: Read {
88    /// Returns the buffer contents.
89    ///
90    /// This function is a lower-level call. It needs to be paired with the consume method to
91    /// function properly. When calling this method, none of the contents will be "read" in the
92    /// sense that later calling read may return the same contents. As such, consume must be called
93    /// with the number of bytes that are consumed from this buffer to ensure that the bytes are
94    /// never returned twice.
95    ///
96    /// An empty buffer returned indicates that the stream has reached EOF.
97    fn fill_buf(&self) -> &'a [u8];
98
99    /// Tells this buffer that len bytes have been consumed from the buffer, so they should no
100    /// longer be returned in calls to read.
101    fn consume(&mut self, len: usize);
102}
103
104impl<'a> BorrowRead<'a> for &'a [u8] {
105    fn fill_buf(&self) -> &'a [u8] {
106        self
107    }
108
109    fn consume(&mut self, len: usize) {
110        *self = &(*self)[len..];
111    }
112}
113
114/// Useful when you want to know how much bytes has been consumed during ValueRef decoding.
115impl<'a> BorrowRead<'a> for Cursor<&'a [u8]> {
116    fn fill_buf(&self) -> &'a [u8] {
117        let len = std::cmp::min(self.position(), self.get_ref().len() as u64);
118        &self.get_ref()[len as usize..]
119    }
120
121    fn consume(&mut self, len: usize) {
122        let pos = self.position();
123        self.set_position(pos + len as u64);
124    }
125}
126
127/// Attempts to read the data from the given reader until either a complete MessagePack value
128/// decoded or an error detected.
129///
130/// Returns either a non-owning `ValueRef`, which borrows the buffer from the given reader or an
131/// error.
132///
133/// The reader should meet the requirement of a special `BorrowRead` trait, which allows to mutate
134/// itself but permits to mutate the buffer it contains. It allows to perform a completely
135/// zero-copy reading without a data loss fear in case of an error.
136///
137/// Currently only two types fit in this requirement: `&[u8]` and `Cursor<&[u8]>`. Using Cursor is
138/// helpful, when you need to know how exactly many bytes the decoded ValueRef consumes. A `Vec<u8>`
139/// type doesn't fit in the `BorrowRead` requirement, because its mut reference can mutate the
140/// underlying buffer - use `Vec::as_slice()` if you need to decode a value from the vector.
141///
142/// # Errors
143///
144/// Returns an `Error` value if unable to continue the decoding operation either because of read
145/// failure or any other circumstances. See `Error` documentation for more information.
146///
147/// # Examples
148/// ```
149/// use rmpv::ValueRef;
150/// use rmpv::decode::read_value_ref;
151///
152/// let buf = [0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
153/// let mut rd = &buf[..];
154///
155/// assert_eq!(ValueRef::from("le message"), read_value_ref(&mut rd).unwrap());
156/// ```
157pub fn read_value_ref<'a, R>(rd: &mut R) -> Result<ValueRef<'a>, Error>
158    where R: BorrowRead<'a>
159{
160
161    // Reading the marker involves either 1 byte read or nothing. On success consumes strictly
162    // 1 byte from the `rd`.
163    let val = match read_marker(rd)? {
164        Marker::Null => ValueRef::Nil,
165        Marker::True => ValueRef::Boolean(true),
166        Marker::False => ValueRef::Boolean(false),
167        Marker::FixPos(val) => ValueRef::from(val),
168        Marker::FixNeg(val) => ValueRef::from(val),
169        Marker::U8 => ValueRef::from(read_data_u8(rd)?),
170        Marker::U16 => ValueRef::from(read_data_u16(rd)?),
171        Marker::U32 => ValueRef::from(read_data_u32(rd)?),
172        Marker::U64 => ValueRef::from(read_data_u64(rd)?),
173        Marker::I8 => ValueRef::from(read_data_i8(rd)?),
174        Marker::I16 => ValueRef::from(read_data_i16(rd)?),
175        Marker::I32 => ValueRef::from(read_data_i32(rd)?),
176        Marker::I64 => ValueRef::from(read_data_i64(rd)?),
177        Marker::F32 => ValueRef::F32(read_data_f32(rd)?),
178        Marker::F64 => ValueRef::F64(read_data_f64(rd)?),
179        Marker::FixStr(len) => {
180            let res = read_str_data(rd, len as usize)?;
181            ValueRef::String(res)
182        }
183        Marker::Str8 => {
184            let len = read_data_u8(rd)?;
185            let res = read_str_data(rd, len as usize)?;
186            ValueRef::String(res)
187        }
188        Marker::Str16 => {
189            let len = read_data_u16(rd)?;
190            let res = read_str_data(rd, len as usize)?;
191            ValueRef::String(res)
192        }
193        Marker::Str32 => {
194            let len = read_data_u32(rd)?;
195            let res = read_str_data(rd, len as usize)?;
196            ValueRef::String(res)
197        }
198        Marker::Bin8 => {
199            let len = read_data_u8(rd)?;
200            let res = read_bin_data(rd, len as usize)?;
201            ValueRef::Binary(res)
202        }
203        Marker::Bin16 => {
204            let len = read_data_u16(rd)?;
205            let res = read_bin_data(rd, len as usize)?;
206            ValueRef::Binary(res)
207        }
208        Marker::Bin32 => {
209            let len = read_data_u32(rd)?;
210            let res = read_bin_data(rd, len as usize)?;
211            ValueRef::Binary(res)
212        }
213        Marker::FixArray(len) => {
214            let vec = read_array_data(rd, len as usize)?;
215            ValueRef::Array(vec)
216        }
217        Marker::Array16 => {
218            let len = read_data_u16(rd)?;
219            let vec = read_array_data(rd, len as usize)?;
220            ValueRef::Array(vec)
221        }
222        Marker::Array32 => {
223            let len = read_data_u32(rd)?;
224            let vec = read_array_data(rd, len as usize)?;
225            ValueRef::Array(vec)
226        }
227        Marker::FixMap(len) => {
228            let map = read_map_data(rd, len as usize)?;
229            ValueRef::Map(map)
230        }
231        Marker::Map16 => {
232            let len = read_data_u16(rd)?;
233            let map = read_map_data(rd, len as usize)?;
234            ValueRef::Map(map)
235        }
236        Marker::Map32 => {
237            let len = read_data_u32(rd)?;
238            let map = read_map_data(rd, len as usize)?;
239            ValueRef::Map(map)
240        }
241        Marker::FixExt1 => {
242            let len = 1;
243            let (ty, vec) = read_ext_body(rd, len as usize)?;
244            ValueRef::Ext(ty, vec)
245        }
246        Marker::FixExt2 => {
247            let len = 2;
248            let (ty, vec) = read_ext_body(rd, len as usize)?;
249            ValueRef::Ext(ty, vec)
250        }
251        Marker::FixExt4 => {
252            let len = 4;
253            let (ty, vec) = read_ext_body(rd, len as usize)?;
254            ValueRef::Ext(ty, vec)
255        }
256        Marker::FixExt8 => {
257            let len = 8;
258            let (ty, vec) = read_ext_body(rd, len as usize)?;
259            ValueRef::Ext(ty, vec)
260        }
261        Marker::FixExt16 => {
262            let len = 16;
263            let (ty, vec) = read_ext_body(rd, len as usize)?;
264            ValueRef::Ext(ty, vec)
265        }
266        Marker::Ext8 => {
267            let len = read_data_u8(rd)?;
268            let (ty, vec) = read_ext_body(rd, len as usize)?;
269            ValueRef::Ext(ty, vec)
270        }
271        Marker::Ext16 => {
272            let len = read_data_u16(rd)?;
273            let (ty, vec) = read_ext_body(rd, len as usize)?;
274            ValueRef::Ext(ty, vec)
275        }
276        Marker::Ext32 => {
277            let len = read_data_u32(rd)?;
278            let (ty, vec) = read_ext_body(rd, len as usize)?;
279            ValueRef::Ext(ty, vec)
280        }
281        Marker::Reserved => ValueRef::Nil,
282    };
283
284    Ok(val)
285}