rmpv/decode/
value.rs

1use std::cmp::min;
2use std::io::{self, Read};
3
4use rmp::Marker;
5use rmp::decode::{read_marker, read_data_u8, read_data_u16, read_data_u32, read_data_u64,
6                  read_data_i8, read_data_i16, read_data_i32, read_data_i64, read_data_f32,
7                  read_data_f64};
8
9use crate::{Utf8String, Value};
10use super::Error;
11
12
13// See https://github.com/3Hren/msgpack-rust/issues/151
14const PREALLOC_MAX: usize = 64 * 1024; // 64 KiB
15
16
17fn read_array_data<R: Read>(rd: &mut R, mut len: usize) -> Result<Vec<Value>, Error> {
18    // Note: Do not preallocate a Vec of size `len`.
19    // See https://github.com/3Hren/msgpack-rust/issues/151
20    let mut vec = Vec::new();
21
22    while len > 0 {
23        vec.push(read_value(rd)?);
24        len -= 1;
25    }
26
27    Ok(vec)
28}
29
30fn read_map_data<R: Read>(rd: &mut R, mut len: usize) -> Result<Vec<(Value, Value)>, Error> {
31    // Note: Do not preallocate a Vec of size `len`.
32    // See https://github.com/3Hren/msgpack-rust/issues/151
33    let mut vec = Vec::new();
34
35    while len > 0 {
36        vec.push((read_value(rd)?, read_value(rd)?));
37        len -= 1;
38    }
39
40    Ok(vec)
41}
42
43fn read_str_data<R: Read>(rd: &mut R, len: usize) -> Result<Utf8String, Error> {
44    match String::from_utf8(read_bin_data(rd, len)?) {
45        Ok(s) => Ok(Utf8String::from(s)),
46        Err(err) => {
47            let e = err.utf8_error();
48            let s = Utf8String {
49                s: Err((err.into_bytes(), e)),
50            };
51            Ok(s)
52        }
53    }
54}
55
56fn read_bin_data<R: Read>(rd: &mut R, len: usize) -> Result<Vec<u8>, Error> {
57    let mut buf = Vec::with_capacity(min(len, PREALLOC_MAX));
58    let bytes_read = rd.take(len as u64).read_to_end(&mut buf).map_err(Error::InvalidDataRead)?;
59    if bytes_read != len {
60        return Err(Error::InvalidDataRead(io::Error::new(
61            io::ErrorKind::UnexpectedEof,
62            format!("Expected {} bytes, read {} bytes", len, bytes_read),
63        )));
64    }
65
66    Ok(buf)
67}
68
69fn read_ext_body<R: Read>(rd: &mut R, len: usize) -> Result<(i8, Vec<u8>), Error> {
70    let ty = read_data_i8(rd)?;
71    let vec = read_bin_data(rd, len)?;
72
73    Ok((ty, vec))
74}
75
76/// Attempts to read bytes from the given reader and interpret them as a `Value`.
77///
78/// # Errors
79///
80/// This function will return `Error` on any I/O error while either reading or decoding a `Value`.
81/// All instances of `ErrorKind::Interrupted` are handled by this function and the underlying
82/// operation is retried.
83pub fn read_value<R>(rd: &mut R) -> Result<Value, Error>
84    where R: Read
85{
86    let val = match read_marker(rd)? {
87        Marker::Null => Value::Nil,
88        Marker::True => Value::Boolean(true),
89        Marker::False => Value::Boolean(false),
90        Marker::FixPos(val) => Value::from(val),
91        Marker::FixNeg(val) => Value::from(val),
92        Marker::U8 => Value::from(read_data_u8(rd)?),
93        Marker::U16 => Value::from(read_data_u16(rd)?),
94        Marker::U32 => Value::from(read_data_u32(rd)?),
95        Marker::U64 => Value::from(read_data_u64(rd)?),
96        Marker::I8 => Value::from(read_data_i8(rd)?),
97        Marker::I16 => Value::from(read_data_i16(rd)?),
98        Marker::I32 => Value::from(read_data_i32(rd)?),
99        Marker::I64 => Value::from(read_data_i64(rd)?),
100        Marker::F32 => Value::F32(read_data_f32(rd)?),
101        Marker::F64 => Value::F64(read_data_f64(rd)?),
102        Marker::FixStr(len) => {
103            let res = read_str_data(rd, len as usize)?;
104            Value::String(res)
105        }
106        Marker::Str8 => {
107            let len = read_data_u8(rd)?;
108            let res = read_str_data(rd, len as usize)?;
109            Value::String(res)
110        }
111        Marker::Str16 => {
112            let len = read_data_u16(rd)?;
113            let res = read_str_data(rd, len as usize)?;
114            Value::String(res)
115        }
116        Marker::Str32 => {
117            let len = read_data_u32(rd)?;
118            let res = read_str_data(rd, len as usize)?;
119            Value::String(res)
120        }
121        Marker::FixArray(len) => {
122            let vec = read_array_data(rd, len as usize)?;
123            Value::Array(vec)
124        }
125        Marker::Array16 => {
126            let len = read_data_u16(rd)?;
127            let vec = read_array_data(rd, len as usize)?;
128            Value::Array(vec)
129        }
130        Marker::Array32 => {
131            let len = read_data_u32(rd)?;
132            let vec = read_array_data(rd, len as usize)?;
133            Value::Array(vec)
134        }
135        Marker::FixMap(len) => {
136            let map = read_map_data(rd, len as usize)?;
137            Value::Map(map)
138        }
139        Marker::Map16 => {
140            let len = read_data_u16(rd)?;
141            let map = read_map_data(rd, len as usize)?;
142            Value::Map(map)
143        }
144        Marker::Map32 => {
145            let len = read_data_u32(rd)?;
146            let map = read_map_data(rd, len as usize)?;
147            Value::Map(map)
148        }
149        Marker::Bin8 => {
150            let len = read_data_u8(rd)?;
151            let vec = read_bin_data(rd, len as usize)?;
152            Value::Binary(vec)
153        }
154        Marker::Bin16 => {
155            let len = read_data_u16(rd)?;
156            let vec = read_bin_data(rd, len as usize)?;
157            Value::Binary(vec)
158        }
159        Marker::Bin32 => {
160            let len = read_data_u32(rd)?;
161            let vec = read_bin_data(rd, len as usize)?;
162            Value::Binary(vec)
163        }
164        Marker::FixExt1 => {
165            let len = 1 as usize;
166            let (ty, vec) = read_ext_body(rd, len)?;
167            Value::Ext(ty, vec)
168        }
169        Marker::FixExt2 => {
170            let len = 2 as usize;
171            let (ty, vec) = read_ext_body(rd, len)?;
172            Value::Ext(ty, vec)
173        }
174        Marker::FixExt4 => {
175            let len = 4 as usize;
176            let (ty, vec) = read_ext_body(rd, len)?;
177            Value::Ext(ty, vec)
178        }
179        Marker::FixExt8 => {
180            let len = 8 as usize;
181            let (ty, vec) = read_ext_body(rd, len)?;
182            Value::Ext(ty, vec)
183        }
184        Marker::FixExt16 => {
185            let len = 16 as usize;
186            let (ty, vec) = read_ext_body(rd, len)?;
187            Value::Ext(ty, vec)
188        }
189        Marker::Ext8 => {
190            let len = read_data_u8(rd)? as usize;
191            let (ty, vec) = read_ext_body(rd, len)?;
192            Value::Ext(ty, vec)
193        }
194        Marker::Ext16 => {
195            let len = read_data_u16(rd)? as usize;
196            let (ty, vec) = read_ext_body(rd, len)?;
197            Value::Ext(ty, vec)
198        }
199        Marker::Ext32 => {
200            let len = read_data_u32(rd)? as usize;
201            let (ty, vec) = read_ext_body(rd, len)?;
202            Value::Ext(ty, vec)
203        }
204        Marker::Reserved => Value::Nil,
205    };
206
207    Ok(val)
208}