1use serde_json::Value;
5use std::collections::BTreeMap;
6use std::collections::HashMap;
7
8use crate::error::Result;
9use crate::hashmap::DiffHashMap;
10use crate::traits::Diff;
11
12pub type DiffObject = DiffHashMap<String, Value>;
13
14type ObjectSrc = BTreeMap<String, Value>;
15type ObjectDst = HashMap<String, Value>;
16
17impl Diff for ObjectSrc {
18 type Type = DiffObject;
19
20 fn diff(&self, other: &Self) -> Result<Self::Type> {
21 let a: ObjectDst = self.clone().into_iter().collect();
22 let b: ObjectDst = other.clone().into_iter().collect();
23
24 a.diff(&b)
25 }
26
27 fn merge(&self, diff: Self::Type) -> Result<Self> {
28 let this: ObjectDst = self.clone().into_iter().collect();
29 let this: ObjectDst = this.merge(diff)?;
30
31 Ok(this.into_iter().collect())
32 }
33
34 fn from_diff(diff: Self::Type) -> Result<Self> {
35 Ok(ObjectDst::from_diff(diff)?.into_iter().collect())
36 }
37
38 fn into_diff(self) -> Result<Self::Type> {
39 self.into_iter().collect::<ObjectDst>().into_diff()
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use crate::hashmap::InnerValue;
47 use serde_json::json;
48
49 #[test]
50 fn test_diff_empty() {
51 let a: ObjectSrc = ObjectSrc::default();
53 let b: ObjectSrc = ObjectSrc::default();
54 let diff: DiffObject = Diff::diff(&a, &b).unwrap();
55 assert!(diff.0.is_none());
56 let merge: ObjectSrc = a.merge(diff.clone()).unwrap();
57 assert_eq!(merge, a);
58
59 let serialized: String = serde_json::to_string(&diff).unwrap();
61 let deserialized: DiffObject = serde_json::from_str(&serialized).unwrap();
62 assert_eq!(diff, deserialized)
63 }
64
65 #[test]
66 fn test_diff() {
67 let mut a: ObjectSrc = ObjectSrc::new();
68 a.insert("foo".into(), 12.into());
69 a.insert("bar".into(), 34.into());
70 a.insert("baz".into(), 56.into());
71 a.insert("qux".into(), 78.into());
72
73 let mut b: ObjectSrc = ObjectSrc::new();
74 b.insert("foo".into(), 56.into());
75 b.insert("thud".into(), 9.into());
76 b.insert("bar".into(), 34.into());
77 b.insert("qux".into(), 78.into());
78
79 let diff: DiffObject = Diff::diff(&a, &b).unwrap();
80 let expected: DiffObject = DiffHashMap(Some(vec![
81 InnerValue::Change {
82 key: "foo".into(),
83 value: json!(56).into_diff().unwrap(),
84 },
85 InnerValue::Add {
86 key: "thud".into(),
87 value: json!(9).into_diff().unwrap(),
88 },
89 InnerValue::Remove { key: "baz".into() },
90 ]));
91 assert_eq!(expected, diff);
92
93 let merge: ObjectSrc = a.merge(diff.clone()).unwrap();
94 assert_eq!(merge, b);
95
96 let serialized: String = serde_json::to_string(&diff).unwrap();
98 let deserialized: DiffObject = serde_json::from_str(&serialized).unwrap();
99 assert_eq!(diff, deserialized)
100 }
101}