cumulo_dipa/map/
map_impl_macro.rs1#[macro_export]
2macro_rules! map_impl {
3 ($map_ty:ty, $module:ident, $($additional_key_bounds:tt)*) => {
4 mod $module {
5 use super::{MapDelta, MapDeltaOwned};
6 use crate::{CreatedDelta, Diffable, Patchable};
7 use serde::{Serialize, de::DeserializeOwned};
8 use std::hash::Hash;
9
10 type MapAssociatedDeltaOwned<'s, 'e, K, V> =
11 <$map_ty as Diffable<'s, 'e, $map_ty>>::DeltaOwned;
12
13 impl<'s, 'e, K, V> Diffable<'s, 'e, $map_ty> for $map_ty
14 where
15 K: 's + 'e + Eq + Hash $($additional_key_bounds)*,
16 V: 'e + Diffable<'s, 'e, V>,
17 <V as Diffable<'s,'e,V>>::Delta: Serialize,
18 <V as Diffable<'s,'e,V>>::DeltaOwned: DeserializeOwned
19 {
20 type Delta = MapDelta<'s, 'e, K, V>;
21 type DeltaOwned = MapDeltaOwned<'s, 'e, K, V>;
22
23 fn create_delta_towards(
24 &'s self,
25 end_state: &'e $map_ty,
26 ) -> CreatedDelta<Self::Delta> {
27 let mut did_change = false;
28
29 if end_state.len() == 0 && self.len() > 0 {
30 let delta = MapDelta::RemoveAll;
31 return CreatedDelta {
32 delta,
33 did_change: true
34 };
35 }
36
37 let mut delta = MapDelta::NoChange;
38
39 let mut fields_to_add = Vec::new();
40 let mut fields_to_remove = Vec::new();
41 let mut fields_changed = Vec::new();
42
43 for (key, start) in self.iter() {
44 match end_state.get(key) {
45 None => {
46 did_change = true;
47 fields_to_remove.push(key);
48 }
49 Some(end) => {
50 let CreatedDelta {delta, did_change: changed} = start.create_delta_towards(end);
51
52 if changed {
53 did_change = true;
54 fields_changed.push((key, delta));
55 }
56 }
57 }
58 }
59
60 for (key, val) in end_state.iter() {
61 if !self.contains_key(key) {
62 did_change = true;
63 fields_to_add.push((key, val));
64 }
65 }
66
67 let many_fields_to_add = fields_to_add.len() > 1;
68 let many_fields_to_remove = fields_to_remove.len() > 1;
69 let many_fields_changed = fields_changed.len() > 1;
70
71 let one_field_to_add = fields_to_add.len() == 1;
72 let one_field_to_remove = fields_to_remove.len() == 1;
73 let one_field_changed = fields_changed.len() == 1;
74
75 let encode_using_many_variant =
76 many_fields_to_add || many_fields_to_remove || many_fields_changed;
77
78 if encode_using_many_variant {
79 delta = MapDelta::ModifyMany {
80 added: fields_to_add,
81 removed: fields_to_remove,
82 changed: fields_changed,
83 }
84 } else if one_field_to_add {
85 delta = MapDelta::AddOneField(fields_to_add[0].0, fields_to_add[0].1);
86 } else if one_field_to_remove {
87 delta = MapDelta::RemoveOneField(fields_to_remove[0]);
88 } else if one_field_changed {
89 let change = fields_changed.remove(0);
90 delta = MapDelta::ChangeOneField(change.0, change.1);
91 }
92
93 CreatedDelta {
94 delta,
95 did_change
96 }
97 }
98 }
99
100 impl<'s, 'e, K, V> Patchable<MapAssociatedDeltaOwned<'s, 'e, K, V>> for $map_ty
101 where
102 K: 's + 'e + Eq + Hash $($additional_key_bounds)*,
103 V: 'e + Diffable<'s, 'e, V>,
104 V: Patchable<<V as Diffable<'s, 'e, V>>::DeltaOwned>,
105 <V as Diffable<'s,'e,V>>::Delta: Serialize,
106 <V as Diffable<'s,'e,V>>::DeltaOwned: DeserializeOwned
107 {
108 fn apply_patch(&mut self, patch: MapAssociatedDeltaOwned<'s, 'e, K, V>) {
109 match patch {
110 MapDeltaOwned::NoChange => {}
111 MapDeltaOwned::RemoveAll => self.clear(),
112 MapDeltaOwned::AddOneField(k, v) => {
113 self.insert(k, v);
114 }
115 MapDeltaOwned::RemoveOneField(k) => {
116 self.remove(&k);
117 }
118 MapDeltaOwned::ChangeOneField(k, delta) => {
119 self.get_mut(&k).unwrap().apply_patch(delta);
120 }
121 MapDeltaOwned::ModifyMany {
122 added,
123 removed,
124 changed,
125 } => {
126 for add in added {
127 self.insert(add.0, add.1);
128 }
129
130 for remove in removed {
131 self.remove(&remove);
132 }
133
134 for change in changed {
135 self.get_mut(&change.0).unwrap().apply_patch(change.1);
136 }
137 }
138 }
139 }
140 }
141 }
142 };
143}