llsd/
binary.rs

1// LLSD for Rust - Parser and Writer for the LLSD format.
2// Copyright (C) 2017-2018  Leonardo Schwarz <mail@leoschwarz.com>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Handle binary representation of LLSD data.
18
19use 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
47/// Read an LLSD value from its binary representation.
48///
49/// This assumes that the header has already been skipped by the initial caller.
50pub 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            // ']'
90            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            // ']'
107            reader.read_u8()?;
108            Ok(Value::Map(items))
109        }
110        prefix => Err(ReadError::InvalidTypePrefix(prefix)),
111    }
112}
113
114/// Writes a Value to the writer.
115///
116/// Note that this does not write the LLSD header.
117pub 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            // TODO
143            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                // Key
164                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                // Value
170                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    // test helper
192    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        // Empty array.
307        let data = vec![0x5b, 0x0, 0x0, 0x0, 0x0, 0x5d];
308        assert_eq!(read_unwrap(data), Value::Array(Vec::new()));
309
310        // { 0 }
311        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        // { 0, 0 }
317        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        // {}
329        let data = vec![0x7b, 0x0, 0x0, 0x0, 0x0, 0x7d];
330        assert_eq!(read_unwrap(data), Value::Map(Map::new()));
331
332        // { test = 0 }
333        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        // { t0st = 241, tes1 = "aha", test = undef }
342        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}