segmap/set/ops/symmetric_difference.rs
1use core::{cmp::Ordering::*, fmt::Debug, iter::FusedIterator};
2
3use crate::{map::Key, set::iterators::Iter, Segment, SegmentMap, SegmentSet};
4
5impl<T> SegmentSet<T> {
6 // TODO: into_difference_iter
7
8 pub fn symmetric_difference_iter<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T> {
9 SymmetricDifference {
10 iter_a: self.iter(),
11 prev_a: None,
12 iter_b: other.iter(),
13 prev_b: None,
14 }
15 }
16
17 // TODO: into_symmetric_difference
18
19 pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SegmentSet<&'a T>
20 where
21 T: Ord,
22 {
23 // Don't need to insert, since we know ranges produced by the iterator
24 // aren't overlapping
25 SegmentSet {
26 map: SegmentMap {
27 map: self
28 .symmetric_difference_iter(other)
29 .map(|r| (Key(r), ()))
30 .collect(),
31 store: alloc::vec::Vec::new(),
32 },
33 }
34 }
35}
36
37/// Set Symmetric Difference
38impl<'a, T: Ord + Clone> core::ops::BitXor<&'a SegmentSet<T>> for &'a SegmentSet<T> {
39 type Output = SegmentSet<&'a T>;
40
41 // TODO: docs
42
43 /// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
44 ///
45 /// # Examples
46 ///
47 /// ```
48 /// use std::collections::BTreeSet;
49 ///
50 /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
51 /// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect();
52 ///
53 /// let result = &a ^ &b;
54 /// let result_vec: Vec<_> = result.into_iter().collect();
55 /// assert_eq!(result_vec, [1, 4]);
56 /// ```
57 fn bitxor(self, rhs: &'a SegmentSet<T>) -> SegmentSet<&'a T> {
58 self.symmetric_difference(rhs)
59 }
60}
61
62// TODO: BitXorAssign for symmetric difference? Maybe omit, unless a good use case comes up
63// /// Set in-place symmetric difference // TODO: self.into_symmetric_difference() may be quicker for these?
64// impl<T: Ord + Clone> core::ops::BitXorAssign<&SegmentSet<T>> for SegmentSet<T> {
65// fn bitxor_assign(&mut self, rhs: &SegmentSet<T>) {
66
67// }
68// }
69// impl<T: Ord + Clone> core::ops::BitXorAssign<SegmentSet<T>> for SegmentSet<T> {
70// fn sub_assign(&mut self, rhs: SegmentSet<T>) {
71// for range in rhs.iter() {
72// self.remove(range);
73// }
74// }
75// }
76
77#[derive(Debug, Clone)]
78pub struct SymmetricDifference<'a, T> {
79 iter_a: Iter<'a, T>,
80 prev_a: Option<Segment<&'a T>>,
81 iter_b: Iter<'a, T>,
82 prev_b: Option<Segment<&'a T>>,
83}
84
85// impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
86// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87// f.debug_tuple("SymmetricDifference").field(&self.).finish()
88// }
89// }
90
91// impl<T> Clone for SymmetricDifference<'_, T> {
92// fn clone(&self) -> Self {
93// Self {
94
95// }
96// }
97// }
98
99impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
100 type Item = Segment<&'a T>;
101
102 fn next(&mut self) -> Option<Segment<&'a T>> {
103 let next_a = self
104 .prev_a
105 .take()
106 .or_else(|| self.iter_a.next().map(|x| x.as_ref()));
107
108 let next_b = self
109 .prev_b
110 .take()
111 .or_else(|| self.iter_b.next().map(|x| x.as_ref()));
112
113 // If one ran out, use the other
114 let mut next_a = match next_a {
115 Some(a) => a,
116 None => return next_b,
117 };
118 let mut next_b = match next_b {
119 Some(b) => b,
120 None => return Some(next_a),
121 };
122
123 // Otherwise, look for mutually exclusive items
124 loop {
125 // If `next_a` is fully before `next_b`, use it
126 // (and hold on to `next_b`)
127 if next_a.end.cmp_start(&next_b.start).is_gt() {
128 self.prev_b.insert(next_b);
129 return Some(next_b);
130 }
131
132 // Likewise the other way around
133 if next_a.start.cmp_end(&next_b.end).is_gt() {
134 self.prev_a.insert(next_a);
135 return Some(next_a);
136 }
137
138 // Otherwise, we have some overlap
139 match (next_a.start.cmp(&next_b.start), next_a.end.cmp(&next_b.end)) {
140 // Partial overlap, but `a` doesn't extend beyond `b`.
141 // Use the non-overlapped part of `a` and remember to remove
142 // the overlap from `b` for the next iteration.
143 (Less, Less) => {
144 // When removing the overlapped region, use `replace` to
145 // make sure we do it in order.
146 next_b.start =
147 core::mem::replace(&mut next_a.end, next_b.borrow_bound_before().unwrap())
148 .borrow_after()
149 .unwrap();
150 self.prev_b.insert(next_b);
151 return Some(next_a);
152 }
153
154 // Partial overlap where `a` extends just to the
155 // end of `b` (don't save `b`)
156 (Less, Equal) => {
157 next_a.end = next_b.borrow_bound_before().unwrap();
158 return Some(next_a);
159 }
160
161 // `a` extends beyond `b` in both directions.
162 // Use the part of `a` before `b` and store
163 // the part after.
164 (Less, Greater) => {
165 self.prev_a.insert(Segment {
166 start: next_b.borrow_bound_after().unwrap(),
167 end: next_a.end,
168 });
169 next_a.end = next_b.borrow_bound_before().unwrap();
170 return Some(next_a);
171 }
172
173 // `b` extends past `a`. Remove the overlap and loop
174 // (if necessary)
175 (Equal, Less) => {
176 next_b.start = next_a.borrow_bound_after().unwrap();
177 if let Some(a) = self.iter_a.next() {
178 next_a = a.as_ref();
179 continue;
180 } else {
181 // No more `a`s, just return this `b` part
182 return Some(next_b);
183 }
184 }
185
186 // Both exactly overlap each other. loop!
187 // (or return early because we're out of items in one)
188 (Equal, Equal) => {
189 if let Some(a) = self.iter_a.next().map(|x| x.as_ref()) {
190 next_a = a;
191 } else {
192 // But no more `a`s
193 return Some(next_b);
194 }
195 if let Some(b) = self.iter_b.next().map(|x| x.as_ref()) {
196 next_b = b;
197 } else {
198 // But no more `b`s
199 return Some(next_a);
200 }
201 continue;
202 }
203
204 // Partial overlap, but some `b` past `a`
205 // Keep part of `a` and look for a new `b`
206 (Equal, Greater) => {
207 next_a.start = next_b.borrow_bound_after().unwrap();
208 if let Some(b) = self.iter_b.next().map(|x| x.as_ref()) {
209 next_b = b;
210 } else {
211 return Some(next_b);
212 }
213 continue;
214 }
215
216 // `b` extends beyond `a` in both directions.
217 // Use the part of `b` before `a` and store
218 // the part after.
219 (Greater, Less) => {
220 self.prev_b.insert(Segment {
221 start: next_a.borrow_bound_after().unwrap(),
222 end: next_b.end,
223 });
224 next_b.end = next_a.borrow_bound_before().unwrap();
225 return Some(next_b);
226 }
227
228 // Partial overlap, where `b` extends before `a`, but they
229 // end together.
230 (Greater, Equal) => {
231 next_b.end = next_a.borrow_bound_before().unwrap();
232 return Some(next_b);
233 }
234
235 // Partial overlap, but `b` doesn't extend beyond `a`.
236 // Use the non-overlapped part of `b` and remember to remove
237 // the overlap from `a` for the next iteration.
238 (Greater, Greater) => {
239 // When removing the overlapped region, use `replace` to
240 // make sure we do it in order. (Similar to (Less, Less))
241 next_a.start =
242 core::mem::replace(&mut next_b.end, next_a.borrow_bound_before().unwrap())
243 .borrow_after()
244 .unwrap();
245 self.prev_a.insert(next_a);
246 return Some(next_b);
247 }
248 }
249 }
250 }
251
252 fn size_hint(&self) -> (usize, Option<usize>) {
253 (0, Some(self.iter_a.len() + self.iter_b.len()))
254 }
255
256 fn min(mut self) -> Option<Segment<&'a T>> {
257 self.next()
258 }
259}
260
261impl<T: Ord> FusedIterator for SymmetricDifference<'_, T> {}