1use crate::LLSDValue;
15use anyhow::{anyhow, Error};
16use std::collections::HashMap;
17use std::io::{Cursor, Read};
18use uuid;
19pub const LLSDBINARYPREFIX: &[u8] = b"<? LLSD/Binary ?>\n"; pub const LLSDBINARYSENTINEL: &[u8] = LLSDBINARYPREFIX; pub fn from_bytes(b: &[u8]) -> Result<LLSDValue, Error> {
27 let mut cursor: Cursor<&[u8]> = Cursor::new(b);
28 parse_value(&mut cursor)
29}
30
31pub fn from_reader(cursor: &mut dyn Read) -> Result<LLSDValue, Error> {
33 parse_value(cursor)
34}
35
36fn parse_value(cursor: &mut dyn Read) -> Result<LLSDValue, Error> {
38 fn read_u8(cursor: &mut dyn Read) -> Result<u8, Error> {
40 let mut b: [u8; 1] = [0; 1];
41 cursor.read_exact(&mut b)?; Ok(b[0])
43 }
44 fn read_u32(cursor: &mut dyn Read) -> Result<u32, Error> {
45 let mut b: [u8; 4] = [0; 4];
46 cursor.read_exact(&mut b)?; Ok(u32::from_be_bytes(b))
48 }
49 fn read_i32(cursor: &mut dyn Read) -> Result<i32, Error> {
50 let mut b: [u8; 4] = [0; 4];
51 cursor.read_exact(&mut b)?; Ok(i32::from_be_bytes(b))
53 }
54 fn read_i64(cursor: &mut dyn Read) -> Result<i64, Error> {
55 let mut b: [u8; 8] = [0; 8];
56 cursor.read_exact(&mut b)?; Ok(i64::from_be_bytes(b))
58 }
59 fn read_f64(cursor: &mut dyn Read) -> Result<f64, Error> {
60 let mut b: [u8; 8] = [0; 8];
61 cursor.read_exact(&mut b)?; Ok(f64::from_be_bytes(b))
63 }
64 fn read_variable(cursor: &mut dyn Read) -> Result<Vec<u8>, Error> {
65 let length = read_u32(cursor)?; let mut buf = vec![0u8; length as usize];
67 cursor.read_exact(&mut buf)?;
68 Ok(buf) }
70
71 let typecode = read_u8(cursor)?;
72 match typecode {
73 b'!' => Ok(LLSDValue::Undefined),
75 b'0' => Ok(LLSDValue::Boolean(false)),
77 b'1' => Ok(LLSDValue::Boolean(true)),
78 b's' => Ok(LLSDValue::String(
80 std::str::from_utf8(&read_variable(cursor)?)?.to_string(),
81 )),
82 b'l' => Ok(LLSDValue::URI(
84 std::str::from_utf8(&read_variable(cursor)?)?.to_string(),
85 )),
86 b'i' => Ok(LLSDValue::Integer(read_i32(cursor)?)),
88 b'r' => Ok(LLSDValue::Real(read_f64(cursor)?)),
90 b'u' => {
92 let mut buf: [u8; 16] = [0u8; 16];
93 cursor.read_exact(&mut buf)?; Ok(LLSDValue::UUID(uuid::Uuid::from_bytes(buf)))
95 }
96 b'b' => Ok(LLSDValue::Binary(read_variable(cursor)?)),
98 b'd' => Ok(LLSDValue::Date(read_i64(cursor)?)),
100 b'{' => {
102 let mut dict: HashMap<String, LLSDValue> = HashMap::new(); let count = read_u32(cursor)?; for _ in 0..count {
105 let keyprefix = &read_u8(cursor)?; match keyprefix {
107 b'k' => {
108 let key = std::str::from_utf8(&read_variable(cursor)?)?.to_string();
109 let _ = dict.insert(key, parse_value(cursor)?); }
111 _ => {
112 return Err(anyhow!(
113 "Binary LLSD map key had {:?} instead of expected 'k'",
114 keyprefix
115 ))
116 }
117 }
118 }
119 if read_u8(cursor)? != b'}' {
120 return Err(anyhow!("Binary LLSD map did not end properly with }}"));
121 }
122 Ok(LLSDValue::Map(dict))
123 }
124 b'[' => {
126 let mut array: Vec<LLSDValue> = Vec::new(); let count = read_u32(cursor)?; for _ in 0..count {
129 array.push(parse_value(cursor)?); }
131 if read_u8(cursor)? != b']' {
132 return Err(anyhow!("Binary LLSD array did not end properly with ] "));
133 }
134 Ok(LLSDValue::Array(array))
135 }
136
137 _ => Err(anyhow!("Binary LLSD, unexpected type code {:?}", typecode)),
138 }
139}
140
141#[test]
144fn binaryparsetest1() {
145 let test1map: HashMap<String, LLSDValue> = [
147 ("val1".to_string(), LLSDValue::Real(456.0)),
148 ("val2".to_string(), LLSDValue::Integer(999)),
149 ]
150 .iter()
151 .cloned()
152 .collect();
153 let test1: LLSDValue = LLSDValue::Array(vec![
154 LLSDValue::Real(123.5),
155 LLSDValue::Map(test1map),
156 LLSDValue::Integer(42),
157 LLSDValue::String("Hello world".to_string()),
158 ]);
159 let test1bin = crate::to_bytes(&test1).unwrap();
161 println!("Binary form: {:?}", test1bin);
162 let test1value = from_bytes(&test1bin[LLSDBINARYSENTINEL.len()..]).unwrap();
164 println!("Value after round-trip conversion: {:?}", test1value);
165 assert_eq!(test1, test1value);
167}