1use alloc::collections::BTreeSet;
2
3use crate::Crdt;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32pub struct TwoPSet<T: Ord + Clone> {
33 added: BTreeSet<T>,
34 removed: BTreeSet<T>,
35}
36
37impl<T: Ord + Clone> TwoPSet<T> {
38 #[must_use]
40 pub fn new() -> Self {
41 Self {
42 added: BTreeSet::new(),
43 removed: BTreeSet::new(),
44 }
45 }
46
47 pub fn insert(&mut self, value: T) -> bool {
53 if self.removed.contains(&value) {
54 return false;
55 }
56 self.added.insert(value)
57 }
58
59 pub fn remove(&mut self, value: &T) -> bool {
64 if self.added.contains(value) && !self.removed.contains(value) {
65 self.removed.insert(value.clone());
66 true
67 } else {
68 false
69 }
70 }
71
72 #[must_use]
74 pub fn contains(&self, value: &T) -> bool {
75 self.added.contains(value) && !self.removed.contains(value)
76 }
77
78 #[must_use]
80 pub fn len(&self) -> usize {
81 self.added.difference(&self.removed).count()
82 }
83
84 #[must_use]
86 pub fn is_empty(&self) -> bool {
87 self.len() == 0
88 }
89
90 pub fn iter(&self) -> impl Iterator<Item = &T> {
92 self.added.difference(&self.removed)
93 }
94}
95
96impl<T: Ord + Clone> Default for TwoPSet<T> {
97 fn default() -> Self {
98 Self::new()
99 }
100}
101
102impl<T: Ord + Clone> Crdt for TwoPSet<T> {
103 fn merge(&mut self, other: &Self) {
104 for elem in &other.added {
105 self.added.insert(elem.clone());
106 }
107 for elem in &other.removed {
108 self.removed.insert(elem.clone());
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn new_set_is_empty() {
119 let s = TwoPSet::<String>::new();
120 assert!(s.is_empty());
121 }
122
123 #[test]
124 fn insert_and_contains() {
125 let mut s = TwoPSet::new();
126 s.insert("a");
127 assert!(s.contains(&"a"));
128 assert_eq!(s.len(), 1);
129 }
130
131 #[test]
132 fn remove_element() {
133 let mut s = TwoPSet::new();
134 s.insert("a");
135 assert!(s.remove(&"a"));
136 assert!(!s.contains(&"a"));
137 assert_eq!(s.len(), 0);
138 }
139
140 #[test]
141 fn cannot_readd_removed_element() {
142 let mut s = TwoPSet::new();
143 s.insert("a");
144 s.remove(&"a");
145 assert!(!s.insert("a")); assert!(!s.contains(&"a"));
147 }
148
149 #[test]
150 fn remove_wins_on_merge() {
151 let mut s1 = TwoPSet::new();
152 s1.insert("a");
153 s1.remove(&"a");
154
155 let mut s2 = TwoPSet::new();
156 s2.insert("a"); s1.merge(&s2);
159 assert!(!s1.contains(&"a")); }
161
162 #[test]
163 fn merge_is_commutative() {
164 let mut s1 = TwoPSet::new();
165 s1.insert("a");
166 s1.insert("b");
167 s1.remove(&"a");
168
169 let mut s2 = TwoPSet::new();
170 s2.insert("b");
171 s2.insert("c");
172
173 let mut left = s1.clone();
174 left.merge(&s2);
175
176 let mut right = s2.clone();
177 right.merge(&s1);
178
179 assert_eq!(left, right);
180 }
181
182 #[test]
183 fn merge_is_idempotent() {
184 let mut s1 = TwoPSet::new();
185 s1.insert("a");
186
187 let mut s2 = TwoPSet::new();
188 s2.insert("b");
189
190 s1.merge(&s2);
191 let after_first = s1.clone();
192 s1.merge(&s2);
193
194 assert_eq!(s1, after_first);
195 }
196
197 #[test]
198 fn iterate_active_elements() {
199 let mut s = TwoPSet::new();
200 s.insert(1);
201 s.insert(2);
202 s.insert(3);
203 s.remove(&2);
204
205 let active: Vec<&i32> = s.iter().collect();
206 assert_eq!(active, vec![&1, &3]);
207 }
208}