1use serde::Serialize;
2use std::fmt::{Debug, Formatter};
3
4#[macro_use]
5mod set_impl_macro;
6
7set_impl!(std::collections::HashSet<K>, hash_map_impl,);
8set_impl!(std::collections::BTreeSet<K>, btree_map_impl, + Ord);
9
10#[derive(Serialize)]
11pub enum SetDelta<'s, 'e, K> {
13 NoChange,
15 RemoveAll,
17 AddOneField(&'e K),
19 RemoveOneField(&'s K),
21 ModifyMany {
23 added: Vec<&'e K>,
24 removed: Vec<&'s K>,
25 },
26}
27
28#[derive(Deserialize)]
29#[allow(missing_docs)]
30pub enum SetDeltaOwned<K> {
32 NoChange,
34 RemoveAll,
36 AddOneField(K),
38 RemoveOneField(K),
40 ModifyMany { added: Vec<K>, removed: Vec<K> },
42}
43
44impl<'s, 'e, K> Debug for SetDelta<'s, 'e, K>
46where
47 K: Debug,
48{
49 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50 match self {
51 SetDelta::NoChange => {
52 f.write_str("NoChange")?;
53 }
54 SetDelta::RemoveAll => {
55 f.write_str("RemoveAll")?;
56 }
57 SetDelta::AddOneField(k) => {
58 f.debug_tuple("AddOneField").field(k).finish()?;
59 }
60 SetDelta::RemoveOneField(k) => {
61 f.debug_tuple("RemoveOneField").field(k).finish()?;
62 }
63 SetDelta::ModifyMany { added, removed } => {
64 f.debug_struct("ModifyMany")
65 .field("added", added)
66 .field("removed", removed)
67 .finish()?;
68 }
69 };
70
71 Ok(())
72 }
73}
74
75impl<'s, 'e, K> PartialEq for SetDelta<'s, 'e, K>
77where
78 K: PartialEq,
79{
80 fn eq(&self, other: &Self) -> bool {
81 match (self, other) {
83 (Self::NoChange, Self::NoChange) => true,
84 (Self::NoChange, _) => false,
85
86 (
87 Self::ModifyMany {
88 added: left_added,
89 removed: left_removed,
90 },
91 Self::ModifyMany {
92 added: right_added,
93 removed: right_removed,
94 },
95 ) => left_added == right_added && left_removed == right_removed,
96 (Self::ModifyMany { .. }, _) => false,
97
98 (Self::AddOneField(left_k), Self::AddOneField(right_k)) => left_k == right_k,
99 (Self::AddOneField(..), _) => false,
100
101 (Self::RemoveOneField(left_k), Self::RemoveOneField(right_k)) => left_k == right_k,
102 (Self::RemoveOneField(_), _) => false,
103
104 (Self::RemoveAll, Self::RemoveAll) => true,
105 (Self::RemoveAll, _) => false,
106 }
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use crate::DipaImplTester;
114 use std::collections::{BTreeSet, HashSet};
115
116 #[test]
118 fn unchanged_empty_hashmap() {
119 DipaImplTester {
120 label: None,
121 start: &mut HashSet::<()>::new(),
122 end: &HashSet::new(),
123 expected_delta: SetDelta::NoChange,
124 expected_serialized_patch_size: 1,
125 expected_did_change: false,
126 }
127 .test();
128 }
129
130 #[test]
132 fn unchanged_hashmap() {
133 DipaImplTester {
134 label: None,
135 start: &mut vec![1u32].into_iter().collect::<HashSet<_>>(),
136 end: &vec![1].into_iter().collect(),
137 expected_delta: SetDelta::NoChange,
138 expected_serialized_patch_size: 1,
139 expected_did_change: false,
140 }
141 .test();
142 }
143
144 #[test]
146 fn all_fields_removed() {
147 DipaImplTester {
148 label: None,
149 start: &mut vec![1u32, 22].into_iter().collect(),
150 end: &HashSet::new(),
151 expected_delta: SetDelta::RemoveAll,
152 expected_serialized_patch_size: 1,
153 expected_did_change: true,
154 }
155 .test();
156 }
157
158 #[test]
160 fn one_field_added() {
161 DipaImplTester {
162 label: None,
163 start: &mut HashSet::new(),
164 end: &vec![1u32].into_iter().collect(),
165 expected_delta: SetDelta::AddOneField(&1),
166 expected_serialized_patch_size: 2,
167 expected_did_change: true,
168 }
169 .test();
170 }
171
172 #[test]
174 fn one_field_removed() {
175 DipaImplTester {
176 label: None,
177 start: &mut vec![1u32, 3].into_iter().collect::<HashSet<_>>(),
178 end: &vec![1].into_iter().collect(),
179 expected_delta: SetDelta::RemoveOneField(&3),
180 expected_serialized_patch_size: 2,
181 expected_did_change: true,
182 }
183 .test();
184 }
185
186 #[test]
188 fn many_fields_added() {
189 DipaImplTester {
190 label: None,
191 start: &mut BTreeSet::new(),
192 end: &vec![1u32, 3].into_iter().collect(),
193 expected_delta: SetDelta::ModifyMany {
194 added: vec![&1, &3],
195 removed: vec![],
196 },
197 expected_serialized_patch_size: 5,
198 expected_did_change: true,
199 }
200 .test();
201 }
202
203 #[test]
205 fn many_fields_removed() {
206 DipaImplTester {
207 label: None,
208 start: &mut vec![1u32, 3, 5].into_iter().collect::<BTreeSet<_>>(),
209 end: &vec![1].into_iter().collect(),
210 expected_delta: SetDelta::ModifyMany {
211 added: vec![],
212 removed: vec![&3, &5],
213 },
214 expected_serialized_patch_size: 5,
215 expected_did_change: true,
216 }
217 .test();
218 }
219}