1use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
20use data::*;
21use std::io::{Read, Write};
22
23#[derive(Debug, Fail)]
24pub enum ReadError {
25 #[fail(display = "{}", _0)]
26 Io(#[cause] ::std::io::Error),
27
28 #[fail(display = "key was not a scalar that can be converted to a string")]
29 InvalidKey,
30
31 #[fail(display = "Invalid type prefix: {:?}", _0)]
32 InvalidTypePrefix(char),
33}
34
35impl From<::std::io::Error> for ReadError {
36 fn from(e: ::std::io::Error) -> Self {
37 ReadError::Io(e)
38 }
39}
40
41fn read_n_bytes<R: Read>(reader: &mut R, n_bytes: u32) -> Result<Vec<u8>, ReadError> {
42 let mut data = vec![0u8; n_bytes as usize];
43 reader.read_exact(&mut data)?;
44 Ok(data.to_vec())
45}
46
47pub fn read_value<R: Read>(reader: &mut R) -> Result<Value, ReadError> {
51 let code = reader.read_u8()? as char;
52 match code {
53 '!' => Ok(Value::Scalar(Scalar::Undefined)),
54 '1' => Ok(Value::new_boolean(true)),
55 '0' => Ok(Value::new_boolean(false)),
56 'i' => Ok(Value::new_integer(reader.read_i32::<BigEndian>()?)),
57 'r' => Ok(Value::new_real(reader.read_f64::<BigEndian>()?)),
58 'u' => {
59 let mut bytes = [0u8; 16];
60 reader.read_exact(&mut bytes)?;
61 Ok(Value::new_uuid(Uuid::from_bytes(bytes)))
62 }
63 'b' => {
64 let len = reader.read_u32::<BigEndian>()?;
65 Ok(Value::new_binary(read_n_bytes(reader, len)?))
66 }
67 's' | 'k' => {
68 let len = reader.read_u32::<BigEndian>()?;
69 let data = read_n_bytes(reader, len)?;
70 Ok(Value::new_string(String::from_utf8_lossy(&data)))
71 }
72 'l' => {
73 let len = reader.read_u32::<BigEndian>()?;
74 let data = read_n_bytes(reader, len)?;
75 Ok(Value::new_uri(String::from_utf8_lossy(&data).to_string()))
76 }
77 'd' => {
78 let real = Scalar::Real(reader.read_f64::<LittleEndian>()?);
79 Ok(Value::new_date(real.as_date().unwrap()))
80 }
81 '[' => {
82 let len = reader.read_u32::<BigEndian>()?;
83 let mut items = Vec::new();
84
85 for _ in 0..len {
86 items.push(read_value(reader)?);
87 }
88
89 reader.read_u8()?;
91 Ok(Value::Array(items))
92 }
93 '{' => {
94 let len = reader.read_u32::<BigEndian>()?;
95 let mut items = Map::new();
96
97 for _ in 0..len {
98 let key = match read_value(reader)? {
99 Value::Scalar(Scalar::String(s)) => s,
100 _ => return Err(ReadError::InvalidKey),
101 };
102 let value = read_value(reader)?;
103 items.insert(key, value);
104 }
105
106 reader.read_u8()?;
108 Ok(Value::Map(items))
109 }
110 prefix => Err(ReadError::InvalidTypePrefix(prefix)),
111 }
112}
113
114pub fn write_value<W: Write>(writer: &mut W, value: &Value) -> Result<(), ::std::io::Error> {
118 match *value {
119 Value::Scalar(Scalar::Boolean(ref b)) => {
120 writer.write_u8(if *b { '1' as u8 } else { '0' as u8 })
121 }
122 Value::Scalar(Scalar::Integer(ref i)) => {
123 writer.write_u8('i' as u8)?;
124 writer.write_i32::<BigEndian>(*i)
125 }
126 Value::Scalar(Scalar::Real(ref r)) => {
127 writer.write_u8('r' as u8)?;
128 writer.write_f64::<BigEndian>(*r)
129 }
130 Value::Scalar(Scalar::Uuid(ref u)) => {
131 writer.write_u8('u' as u8)?;
132 writer.write_all(u.as_bytes())
133 }
134 Value::Scalar(Scalar::String(ref s)) => {
135 writer.write_u8('s' as u8)?;
136 let bytes = s.as_bytes();
137 writer.write_u32::<BigEndian>(bytes.len() as u32)?;
138 writer.write_all(bytes)
139 }
140 Value::Scalar(Scalar::Date(ref d)) => {
141 writer.write_u8('d' as u8)?;
142 let date = Scalar::Date(d.clone());
144 writer.write_f64::<LittleEndian>(date.as_real().unwrap())
145 }
146 Value::Scalar(Scalar::Uri(ref u)) => {
147 writer.write_u8('l' as u8)?;
148 let string = u.clone().into_string();
149 let bytes = string.as_bytes();
150 writer.write_u32::<BigEndian>(bytes.len() as u32)?;
151 writer.write_all(bytes)
152 }
153 Value::Scalar(Scalar::Binary(ref b)) => {
154 writer.write_u8('b' as u8)?;
155 writer.write_u32::<BigEndian>(b.len() as u32)?;
156 writer.write_all(b)
157 }
158 Value::Scalar(Scalar::Undefined) => writer.write_u8('!' as u8),
159 Value::Map(ref map) => {
160 writer.write_u8('{' as u8)?;
161 writer.write_u32::<BigEndian>(map.len() as u32)?;
162 for (key, val) in map {
163 writer.write_u8('k' as u8)?;
165 let bytes = key.as_bytes();
166 writer.write_u32::<BigEndian>(bytes.len() as u32)?;
167 writer.write_all(bytes)?;
168
169 write_value(writer, val)?;
171 }
172 writer.write_u8('}' as u8)
173 }
174 Value::Array(ref arr) => {
175 writer.write_u8('[' as u8)?;
176 writer.write_u32::<BigEndian>(arr.len() as u32)?;
177 for item in arr {
178 write_value(writer, item)?;
179 }
180 writer.write_u8(']' as u8)
181 }
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188 use data::scalar;
189 use std::io::BufReader;
190
191 fn read_unwrap(bytes: Vec<u8>) -> Value {
193 let mut reader = BufReader::new(&bytes[..]);
194 read_value(&mut reader).unwrap()
195 }
196
197 #[test]
198 fn read_undef() {
199 let value = read_unwrap(vec![0x21]);
200 assert_eq!(value, Value::Scalar(Scalar::Undefined));
201 }
202
203 #[test]
204 fn read_boolean() {
205 assert_eq!(read_unwrap(vec![0x31]), Value::new_boolean(true));
206 assert_eq!(read_unwrap(vec![0x30]), Value::new_boolean(false));
207 }
208
209 #[test]
210 fn read_integer() {
211 assert_eq!(
212 read_unwrap(vec![0x69, 0x0, 0x0, 0x0, 0x0]),
213 Value::new_integer(0)
214 );
215 assert_eq!(
216 read_unwrap(vec![0x69, 0x0, 0x12, 0xd7, 0x9b]),
217 Value::new_integer(1234843)
218 );
219 }
220
221 #[test]
222 fn read_real() {
223 let data = vec![0x72, 0x41, 0x2c, 0xec, 0xf6, 0x77, 0xce, 0xd9, 0x17];
224 assert_eq!(read_unwrap(data), Value::new_real(947835.234));
225 }
226
227 #[test]
228 fn read_uuid() {
229 let data = vec![
230 0x75, 0x97, 0xf4, 0xae, 0xca, 0x88, 0xa1, 0x42, 0xa1, 0xb3, 0x85, 0xb9, 0x7b, 0x18,
231 0xab, 0xb2, 0x55,
232 ];
233 assert_eq!(
234 read_unwrap(data),
235 Value::new_uuid("97f4aeca-88a1-42a1-b385-b97b18abb255".parse().unwrap())
236 );
237
238 let data = vec![0x75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
239 assert_eq!(
240 read_unwrap(data),
241 Value::new_uuid("00000000-0000-0000-0000-000000000000".parse().unwrap())
242 );
243 }
244
245 #[test]
246 fn read_binary() {
247 let data = vec![
248 0x62, 0x0, 0x0, 0x0, 0x34, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20,
249 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20,
250 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72,
251 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0xd,
252 ];
253
254 assert_eq!(
255 read_unwrap(data),
256 Value::new_binary(vec![
257 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6d, 0x70,
258 0x6c, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76,
259 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x69,
260 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0xd,
261 ])
262 );
263 }
264
265 #[test]
266 fn read_string() {
267 let data = vec![0x73, 0, 0, 0, 0];
268 assert_eq!(read_unwrap(data), Value::new_string(""));
269
270 let data = vec![
271 0x73, 0x0, 0x0, 0x0, 0x25, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
272 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
273 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
274 ];
275 assert_eq!(
276 read_unwrap(data),
277 Value::new_string("abcdefghijklmnopqrstuvwxyz01234567890")
278 );
279 }
280
281 #[test]
282 fn read_uri() {
283 let data = vec![
284 0x6c, 0x0, 0x0, 0x0, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
285 0x2e, 0x74, 0x65, 0x73, 0x74, 0x75, 0x72, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2f,
286 ];
287 assert_eq!(
288 read_unwrap(data),
289 Value::new_uri("http://www.testurl.test/")
290 );
291 }
292
293 #[test]
294 fn read_datetime() {
295 use chrono::{NaiveDate, NaiveDateTime, NaiveTime, Utc};
296
297 let data = vec![100, 0, 0, 192, 141, 167, 222, 209, 65];
298 let d = NaiveDate::from_ymd(2008, 1, 1);
299 let t = NaiveTime::from_hms_milli(20, 10, 31, 0);
300 let date = scalar::Date::from_utc(NaiveDateTime::new(d, t), Utc);
301 assert_eq!(read_unwrap(data), Value::new_date(date));
302 }
303
304 #[test]
305 fn read_array() {
306 let data = vec![0x5b, 0x0, 0x0, 0x0, 0x0, 0x5d];
308 assert_eq!(read_unwrap(data), Value::Array(Vec::new()));
309
310 let data = vec![0x5b, 0x0, 0x0, 0x0, 0x1, 0x69, 0x0, 0x0, 0x0, 0x0, 0x5d];
312 let arr = read_unwrap(data).array().unwrap();
313 assert_eq!(arr.len(), 1);
314 assert_eq!(arr[0], Value::new_integer(0));
315
316 let data = vec![
318 0x5b, 0x0, 0x0, 0x0, 0x2, 0x69, 0x0, 0x0, 0x0, 0x0, 0x69, 0x0, 0x0, 0x0, 0x0, 0x5d,
319 ];
320 let arr = read_unwrap(data).array().unwrap();
321 assert_eq!(arr.len(), 2);
322 assert_eq!(arr[0], Value::new_integer(0));
323 assert_eq!(arr[1], Value::new_integer(0));
324 }
325
326 #[test]
327 fn read_map() {
328 let data = vec![0x7b, 0x0, 0x0, 0x0, 0x0, 0x7d];
330 assert_eq!(read_unwrap(data), Value::Map(Map::new()));
331
332 let data = vec![
334 0x7b, 0x0, 0x0, 0x0, 0x1, 0x6b, 0x0, 0x0, 0x0, 0x4, 0x74, 0x65, 0x73, 0x74, 0x69, 0x0,
335 0x0, 0x0, 0x0, 0x7d,
336 ];
337 let map = read_unwrap(data).map().unwrap();
338 assert_eq!(map.len(), 1);
339 assert_eq!(map["test"], Value::new_integer(0));
340
341 let data = vec![
343 0x7b, 0x0, 0x0, 0x0, 0x3, 0x6b, 0x0, 0x0, 0x0, 0x4, 0x74, 0x65, 0x73, 0x74, 0x21, 0x6b,
344 0x0, 0x0, 0x0, 0x4, 0x74, 0x65, 0x73, 0x31, 0x73, 0x0, 0x0, 0x0, 0x3, 0x61, 0x68, 0x61,
345 0x6b, 0x0, 0x0, 0x0, 0x4, 0x74, 0x30, 0x73, 0x74, 0x69, 0x0, 0x0, 0x0, 0xf1, 0x7d,
346 ];
347 let map = read_unwrap(data).map().unwrap();
348 assert_eq!(map.len(), 3);
349 assert_eq!(map["t0st"], Value::new_integer(241));
350 assert_eq!(map["tes1"], Value::new_string("aha"));
351 assert_eq!(map["test"], Value::Scalar(Scalar::Undefined));
352 }
353
354 #[test]
355 fn write() {
356 use chrono::{NaiveDate, NaiveDateTime, NaiveTime, Utc};
357 use std::collections::HashMap;
358
359 let mut map = HashMap::new();
360 map.insert("bool_0".to_string(), Value::new_boolean(false));
361 map.insert("bool_1".to_string(), Value::new_boolean(true));
362 map.insert("int".to_string(), Value::new_integer(42));
363 map.insert("real".to_string(), Value::new_real(1.2141e30));
364 map.insert(
365 "uuid".to_string(),
366 Value::new_uuid("7ad22c95-f7c2-47ab-9525-ca64135c928c".parse().unwrap()),
367 );
368 map.insert("string".to_string(), Value::new_string("Lorem ipsum"));
369 let d = NaiveDate::from_ymd(2008, 1, 1);
370 let t = NaiveTime::from_hms_milli(20, 10, 31, 0);
371 let date = scalar::Date::from_utc(NaiveDateTime::new(d, t), Utc);
372 map.insert("date".to_string(), Value::new_date(date));
373 map.insert("uri".to_string(), Value::new_uri("http://example.com"));
374 map.insert(
375 "binary".to_string(),
376 Value::new_binary(vec![10, 11, 12, 13, 5, 6, 7, 8]),
377 );
378 map.insert("undef".to_string(), Value::Scalar(Scalar::Undefined));
379 map.insert(
380 "arr".to_string(),
381 Value::Array(vec![
382 Value::new_string("abc"),
383 Value::new_string("xyz"),
384 Value::new_real(123.456),
385 ]),
386 );
387 let data_in = Value::Map(map);
388
389 let mut ser = Vec::new();
390 write_value(&mut ser, &data_in).unwrap();
391
392 let data_out = read_unwrap(ser);
393
394 assert_eq!(data_out, data_in);
395 }
396}