bpx/sd/
decoder.rs

1// Copyright (c) 2021, BlockProject 3D
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification,
6// are permitted provided that the following conditions are met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above copyright notice,
11//       this list of conditions and the following disclaimer in the documentation
12//       and/or other materials provided with the distribution.
13//     * Neither the name of BlockProject 3D nor the names of its contributors
14//       may be used to endorse or promote products derived from this software
15//       without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29use 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]; //read char by char with a buffer
153
154    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}