1use std::io::Read;
30
31use byteorder::{ByteOrder, LittleEndian};
32
33use crate::{
34 error::Error,
35 sd::{Array, Object, Value},
36 Result
37};
38
39fn read_bool<TRead: Read>(stream: &mut TRead) -> Result<Value>
40{
41 let mut flag: [u8; 1] = [0; 1];
42
43 if stream.read(&mut flag)? != 1 {
44 return Err(Error::Truncation("Read Structured Data Value (bool)"));
45 }
46 return Ok(Value::Bool(flag[0] == 1));
47}
48
49fn read_uint8<TRead: Read>(stream: &mut TRead) -> Result<Value>
50{
51 let mut val: [u8; 1] = [0; 1];
52
53 if stream.read(&mut val)? != 1 {
54 return Err(Error::Truncation("Read Structured Data Value (uint8)"));
55 }
56 return Ok(Value::Uint8(val[0]));
57}
58
59fn read_int8<TRead: Read>(stream: &mut TRead) -> Result<Value>
60{
61 let mut val: [u8; 1] = [0; 1];
62
63 if stream.read(&mut val)? != 1 {
64 return Err(Error::Truncation("Read Structured Data Value (int8)"));
65 }
66 return Ok(Value::Int8(val[0] as i8));
67}
68
69fn read_uint16<TRead: Read>(stream: &mut TRead) -> Result<Value>
70{
71 let mut val: [u8; 2] = [0; 2];
72
73 if stream.read(&mut val)? != 2 {
74 return Err(Error::Truncation("Read Structured Data Value (uint16)"));
75 }
76 return Ok(Value::Uint16(LittleEndian::read_u16(&val)));
77}
78
79fn read_int16<TRead: Read>(stream: &mut TRead) -> Result<Value>
80{
81 let mut val: [u8; 2] = [0; 2];
82
83 if stream.read(&mut val)? != 2 {
84 return Err(Error::Truncation("Read Structured Data Value (int16)"));
85 }
86 return Ok(Value::Int16(LittleEndian::read_i16(&val)));
87}
88
89fn read_uint32<TRead: Read>(stream: &mut TRead) -> Result<Value>
90{
91 let mut val: [u8; 4] = [0; 4];
92
93 if stream.read(&mut val)? != 4 {
94 return Err(Error::Truncation("Read Structured Data Value (uint32)"));
95 }
96 return Ok(Value::Uint32(LittleEndian::read_u32(&val)));
97}
98
99fn read_int32<TRead: Read>(stream: &mut TRead) -> Result<Value>
100{
101 let mut val: [u8; 4] = [0; 4];
102
103 if stream.read(&mut val)? != 4 {
104 return Err(Error::Truncation("Read Structured Data Value (int32)"));
105 }
106 return Ok(Value::Int32(LittleEndian::read_i32(&val)));
107}
108
109fn read_uint64<TRead: Read>(stream: &mut TRead) -> Result<Value>
110{
111 let mut val: [u8; 8] = [0; 8];
112
113 if stream.read(&mut val)? != 8 {
114 return Err(Error::Truncation("Read Structured Data Value (uint64)"));
115 }
116 return Ok(Value::Uint64(LittleEndian::read_u64(&val)));
117}
118
119fn read_int64<TRead: Read>(stream: &mut TRead) -> Result<Value>
120{
121 let mut val: [u8; 8] = [0; 8];
122
123 if stream.read(&mut val)? != 8 {
124 return Err(Error::Truncation("Read Structured Data Value (int64)"));
125 }
126 return Ok(Value::Int64(LittleEndian::read_i64(&val)));
127}
128
129fn read_float<TRead: Read>(stream: &mut TRead) -> Result<Value>
130{
131 let mut val: [u8; 4] = [0; 4];
132
133 if stream.read(&mut val)? != 4 {
134 return Err(Error::Truncation("Read Structured Data Value (float)"));
135 }
136 return Ok(Value::Float(LittleEndian::read_f32(&val)));
137}
138
139fn read_double<TRead: Read>(stream: &mut TRead) -> Result<Value>
140{
141 let mut val: [u8; 8] = [0; 8];
142
143 if stream.read(&mut val)? != 8 {
144 return Err(Error::Truncation("Read Structured Data Value (double)"));
145 }
146 return Ok(Value::Double(LittleEndian::read_f64(&val)));
147}
148
149fn read_string<TRead: Read>(stream: &mut TRead) -> Result<Value>
150{
151 let mut curs: Vec<u8> = Vec::new();
152 let mut chr: [u8; 1] = [0; 1]; stream.read(&mut chr)?;
155 while chr[0] != 0x0 {
156 curs.push(chr[0]);
157 let res = stream.read(&mut chr)?;
158 if res != 1 {
159 return Err(Error::Truncation("Read Structured Data Value (string)"));
160 }
161 }
162 match String::from_utf8(curs) {
163 Err(_) => return Err(Error::Utf8("Read Structured Data Value (string)")),
164 Ok(v) => return Ok(Value::String(v))
165 }
166}
167
168fn parse_object<TRead: Read>(stream: &mut TRead) -> Result<Object>
169{
170 let mut obj = Object::new();
171 let mut count = {
172 let mut buf: [u8; 1] = [0; 1];
173 if stream.read(&mut buf)? != 1 {
174 return Err(Error::Truncation("Read Structured Data Value (object)"));
175 }
176 buf[0]
177 };
178
179 while count > 0 {
180 let mut prop: [u8; 9] = [0; 9];
181 if stream.read(&mut prop)? != 9 {
182 return Err(Error::Truncation("Read Structured Data Value (object)"));
183 }
184 let hash = LittleEndian::read_u64(&prop[0..8]);
185 let type_code = prop[8];
186 match get_value_parser(type_code) {
187 Some(func) => obj.raw_set(hash, func(stream)?),
188 None => {
189 return Err(Error::Corruption(format!(
190 "Got unexpected unknown variant code ({}) while reading Structured Data Object",
191 type_code
192 )))
193 },
194 }
195 count -= 1;
196 }
197 return Ok(obj);
198}
199
200fn parse_array<TRead: Read>(stream: &mut TRead) -> Result<Array>
201{
202 let mut arr = Array::new();
203 let mut count = {
204 let mut buf: [u8; 1] = [0; 1];
205 if stream.read(&mut buf)? != 1 {
206 return Err(Error::Truncation("Read Structured Data Value (array)"));
207 }
208 buf[0]
209 };
210
211 while count > 0 {
212 let mut type_code: [u8; 1] = [0; 1];
213 if stream.read(&mut type_code)? != 1 {
214 return Err(Error::Truncation("Read Structured Data Value (array)"));
215 }
216 match get_value_parser(type_code[0]) {
217 Some(func) => arr.add(func(stream)?),
218 None => {
219 return Err(Error::Corruption(format!(
220 "Got unexpected unknown variant code ({}) while reading Structured Data Array",
221 type_code[0]
222 )))
223 },
224 }
225 count -= 1;
226 }
227 return Ok(arr);
228}
229
230fn get_value_parser<TRead: Read>(type_code: u8) -> Option<fn(stream: &mut TRead) -> Result<Value>>
231{
232 match type_code {
233 0x0 => Some(|_| {
234 return Ok(Value::Null);
235 }),
236 0x1 => Some(read_bool),
237 0x2 => Some(read_uint8),
238 0x3 => Some(read_uint16),
239 0x4 => Some(read_uint32),
240 0x5 => Some(read_uint64),
241 0x6 => Some(read_int8),
242 0x7 => Some(read_int16),
243 0x8 => Some(read_int32),
244 0x9 => Some(read_int64),
245 0xA => Some(read_float),
246 0xB => Some(read_double),
247 0xC => Some(read_string),
248 0xD => Some(|stream| {
249 return Ok(Value::Array(parse_array(stream)?));
250 }),
251 0xE => Some(|stream| {
252 return Ok(Value::Object(parse_object(stream)?));
253 }),
254 _ => None
255 }
256}
257
258pub fn read_structured_data<TRead: Read>(source: &mut TRead) -> Result<Object>
259{
260 return parse_object(source);
261}