1extern crate regex;
2extern crate serde;
3extern crate serde_json;
4
5use self::regex::Regex;
6use self::serde::Deserialize;
7use serde_json::Value;
8use std::collections::HashMap;
9use std::error::Error;
10use std::fmt;
11use std::vec::Vec;
12
13const MIN_DICT_INDEX: u64 = 3;
15const TYPE_ARRAY: i64 = 0;
16const TYPE_VALUE: i64 = 1;
17const TYPE_STRING: i64 = 2;
18const MAX_PACK_COMPLEX_OBJECT_SIZE: usize = 12;
19
20#[derive(Default, Debug)]
21pub struct Unpacker {
22 dict: HashMap<u64, String>,
23 dict_index: u64,
24 sequence_id: i64,
25 max_dict_size: u64,
26 pending_unpacks: Vec<i32>,
27}
28
29#[derive(Debug, Clone)]
30pub struct UnpackerError {
31 pub cause: String,
32}
33
34impl fmt::Display for UnpackerError {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 write!(f, "UnpackerError")
37 }
38}
39
40impl Error for UnpackerError {
41 fn description(&self) -> &str {
42 "Unpacker Error"
43 }
44
45 fn cause(&self) -> Option<&dyn Error> {
46 None
47 }
48}
49
50impl Unpacker {
51 pub fn new() -> Unpacker {
52 Unpacker {
53 sequence_id: -1,
54 max_dict_size: 2000,
55 dict_index: MIN_DICT_INDEX,
56 ..Default::default()
57 }
58 }
59
60 pub fn unpack<T>(&mut self, packed_object: &Value) -> Result<T, UnpackerError>
62 where
63 for<'de> T: Deserialize<'de>,
64 {
65 if packed_object.is_null() {
66 return match serde_json::from_value(Value::Null) {
67 Ok(v) => Ok(v),
68 Err(_err) => Err(UnpackerError {
69 cause: "wrong end type for Value::Null, use Value type instead".to_owned(),
70 }),
71 };
72 };
73
74 let packed_arr = match packed_object.as_array() {
75 Some(packed_arr) => packed_arr,
76 None => {
77 return Err(UnpackerError {
78 cause: "packed value expected".to_owned(),
79 })
80 }
81 };
82
83 if !packed_arr[packed_arr.len() - 1].is_number() {
84 return Err(UnpackerError {
85 cause: "packed value expected".to_owned(),
86 });
87 };
88
89 let value = &packed_arr[packed_arr.len() - 1];
90 let remote_sequence_id = match value.as_i64() {
91 Some(v) => v,
92 None => {
93 return Err(UnpackerError {
94 cause: "packed value expected".to_owned(),
95 })
96 }
97 };
98
99 if remote_sequence_id == 0 {
100 self.dict_index = MIN_DICT_INDEX;
101 } else if remote_sequence_id != (self.sequence_id + 1) {
102 return Err(UnpackerError {
103 cause: "message unpacked out of sequence or already unpacked".to_owned(),
104 });
105 };
106
107 self.sequence_id = remote_sequence_id;
108 let unpacked = match self.unpack_object(&json!(packed_arr[..(packed_arr.len() - 1)])) {
109 Ok(result) => result,
110 Err(err) => return Err(err),
111 };
112
113 let result: T = match serde_json::from_value(unpacked) {
114 Ok(result) => result,
115 Err(_err) => {
116 return Err(UnpackerError {
117 cause: "unable to unpack to specific type".to_owned(),
118 })
119 }
120 };
121 Ok(result)
122 }
123
124 pub fn unpack_string(&mut self, packed_object: &Value) -> Result<String, UnpackerError> {
126 match packed_object.as_array() {
127 Some(arr) => {
128 if arr[0] == TYPE_STRING {
129 return self.unpack(packed_object);
130 }
131
132 match self.unpack::<Value>(packed_object) {
133 Ok(s) => Ok(s.to_string()),
134 Err(err) => Err(err),
135 }
136 }
137 None => match self.unpack::<Value>(packed_object) {
138 Ok(s) => Ok(s.to_string()),
139 Err(err) => Err(err),
140 },
141 }
142 }
143
144 fn unpack_object(&mut self, packed_object: &Value) -> Result<Value, UnpackerError> {
145 if packed_object.is_null() {
146 return Ok(Value::Null);
147 };
148
149 if !packed_object.is_array() {
150 return self.unpack_value(packed_object);
151 }
152
153 let packed_array = match packed_object.as_array() {
154 Some(packed_array) => packed_array,
155 None => {
156 return Err(UnpackerError {
157 cause: "wrong packed object".to_owned(),
158 })
159 }
160 };
161
162 let type_value = &packed_array[0];
163 let type_id = match type_value.as_i64() {
164 Some(i) => i,
165 None => -1,
166 };
167
168 if type_id == TYPE_ARRAY {
169 return packed_array[1..]
170 .iter()
171 .map(|v| self.unpack_object(&v))
172 .collect();
173 }
174 if type_id == TYPE_STRING {
175 return match packed_array[1..]
176 .iter()
177 .map(|v| self.unpack_object(&v))
178 .collect::<Result<Value, _>>()
179 {
180 Ok(arr) => {
181 let vec = match arr.as_array() {
182 Some(a) => a,
183 None => {
184 return Err(UnpackerError {
185 cause: "expected array, got something else".to_owned(),
186 })
187 }
188 };
189 Ok(json!(vec.iter().fold("".to_owned(), |acc, x| {
190 if acc.is_empty() {
191 x.as_str().unwrap().to_owned()
192 } else {
193 acc + "\n" + x.as_str().unwrap()
194 }
195 })))
196 }
197 Err(err) => return Err(err),
198 };
199 }
200 if type_id == TYPE_VALUE {
201 return self.unpack_value(&packed_array[1]);
202 }
203
204 let mut contains_unmemoised = false;
205 let mut processed_object: Vec<Value> = Vec::new();
206 for item in packed_array {
207 if item.is_object() || item.is_array() {
208 let value = match self.unpack_object(&item) {
209 Ok(v) => v,
210 Err(err) => return Err(err),
211 };
212 contains_unmemoised = true;
213 processed_object.push(value);
214 } else {
215 if !item.is_number() {
216 contains_unmemoised = true;
217 }
218 let value = match self.unpack_value(&item) {
219 Ok(v) => v,
220 Err(err) => return Err(err),
221 };
222
223 processed_object.push(value);
224 }
225 }
226
227 let mut result: HashMap<String, Value> = HashMap::new();
228 let key_count = processed_object.len() / 2;
229 for i in 0..key_count {
230 let key_value = &processed_object[i];
231 let key = match processed_object[i].as_str() {
232 Some(s) => s.to_string(),
233 None => key_value.to_string(),
234 };
235 result.insert(key, processed_object[i + key_count].clone());
236 }
237
238 let json_result = json!(result);
239 if !contains_unmemoised && packed_array.len() <= MAX_PACK_COMPLEX_OBJECT_SIZE {
240 self.add_to_dict(&json_result.to_string());
241 }
242
243 Ok(json_result)
244 }
245
246 fn unpack_value(&mut self, packed_object: &Value) -> Result<Value, UnpackerError> {
247 if packed_object.is_number() {
248 return match packed_object.as_i64() {
249 Some(v) => {
250 if v < 0 {
251 return Ok(json!(v * -1));
252 }
253 let index = packed_object.as_u64().unwrap();
254 let string = match self.dict.get(&index) {
255 Some(s) => s,
256 None => {
257 return Err(UnpackerError {
258 cause: "no stored value".to_owned(),
259 })
260 }
261 };
262 let json: serde_json::Value = match serde_json::from_str(&string) {
263 Ok(parsed) => parsed,
264 Err(_err) => json!(string),
265 };
266
267 Ok(json)
268 }
269 None => Err(UnpackerError {
270 cause: "unknown".to_owned(),
271 }),
272 };
273 };
274
275 if packed_object.is_string() {
276 let string = match packed_object.as_str() {
277 Some(s) => s,
278 None => {
279 return Err(UnpackerError {
280 cause: "unknown".to_owned(),
281 })
282 }
283 };
284
285 let re = Regex::new(r"^-?[0-9]+\.").unwrap();
286 if re.is_match(string) {
287 let _p: Value = match string.parse::<f64>() {
288 Ok(parse_number) => {
289 self.add_to_dict(string);
290 return Ok(json!(parse_number));
291 }
292 Err(_err) => Value::Null,
293 };
294 };
295
296 let re = Regex::new(r"^-?[0-9\.]").unwrap();
297 if re.is_match(string) {
298 let _p: Value = match string.parse::<i64>() {
299 Ok(parse_number) => {
300 self.add_to_dict(string);
301 return Ok(json!(parse_number));
302 }
303 Err(_err) => Value::Null,
304 };
305 };
306
307 let value = if !string.is_empty() && &string[0..1] == "~" {
308 &string[1..]
309 } else {
310 string
311 };
312
313 self.add_to_dict(&json!(value).to_string());
314 return Ok(json!(value));
315 }
316 Ok(json!(packed_object))
317 }
318
319 fn add_to_dict(&mut self, str_value: &str) {
320 self.dict.insert(self.dict_index, str_value.to_owned());
321 self.dict_index += 1;
322 if self.dict_index >= (self.max_dict_size + MIN_DICT_INDEX) {
323 self.dict_index = MIN_DICT_INDEX;
324 }
325 }
326
327 pub fn set_max_dict_size(&mut self, value: u64) {
330 self.max_dict_size = value;
331 }
332}