1use crate::Diffable;
2use serde::de::DeserializeOwned;
3use serde::Serialize;
4use std::fmt::{Debug, Formatter};
5
6#[macro_use]
7mod map_impl_macro;
8
9map_impl!(std::collections::HashMap<K,V>, hash_map_impl, );
10map_impl!(std::collections::BTreeMap<K,V>, btree_map_impl, + Ord);
11
12#[derive(Serialize)]
13pub enum MapDelta<'s, 'e, K, V: Diffable<'s, 'e, V>>
15where
16 <V as Diffable<'s, 'e, V>>::Delta: Serialize,
17{
18 NoChange,
20 RemoveAll,
22 AddOneField(&'e K, &'e V),
24 RemoveOneField(&'s K),
26 ChangeOneField(&'s K, <V as Diffable<'s, 'e, V>>::Delta),
28 ModifyMany {
30 added: Vec<(&'e K, &'e V)>,
31 removed: Vec<&'s K>,
32 changed: Vec<(&'s K, <V as Diffable<'s, 'e, V>>::Delta)>,
33 },
34}
35
36#[derive(Deserialize)]
37#[allow(missing_docs)]
38pub enum MapDeltaOwned<'s, 'e, K, V: Diffable<'s, 'e, V>>
40where
41 <V as Diffable<'s, 'e, V>>::DeltaOwned: DeserializeOwned,
42{
43 NoChange,
45 RemoveAll,
47 AddOneField(K, V),
49 RemoveOneField(K),
51 ChangeOneField(K, <V as Diffable<'s, 'e, V>>::DeltaOwned),
53 ModifyMany {
55 added: Vec<(K, V)>,
56 removed: Vec<K>,
57 changed: Vec<(K, <V as Diffable<'s, 'e, V>>::DeltaOwned)>,
58 },
59}
60
61impl<'s, 'e, K, V> Debug for MapDelta<'s, 'e, K, V>
63where
64 V: Diffable<'s, 'e, V>,
65 <V as Diffable<'s, 'e, V>>::Delta: Debug,
66 <V as Diffable<'s, 'e, V>>::Delta: Serialize,
67 K: Debug,
68 V: Debug,
69{
70 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
71 match self {
72 MapDelta::NoChange => {
73 f.write_str("NoChange")?;
74 }
75 MapDelta::RemoveAll => {
76 f.write_str("RemoveAll")?;
77 }
78 MapDelta::AddOneField(k, v) => {
79 f.debug_tuple("AddOneField").field(k).field(v).finish()?;
80 }
81 MapDelta::RemoveOneField(k) => {
82 f.debug_tuple("RemoveOneField").field(k).finish()?;
83 }
84 MapDelta::ChangeOneField(k, diff) => {
85 f.debug_tuple("ChangeOneField")
86 .field(k)
87 .field(diff)
88 .finish()?;
89 }
90 MapDelta::ModifyMany {
91 added,
92 removed,
93 changed,
94 } => {
95 f.debug_struct("ModifyMany")
96 .field("added", added)
97 .field("removed", removed)
98 .field("changed", changed)
99 .finish()?;
100 }
101 };
102
103 Ok(())
104 }
105}
106
107impl<'s, 'e, K, V> PartialEq for MapDelta<'s, 'e, K, V>
109where
110 V: Diffable<'s, 'e, V>,
111 <V as Diffable<'s, 'e, V>>::Delta: PartialEq,
112 <V as Diffable<'s, 'e, V>>::Delta: Serialize,
113 K: PartialEq,
114 V: PartialEq,
115{
116 fn eq(&self, other: &Self) -> bool {
117 match (self, other) {
119 (Self::NoChange, Self::NoChange) => true,
120 (Self::NoChange, _) => false,
121
122 (
123 Self::ModifyMany {
124 added: left_added,
125 removed: left_removed,
126 changed: left_changed,
127 },
128 Self::ModifyMany {
129 added: right_added,
130 removed: right_removed,
131 changed: right_changed,
132 },
133 ) => {
134 left_added == right_added
135 && left_removed == right_removed
136 && left_changed == right_changed
137 }
138 (Self::ModifyMany { .. }, _) => false,
139
140 (
141 Self::ChangeOneField(left_k, left_diff),
142 Self::ChangeOneField(right_k, right_diff),
143 ) => left_k == right_k && left_diff == right_diff,
144 (Self::ChangeOneField(..), _) => false,
145
146 (Self::RemoveOneField(left_k), Self::RemoveOneField(right_k)) => left_k == right_k,
147 (Self::RemoveOneField(_), _) => false,
148
149 (Self::AddOneField(left_k, left_v), Self::AddOneField(right_k, right_v)) => {
150 left_k == right_k && left_v == right_v
151 }
152 (Self::AddOneField(..), _) => false,
153
154 (Self::RemoveAll, Self::RemoveAll) => true,
155 (Self::RemoveAll, _) => false,
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use crate::DipaImplTester;
164 use std::collections::{BTreeMap, HashMap};
165
166 #[test]
168 fn unchanged_empty_hashmap() {
169 DipaImplTester {
170 label: None,
171 start: &mut HashMap::<(), ()>::new(),
172 end: &HashMap::new(),
173 expected_delta: MapDelta::NoChange,
174 expected_serialized_patch_size: 1,
175 expected_did_change: false,
176 }
177 .test();
178 }
179
180 #[test]
182 fn unchanged_hashmap() {
183 DipaImplTester {
184 label: None,
185 start: &mut vec![(1u32, 2u64)].into_iter().collect::<HashMap<_, _>>(),
186 end: &vec![(1, 2)].into_iter().collect(),
187 expected_delta: MapDelta::NoChange,
188 expected_serialized_patch_size: 1,
189 expected_did_change: false,
190 }
191 .test();
192 }
193
194 #[test]
196 fn all_fields_removed() {
197 DipaImplTester {
198 label: None,
199 start: &mut vec![(1u32, 2u64)].into_iter().collect(),
200 end: &HashMap::new(),
201 expected_delta: MapDelta::RemoveAll,
202 expected_serialized_patch_size: 1,
203 expected_did_change: true,
204 }
205 .test();
206 }
207
208 #[test]
210 fn one_field_added() {
211 DipaImplTester {
212 label: None,
213 start: &mut HashMap::new(),
214 end: &vec![(1u32, 2u64)].into_iter().collect(),
215 expected_delta: MapDelta::AddOneField(&1, &2),
216 expected_serialized_patch_size: 3,
217 expected_did_change: true,
218 }
219 .test();
220 }
221
222 #[test]
224 fn one_field_removed() {
225 DipaImplTester {
226 label: None,
227 start: &mut vec![(1u32, 2u64), (3, 4)]
228 .into_iter()
229 .collect::<HashMap<_, _>>(),
230 end: &vec![(1, 2)].into_iter().collect(),
231 expected_delta: MapDelta::RemoveOneField(&3),
232 expected_serialized_patch_size: 2,
233 expected_did_change: true,
234 }
235 .test();
236 }
237
238 #[test]
240 fn one_field_changed() {
241 DipaImplTester {
242 label: None,
243 start: &mut vec![(1u32, 2u64), (3, 4)]
244 .into_iter()
245 .collect::<HashMap<_, _>>(),
246 end: &vec![(1, 2), (3, 9)].into_iter().collect(),
247 expected_delta: MapDelta::ChangeOneField(&3, Some(9)),
248 expected_serialized_patch_size: 4,
249 expected_did_change: true,
250 }
251 .test();
252 }
253
254 #[test]
256 fn many_fields_added() {
257 DipaImplTester {
258 label: None,
259 start: &mut BTreeMap::new(),
260 end: &vec![(1u32, 2u64), (3, 4)].into_iter().collect(),
261 expected_delta: MapDelta::ModifyMany {
262 added: vec![(&1, &2), (&3, &4)],
263 removed: vec![],
264 changed: vec![],
265 },
266 expected_serialized_patch_size: 8,
267 expected_did_change: true,
268 }
269 .test();
270 }
271
272 #[test]
274 fn many_fields_removed() {
275 DipaImplTester {
276 label: None,
277 start: &mut vec![(1u32, 2u64), (3, 4), (5, 6)]
278 .into_iter()
279 .collect::<BTreeMap<_, _>>(),
280 end: &vec![(1, 2)].into_iter().collect(),
281 expected_delta: MapDelta::ModifyMany {
282 added: vec![],
283 removed: vec![&3, &5],
284 changed: vec![],
285 },
286 expected_serialized_patch_size: 6,
287 expected_did_change: true,
288 }
289 .test();
290 }
291
292 #[test]
294 fn many_fields_changed() {
295 DipaImplTester {
296 label: None,
297 start: &mut vec![(1u32, 2u64), (3, 4)]
298 .into_iter()
299 .collect::<BTreeMap<_, _>>(),
300 end: &vec![(1, 15), (3, 16)].into_iter().collect(),
301 expected_delta: MapDelta::ModifyMany {
302 added: vec![],
303 removed: vec![],
304 changed: vec![(&1, Some(15)), (&3, Some(16))],
305 },
306 expected_serialized_patch_size: 10,
307 expected_did_change: true,
308 }
309 .test();
310 }
311}