1use crate::{Apply, Core, Delta, DeltaResult, FromDelta, IntoDelta};
7use serde::{Deserialize, Serialize};
8use std::collections::HashSet;
9use std::fmt::Debug;
10use std::hash::Hash;
11
12
13impl<T> Core for HashSet<T>
14where T: Clone + Debug + PartialEq + Ord + Core
15 + for<'de> Deserialize<'de>
16 + Serialize,
17{
18 type Delta = HashSetDelta<T>;
19}
20
21impl<T> Apply for HashSet<T>
22where T: Clone + Debug + PartialEq + Ord + Hash + Apply + FromDelta
23 + for<'de> Deserialize<'de>
24 + Serialize,
25{
26 fn apply(&self, delta: Self::Delta) -> DeltaResult<Self> {
27 match delta.0 {
28 None => Ok(self.clone()),
29 Some(entry_deltas) => {
30 let mut new: Self = self.clone();
31 for entry_delta in entry_deltas { match entry_delta {
32 EntryDelta::Add { item } => {
33 new.insert(<T>::from_delta(item)?);
34 },
35 EntryDelta::Remove { item } => {
36 new.remove(&(<T>::from_delta(item)?));
37 },
38 }}
39 Ok(new)
40 },
41 }
42 }
43}
44
45impl<T> Delta for HashSet<T>
46where T: Clone + Debug + PartialEq + Ord + Hash + Delta + IntoDelta
47 + for<'de> Deserialize<'de>
48 + Serialize,
49{
50 fn delta(&self, rhs: &Self) -> DeltaResult<Self::Delta> {
51 Ok(HashSetDelta(if self == rhs {
52 None
53 } else {
54 let mut entry_deltas: Vec<EntryDelta<T>> = vec![];
55 for addition in rhs.difference(&self) {
56 let addition = addition.clone().into_delta()?;
57 entry_deltas.push(EntryDelta::Add { item: addition });
58 }
59 for removal in self.difference(&rhs) {
60 let removal = removal.clone().into_delta()?;
61 entry_deltas.push(EntryDelta::Remove { item: removal });
62 }
63 Some(entry_deltas)
64 }))
65 }
66}
67
68impl<T> FromDelta for HashSet<T>
69where T: Clone + Debug + PartialEq + Ord + Hash + FromDelta
70 + for<'de> Deserialize<'de>
71 + Serialize,
72{
73 fn from_delta(delta: Self::Delta) -> DeltaResult<Self> {
74 let mut map = Self::new();
75 if let Some(delta_entries) = delta.0 {
76 for entry in delta_entries { match entry {
77 EntryDelta::Add { item } => {
78 map.insert(<T>::from_delta(item)?);
79 },
80 EntryDelta::Remove { item } => {
81 let item = <T>::from_delta(item)?;
82 map.remove(&item);
83 },
84 }}
85 }
86 Ok(map)
87 }
88}
89
90impl<T> IntoDelta for HashSet<T>
91where T: Clone + Debug + PartialEq + Ord + IntoDelta
92 + for<'de> Deserialize<'de>
93 + Serialize,
94{
95 fn into_delta(self) -> DeltaResult<Self::Delta> {
96 Ok(HashSetDelta(if self.is_empty() {
97 None
98 } else {
99 let mut changes: Vec<EntryDelta<T>> = vec![];
100 for item in self {
101 changes.push(EntryDelta::Add { item: item.into_delta()? });
102 }
103 Some(changes)
104 }))
105 }
106}
107
108
109
110
111#[derive(Clone, PartialEq)]
112#[derive(serde_derive::Deserialize, serde_derive::Serialize)]
113pub struct HashSetDelta<T: Core>(
114 #[doc(hidden)] pub Option<Vec<EntryDelta<T>>>,
115);
116
117impl<T> HashSetDelta<T>
118where T: Clone + Debug + PartialEq + Ord + Core
119 + for<'de> Deserialize<'de>
120 + Serialize,
121{
122 pub fn iter<'d>(&'d self) -> Box<dyn Iterator<Item = &EntryDelta<T>> + 'd> {
123 match &self.0 {
124 Some(deltas) => Box::new(deltas.iter()),
125 None => Box::new(std::iter::empty()),
126 }
127 }
128
129 pub fn into_iter<'d>(self) -> Box<dyn Iterator<Item = EntryDelta<T>> + 'd>
130 where Self: 'd {
131 match self.0 {
132 Some(delta) => Box::new(delta.into_iter()),
133 None => Box::new(std::iter::empty()),
134 }
135 }
136
137 pub fn len(&self) -> usize {
138 match &self.0 {
139 Some(deltas) => deltas.len(),
140 None => 0,
141 }
142 }
143}
144
145impl<T> std::fmt::Debug for HashSetDelta<T>
146where T: std::fmt::Debug + Core {
147 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
148 write!(f, "HashSetDelta ")?;
149 let mut buf = f.debug_list();
150 if let Some(d) = &self.0 {
151 buf.entries(d.iter());
152 } else {
153 buf.entries(std::iter::empty::<Vec<EntryDelta<T>>>());
154 }
155 buf.finish()
156 }
157}
158
159
160
161#[derive(Clone, PartialEq)]
162#[derive(serde_derive::Deserialize, serde_derive::Serialize)]
163pub enum EntryDelta<T: Core> {
164 Add { item: <T as Core>::Delta },
165 Remove { item: <T as Core>::Delta },
166}
167
168impl<T> std::fmt::Debug for EntryDelta<T>
169where T: std::fmt::Debug + Core {
170 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
171 match &self {
172 Self::Add { item } => f.debug_struct("Add")
173 .field("item", item)
174 .finish(),
175 Self::Remove { item } => f.debug_struct("Remove")
176 .field("item", item)
177 .finish(),
178 }
179 }
180}
181
182
183
184
185#[allow(non_snake_case)]
186#[cfg(test)]
187mod tests {
188 use super::*;
189 use std::collections::HashSet;
190
191 macro_rules! set {
192 ($($val:expr),* $(,)?) => {{ #[allow(redundant_semicolons)] {
193 let mut set = HashSet::new();
194 $( set.insert($val); )* ;
195 set
196 }}}
197 }
198
199 #[test]
200 fn HashSet__delta__same_values() -> DeltaResult<()> {
201 let set0: HashSet<String> = set! {
202 "bar".into(),
203 "foo".into(),
204 "floozie".into(),
205 "quux".into(),
206 };
207 let set1: HashSet<String> = set! {
208 "bar".into(),
209 "foo".into(),
210 "floozie".into(),
211 "quux".into(),
212 };
213 let delta = set0.delta(&set1)?;
214 let expected = HashSetDelta(None);
215 assert_eq!(delta, expected);
216 let set2 = set0.apply(delta)?;
217 assert_eq!(set0, set2);
218 assert_eq!(set1, set2);
219
220 let delta = set1.delta(&set0)?;
221 assert_eq!(delta, HashSetDelta(None));
222 let set3 = set1.apply(delta)?;
223 assert_eq!(set0, set3);
224 assert_eq!(set1, set3);
225
226 Ok(())
227 }
228
229 #[test]
230 fn HashSet__delta__different_values() -> DeltaResult<()> {
231 let set0: HashSet<String> = set! {
232 "bar".into(),
233 "foo".into(),
234 "floozie".into(),
235 "quux".into(),
236 };
237 let set1: HashSet<String> = set! {
238 "bar".into(),
239 "baz".into(),
240 "foo".into(),
241 "quux".into(),
242 };
243 let delta0 = set0.delta(&set1)?;
244 let expected = HashSetDelta(Some(vec![
245 EntryDelta::Add { item: "baz".to_string().into_delta()? },
246 EntryDelta::Remove { item: "floozie".to_string().into_delta()? },
247 ]));
248 assert_eq!(delta0, expected);
249 let set2 = set0.apply(delta0)?;
250 assert_eq!(set1, set2);
251
252 let delta1 = set1.delta(&set0)?;
253 assert_eq!(delta1, HashSetDelta(Some(vec![
254 EntryDelta::Add { item: "floozie".to_string().into_delta()? },
255 EntryDelta::Remove { item: "baz".to_string().into_delta()? },
256 ])));
257 let set3 = set1.apply(delta1)?;
258 assert_eq!(set0, set3);
259
260 Ok(())
261 }
262
263 #[test]
264 fn HashSet__apply__same_values() -> DeltaResult<()> {
265 let set0: HashSet<String> = set! {
266 "bar".into(),
267 "foo".into(),
268 "floozie".into(),
269 "quux".into(),
270 };
271 let set1: HashSet<String> = set! {
272 "bar".into(),
273 "foo".into(),
274 "floozie".into(),
275 "quux".into(),
276 };
277 let delta = set0.delta(&set1)?;
278 assert_eq!(delta, HashSetDelta(None));
279 let set2 = set0.apply(delta)?;
280 assert_eq!(set1, set2);
281 Ok(())
282 }
283
284 #[test]
285 fn HashSet__apply__different_values() -> DeltaResult<()> {
286 let set0: HashSet<String> = set! {
287 "bar".into(),
288 "foo".into(),
289 "floozie".into(),
290 "quux".into(),
291 };
292 let set1: HashSet<String> = set! {
293 "bar".into(),
294 "baz".into(),
295 "foo".into(),
296 "quux".into(),
297 };
298 let delta = set0.delta(&set1)?;
299 assert_eq!(delta, HashSetDelta(Some(vec![
300 EntryDelta::Add { item: "baz".to_string().into_delta()? },
301 EntryDelta::Remove { item: "floozie".to_string().into_delta()? },
302 ])));
303 let set2 = set0.apply(delta)?;
304 assert_eq!(set1, set2);
305 Ok(())
306 }
307}