json0_rs/
json.rs

1use std::mem;
2
3use crate::{
4    error::{JsonError, Result},
5    operation::Operator,
6    path::Path,
7};
8
9use serde_json::Value;
10
11pub trait Routable {
12    fn route_get(&self, paths: &Path) -> Result<Option<&Value>>;
13
14    fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>>;
15}
16
17pub trait Appliable {
18    fn apply(&mut self, paths: Path, operator: Operator) -> Result<()>;
19}
20
21impl Routable for Value {
22    fn route_get(&self, paths: &Path) -> Result<Option<&Value>> {
23        match self {
24            Value::Array(array) => array.route_get(paths),
25            Value::Object(obj) => obj.route_get(paths),
26            Value::Null => Ok(None),
27            _ => {
28                if paths.is_empty() {
29                    Ok(Some(self))
30                } else {
31                    Err(JsonError::BadPath)
32                }
33            }
34        }
35    }
36
37    fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>> {
38        match self {
39            Value::Array(array) => array.route_get_mut(paths),
40            Value::Object(obj) => obj.route_get_mut(paths),
41            _ => {
42                if paths.is_empty() {
43                    Ok(Some(self))
44                } else {
45                    Err(JsonError::BadPath)
46                }
47            }
48        }
49    }
50}
51
52impl Routable for serde_json::Map<String, serde_json::Value> {
53    fn route_get(&self, paths: &Path) -> Result<Option<&Value>> {
54        let k = paths.first_key_path().ok_or(JsonError::BadPath)?;
55        if let Some(v) = self.get(k) {
56            let next_level = paths.next_level();
57            if next_level.is_empty() {
58                Ok(Some(v))
59            } else {
60                v.route_get(&next_level)
61            }
62        } else {
63            Ok(None)
64        }
65    }
66
67    fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>> {
68        let k = paths.first_key_path().ok_or(JsonError::BadPath)?;
69        if let Some(v) = self.get_mut(k) {
70            let next_level = paths.next_level();
71            if next_level.is_empty() {
72                Ok(Some(v))
73            } else {
74                v.route_get_mut(&next_level)
75            }
76        } else {
77            Ok(None)
78        }
79    }
80}
81
82impl Routable for Vec<serde_json::Value> {
83    fn route_get(&self, paths: &Path) -> Result<Option<&Value>> {
84        let i = paths.first_index_path().ok_or(JsonError::BadPath)?;
85        if let Some(v) = self.get(*i) {
86            let next_level = paths.next_level();
87            if next_level.is_empty() {
88                Ok(Some(v))
89            } else {
90                v.route_get(&next_level)
91            }
92        } else {
93            Ok(None)
94        }
95    }
96
97    fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>> {
98        let i = paths.first_index_path().ok_or(JsonError::BadPath)?;
99        if let Some(v) = self.get_mut(*i) {
100            let next_level = paths.next_level();
101            if next_level.is_empty() {
102                Ok(Some(v))
103            } else {
104                v.route_get_mut(&next_level)
105            }
106        } else {
107            Ok(None)
108        }
109    }
110}
111
112impl Appliable for Value {
113    fn apply(&mut self, paths: Path, op: Operator) -> Result<()> {
114        if paths.len() > 1 {
115            let (left, right) = paths.split_at(paths.len() - 1);
116            return self
117                .route_get_mut(&left)?
118                .ok_or(JsonError::BadPath)?
119                .apply(right, op);
120        }
121        match self {
122            Value::Array(array) => array.apply(paths, op),
123            Value::Object(obj) => obj.apply(paths, op),
124            _ => match op {
125                Operator::SubType(_, op, f) => {
126                    if let Some(v) = f.apply(Some(self), &op)? {
127                        _ = mem::replace(self, v);
128                    }
129                    Ok(())
130                }
131                _ => Err(JsonError::InvalidOperation(
132                    "Operation can only apply on array or object".into(),
133                )),
134            },
135        }
136    }
137}
138
139impl Appliable for serde_json::Map<String, serde_json::Value> {
140    fn apply(&mut self, paths: Path, op: Operator) -> Result<()> {
141        assert!(paths.len() == 1);
142
143        let k = paths.first_key_path().ok_or(JsonError::BadPath)?;
144        let target_value = self.get(k);
145        match &op {
146            Operator::SubType(_, op, f) => {
147                if let Some(v) = f.apply(target_value, op)? {
148                    self.insert(k.clone(), v);
149                }
150                Ok(())
151            }
152            Operator::ObjectInsert(v) => {
153                self.insert(k.clone(), v.clone());
154                Ok(())
155            }
156            Operator::ObjectDelete(_) => {
157                if target_value.is_some() {
158                    // we don't check the equality of the values
159                    // because OT is hard to implement
160                    // if target_v.eq(&delete_v) {
161                    self.remove(k);
162                    // }
163                }
164                Ok(())
165            }
166            Operator::ObjectReplace(new_v, _) => {
167                if target_value.is_some() {
168                    // we don't check the equality of the values
169                    // because OT is hard to implement
170                    // if target_v.eq(&old_v) {
171                    self.insert(k.clone(), new_v.clone());
172                    // }
173                }
174                Ok(())
175            }
176            _ => Err(JsonError::BadPath),
177        }
178    }
179}
180
181impl Appliable for Vec<serde_json::Value> {
182    fn apply(&mut self, paths: Path, op: Operator) -> Result<()> {
183        assert!(paths.len() == 1);
184
185        let index = paths.first_index_path().ok_or(JsonError::BadPath)?;
186        let target_value = self.get(*index);
187        match op {
188            Operator::SubType(_, op, f) => {
189                if let Some(v) = f.apply(target_value, &op)? {
190                    self[*index] = v;
191                }
192                Ok(())
193            }
194            Operator::ListInsert(v) => {
195                if *index > self.len() {
196                    self.push(v.clone())
197                } else {
198                    self.insert(*index, v.clone());
199                }
200                Ok(())
201            }
202            Operator::ListDelete(_) => {
203                if target_value.is_some() {
204                    // we don't check the equality of the values
205                    // because OT is hard to implement
206                    // if target_v.eq(&delete_v) {
207                    self.remove(*index);
208                    // }
209                }
210                Ok(())
211            }
212            Operator::ListReplace(new_v, _) => {
213                if target_value.is_some() {
214                    // we don't check the equality of the values
215                    // because OT is hard to implement
216                    // if target_v.eq(&old_v) {
217                    self[*index] = new_v.clone();
218                    // }
219                }
220                Ok(())
221            }
222            Operator::ListMove(new_index) => {
223                if let Some(target_v) = target_value {
224                    if *index != new_index {
225                        let new_v = target_v.clone();
226                        self.remove(*index);
227                        self.insert(new_index, new_v);
228                    }
229                }
230                Ok(())
231            }
232            _ => Err(JsonError::BadPath),
233        }
234    }
235}
236
237#[cfg(test)]
238mod tests {
239    use crate::path::Path;
240
241    use super::*;
242    use test_log::test;
243
244    #[test]
245    fn test_route_get_by_path_only_has_object() {
246        let json: Value =
247            serde_json::from_str(r#"{"level1":"world", "level12":{"level2":"world2"}}"#).unwrap();
248
249        // simple path with only object
250        let paths = Path::try_from(r#"["level1"]"#).unwrap();
251        assert_eq!(
252            json.route_get(&paths).unwrap().unwrap().to_string(),
253            r#""world""#
254        );
255        let paths = Path::try_from(r#"["level12", "level2"]"#).unwrap();
256        assert_eq!(
257            json.route_get(&paths).unwrap().unwrap().to_string(),
258            r#""world2""#
259        );
260        let paths = Path::try_from(r#"["level3"]"#).unwrap();
261        assert!(json.route_get(&paths).unwrap().is_none());
262
263        // complex path with array
264        let json: Value =
265            serde_json::from_str(r#"{"level1":[1,{"hello":[1,[7,8]]}], "level12":"world"}"#)
266                .unwrap();
267        let paths = Path::try_from(r#"["level1", 1, "hello"]"#).unwrap();
268
269        assert_eq!(
270            json.route_get(&paths).unwrap().unwrap().to_string(),
271            r#"[1,[7,8]]"#
272        );
273    }
274
275    #[test]
276    fn test_route_get_by_path_has_array() {
277        let json: Value =
278            serde_json::from_str(r#"{"level1":["a","b"], "level12":[123, {"level2":["c","d"]}]}"#)
279                .unwrap();
280        // simple path
281        let paths = Path::try_from(r#"["level1", 1]"#).unwrap();
282        assert_eq!(
283            json.route_get(&paths).unwrap().unwrap().to_string(),
284            r#""b""#
285        );
286        let paths = Path::try_from(r#"["level12", 0]"#).unwrap();
287
288        // complex path
289        assert_eq!(
290            json.route_get(&paths).unwrap().unwrap().to_string(),
291            r#"123"#
292        );
293        let paths = Path::try_from(r#"["level12", 1, "level2"]"#).unwrap();
294        assert_eq!(
295            json.route_get(&paths).unwrap().unwrap().to_string(),
296            r#"["c","d"]"#
297        );
298        let json: Value =
299            serde_json::from_str(r#"{"level1":[1,{"hello":[1,[7,8]]}], "level12":"world"}"#)
300                .unwrap();
301        let paths = Path::try_from(r#"["level1", 1, "hello", 1]"#).unwrap();
302
303        assert_eq!(
304            json.route_get(&paths).unwrap().unwrap().to_string(),
305            r#"[7,8]"#
306        );
307    }
308}