1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#[macro_export]
macro_rules! set_impl {
($map_ty:ty, $module:ident, $($additional_key_bounds:tt)*) => {
mod $module {
use super::{SetDelta, SetDeltaOwned};
use crate::{CreatedDelta, Diffable, Patchable};
use std::hash::Hash;
type SetAssociatedDeltaOwned<'s, 'e, K> =
<$map_ty as Diffable<'s, 'e, $map_ty>>::DeltaOwned;
impl<'s, 'e, K> Diffable<'s, 'e, $map_ty> for $map_ty
where
K: 's + 'e + Eq + Hash $($additional_key_bounds)*,
{
type Delta = SetDelta<'s, 'e, K>;
type DeltaOwned = SetDeltaOwned<K>;
fn create_delta_towards(
&'s self,
end_state: &'e $map_ty,
) -> CreatedDelta<Self::Delta> {
let mut did_change = false;
if end_state.len() == 0 && self.len() > 0 {
let delta = SetDelta::RemoveAll;
return CreatedDelta {
delta,
did_change: true,
};
}
let mut delta = SetDelta::NoChange;
let mut fields_to_add = Vec::new();
let mut fields_to_remove = Vec::new();
for key in self.iter() {
if !end_state.contains(key) {
did_change = true;
fields_to_remove.push(key);
}
}
for key in end_state.iter() {
if !self.contains(key) {
did_change = true;
fields_to_add.push(key);
}
}
let many_fields_to_add = fields_to_add.len() > 1;
let many_fields_to_remove = fields_to_remove.len() > 1;
let one_field_to_add = fields_to_add.len() == 1;
let one_field_to_remove = fields_to_remove.len() == 1;
let encode_using_many_variant =
many_fields_to_add || many_fields_to_remove ;
if encode_using_many_variant {
delta = SetDelta::ModifyMany {
added: fields_to_add,
removed: fields_to_remove,
}
} else if one_field_to_add {
delta = SetDelta::AddOneField(fields_to_add[0]);
} else if one_field_to_remove {
delta = SetDelta::RemoveOneField(fields_to_remove[0]);
}
CreatedDelta {
delta,
did_change,
}
}
}
impl<'s, 'e, K> Patchable<SetAssociatedDeltaOwned<'s, 'e, K>> for $map_ty
where
K: 's + 'e + Eq + Hash $($additional_key_bounds)*,
{
fn apply_patch(&mut self, patch: SetAssociatedDeltaOwned<'s, 'e, K>) {
match patch {
SetDeltaOwned::NoChange => {}
SetDeltaOwned::RemoveAll => self.clear(),
SetDeltaOwned::AddOneField(k) => {
self.insert(k);
}
SetDeltaOwned::RemoveOneField(k) => {
self.remove(&k);
}
SetDeltaOwned::ModifyMany {
added,
removed,
} => {
for add in added {
self.insert(add);
}
for remove in removed {
self.remove(&remove);
}
}
}
}
}
}
};
}