delta_struct/
lib.rs

1pub use delta_struct_macros::Delta;
2
3pub trait Delta {
4    type Output;
5
6    fn delta(old: Self, new: Self) -> Option<Self::Output>;
7
8    fn apply_delta(&mut self, delta: Self::Output);
9}
10#[cfg(test)]
11mod tests {
12    use super::*;
13
14    #[derive(Delta)]
15    struct UnitType;
16
17    #[derive(Delta, Clone, Debug, PartialEq, Eq)]
18    #[delta_struct(delta_leader = "#[derive(Clone, Debug, PartialEq, Eq)]")]
19    struct NewType(i32);
20
21    #[derive(Delta)]
22    struct NewTypeWithGeneric<T>(T);
23
24    #[derive(Delta)]
25    struct SimpleType {
26        #[delta_struct(delta_leader = "/// This is foo.")]
27        foo: i32,
28        bar: bool,
29    }
30
31    #[derive(Delta)]
32    struct SimpleTypeWithGeneric<T> {
33        foo: T,
34        bar: bool,
35    }
36
37    #[derive(Delta)]
38    struct SimpleCollectionWithGeneric<T> {
39        #[delta_struct(
40            field_type = "unordered",
41            delta_leader = "/// This the foo type on the delta struct."
42        )]
43        foo: Vec<T>,
44        bar: bool,
45    }
46
47    #[derive(Delta)]
48    struct DeltaRecursion {
49        #[delta_struct(field_type = "delta")]
50        foo: NewType,
51        bar: bool,
52    }
53
54    #[derive(Delta)]
55    #[delta_struct(default = "unordered")]
56    struct AttributeTest {
57        #[delta_struct(field_type = "scalar")]
58        foo: i32,
59        #[delta_struct(field_type = "scalar")]
60        bar: i32,
61        baz: Vec<i32>,
62    }
63
64    #[derive(Delta, Clone, Debug, PartialEq, Eq)]
65    struct AllFieldTypes {
66        #[delta_struct(field_type = "scalar")]
67        scalar: i32,
68        #[delta_struct(field_type = "delta")]
69        delta: NewType,
70        #[delta_struct(field_type = "unordered")]
71        unordered: Vec<i32>,
72    }
73
74    #[derive(Clone, Debug, Delta, PartialEq)]
75    struct DeviceConfig {
76        #[delta_struct(field_type = "unordered")]
77        pub services: Vec<String>,
78        #[delta_struct(field_type = "unordered")]
79        pub settings: Vec<String>,
80        pub thumbnail_request: i32,
81        pub speedtest_request: i32,
82        #[delta_struct(field_type = "delta")]
83        pub features: AllFieldTypes,
84        pub deprovision: bool,
85    }
86
87    #[test]
88    fn unordered_with_scalar() {
89        let old = SimpleCollectionWithGeneric {
90            foo: vec![1, 2, 3],
91            bar: false,
92        };
93        let new = SimpleCollectionWithGeneric {
94            foo: vec![3, 4, 5],
95            bar: true,
96        };
97        let delta = Delta::delta(old, new).unwrap();
98        assert_eq!(delta.foo_add, vec![4, 5]);
99        assert_eq!(delta.foo_remove, vec![1, 2]);
100        assert_eq!(delta.bar, Some(true));
101    }
102
103    #[test]
104    fn delta_false_positive_check() {
105        let old = NewType(5);
106        let new = NewType(5);
107        let delta = Delta::delta(old, new);
108        assert!(delta.is_none());
109    }
110
111    #[test]
112    fn scalar_delta_false_positive_check() {
113        let old = SimpleType { foo: 5, bar: false };
114        let new = SimpleType { foo: 5, bar: true };
115        let delta = Delta::delta(old, new).unwrap();
116        assert!(delta.foo.is_none());
117        assert_eq!(delta.bar, Some(true));
118    }
119
120    #[test]
121    fn delta_field() {
122        let old = DeltaRecursion {
123            foo: NewType(5),
124            bar: false,
125        };
126        let new = DeltaRecursion {
127            foo: NewType(6),
128            bar: true,
129        };
130        let delta = Delta::delta(old, new).unwrap();
131        // TODO: Use assert_eq when we build out delta struct
132        // attributes.
133        if let Some(NewTypeDelta { field_0: Some(6) }) = delta.foo {
134            // Do nothing, this is the pass case.
135        } else {
136            panic!();
137        }
138        assert_eq!(delta.bar, Some(true));
139    }
140
141    #[test]
142    fn default_type_respected() {
143        let old = AttributeTest {
144            foo: 5,
145            bar: 4,
146            baz: vec![],
147        };
148        let new = AttributeTest {
149            foo: 5,
150            bar: 4,
151            baz: vec![9, 4, 5],
152        };
153        let delta = Delta::delta(old, new).unwrap();
154        assert!(delta.foo.is_none());
155        assert!(delta.bar.is_none());
156        assert_eq!(delta.baz_add, vec![9, 4, 5]);
157        assert_eq!(delta.baz_remove, vec![]);
158    }
159
160    #[test]
161    fn apply_delta_all_field_types() {
162        let old = AllFieldTypes {
163            scalar: 1,
164            delta: NewType(3),
165            unordered: vec![1, 2, 3, 3],
166        };
167        let new = AllFieldTypes {
168            scalar: 2,
169            delta: NewType(4),
170            unordered: vec![3, 4, 5],
171        };
172        let new_clone = new.clone();
173        let mut old_delta_applied = old.clone();
174        let delta = Delta::delta(old, new);
175        old_delta_applied.apply_delta(delta.unwrap());
176        assert_eq!(new_clone, old_delta_applied);
177    }
178}