1use serde_json::{Map, Value};
2
3use crate::{error::Error, Result};
4
5#[derive(Debug)]
6pub struct Decompressor {
7 refs: Vec<Value>,
8 input: Value,
9 output: Value,
10}
11
12impl Decompressor {
13 pub fn new(value: &str) -> Result<Self> {
21 let input = serde_json::from_str(value)?;
22
23 Ok(Self {
24 input,
25 refs: Vec::new(),
26 output: Value::default(),
27 })
28 }
29
30 pub fn decompress(&mut self) -> Result<String> {
36 if !self.input.is_array() || self.input.as_array().unwrap().len() != 2 {
37 return Ok(self.input.to_string());
38 }
39
40 self.refs = match self.input.get(1) {
41 Some(values) => values.as_array().unwrap().clone(),
42 None => Vec::new(),
43 };
44
45 let result = match self.input.get(0) {
46 Some(value) => {
47 let output = match value {
48 Value::Array(a) => self.find_array_value_by_ref(a),
49 Value::Object(o) => self.find_object_value_by_ref(o),
50 _ => self.find_value_by_ref(value),
51 }?;
52
53 output.to_string()
54 }
55 None => Value::Null.to_string(),
56 };
57
58 Ok(result)
59 }
60
61 pub(self) fn find_array_value_by_ref(&self, value: &[Value]) -> Result<Value> {
62 let items: Result<Vec<Value>> = value
63 .iter()
64 .map(|v| match v {
65 Value::Array(a) => self.find_array_value_by_ref(a),
66 Value::Object(o) => self.find_object_value_by_ref(o),
67 _ => self.find_value_by_ref(v),
68 })
69 .collect();
70
71 Ok(Value::Array(items?))
72 }
73
74 pub(self) fn find_object_value_by_ref(&self, value: &Map<String, Value>) -> Result<Value> {
75 let mut new_obj: Map<String, Value> = Map::new();
76
77 for (obj_key, obj_value) in value.clone().iter() {
78 let k = self.refs[obj_key.parse::<usize>().unwrap()]
79 .as_str()
80 .unwrap();
81
82 let v = match obj_value {
83 Value::Array(a) => self.find_array_value_by_ref(a),
84 Value::Object(o) => self.find_object_value_by_ref(o),
85 _ => self.find_value_by_ref(obj_value),
86 }?;
87
88 new_obj.insert(k.to_string(), v);
89 }
90
91 Ok(Value::Object(new_obj))
92 }
93
94 pub(self) fn find_value_by_ref(&self, value: &Value) -> Result<Value> {
95 match value {
96 Value::Number(n) => {
97 let index = n.as_u64().unwrap() as usize;
98 Ok(self.refs[index].clone())
99 }
100 Value::String(s) => {
101 let index: usize = s.parse().unwrap();
102 Ok(self.refs[index].clone())
103 }
104 _ => Err(Error::UnknownJSONValueRef(value.to_string())),
105 }
106 }
107}
108
109pub fn decompress_json(json: &str) -> Result<String> {
119 Decompressor::new(json)?.decompress()
120}
121
122#[cfg(test)]
123mod test {
124 use super::*;
125
126 const OUTPUT_SAMPLE: &str = include_str!("../../samples/test-samples/output.json");
127 const INPUT_SAMPLE: &str = include_str!("../../samples/test-samples/input.json");
128
129 #[test]
130 fn should_return_valid_json() -> crate::Result<()> {
131 let result = Decompressor::new(OUTPUT_SAMPLE)?.decompress()?;
132 let output: Value = serde_json::from_str(&result)?;
133 assert_eq!(true, output.is_object());
134 Ok(())
135 }
136
137 #[test]
138 fn should_be_equal_to_original_json() -> crate::Result<()> {
139 let result = Decompressor::new(OUTPUT_SAMPLE)?.decompress()?;
140 let result_value: Value = serde_json::from_str(&result)?;
141 let expect: Value = serde_json::from_str(INPUT_SAMPLE)?;
142 assert_eq!(expect, result_value);
143 Ok(())
144 }
145
146 #[test]
147 fn should_return_original_input_if_not_array() -> crate::Result<()> {
148 let result = Decompressor::new(r#"{"ok":"ok"}"#)?.decompress()?;
149 let result_value: Value = serde_json::from_str(&result)?;
150 let mut expected = Map::new();
151 expected.insert("ok".to_string(), Value::String("ok".to_string()));
152 assert_eq!(Value::Object(expected), result_value);
153 Ok(())
154 }
155
156 #[test]
157 fn should_return_original_input_if_not_array_expected_length() -> crate::Result<()> {
158 let result = Decompressor::new(r#"[{"ok":"ok"}]"#)?.decompress()?;
159 let result_obj: Value = serde_json::from_str(&result)?;
160 let mut expected = Map::new();
161 expected.insert("ok".to_string(), Value::String("ok".to_string()));
162 assert_eq!(Value::Array(vec![Value::Object(expected)]), result_obj);
163 Ok(())
164 }
165}