1use crate::ClosedRange;
3use crate::Endpoint;
4use crate::IntoNormalizedRangeIter;
5use crate::NormalizedRangeIter;
6use crate::RangeVec;
7
8use core::iter::Peekable;
9
10pub struct LinearIntersectionIterator<T, X, Y>
11where
12 T: Endpoint,
13 X: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
14 Y: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
15{
16 left: Peekable<X>,
17 right: Peekable<Y>,
18}
19
20impl<T, X, Y> LinearIntersectionIterator<T, X, Y>
21where
22 T: Endpoint,
23 X: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
24 Y: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
25{
26 pub fn new(left: X, right: Y) -> Self {
27 Self {
28 left: left.peekable(),
29 right: right.peekable(),
30 }
31 }
32}
33
34impl<T, X, Y> Iterator for LinearIntersectionIterator<T, X, Y>
35where
36 T: Endpoint,
37 X: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
38 Y: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
39{
40 type Item = (T, T);
41
42 fn next(&mut self) -> Option<(T, T)> {
43 use core::cmp::Ordering; loop {
46 let (Some(left), Some(right)) = (
47 self.left.peek().map(|x| x.get()),
48 self.right.peek().map(|x| x.get()),
49 ) else {
50 return None;
51 };
52
53 match left.1.cmp_end(right.1) {
55 Ordering::Less => {
56 self.left.next();
57 }
58 Ordering::Equal => {
59 self.left.next();
60 self.right.next();
61 }
62 Ordering::Greater => {
63 self.right.next();
64 }
65 }
66
67 let start = left.0.top_end(right.0);
69 let stop = left.1.bot_end(right.1);
70
71 if start.cmp_end(stop) <= Ordering::Equal {
72 return Some((start, stop));
73 }
74 }
75 }
76
77 #[inline]
78 fn size_hint(&self) -> (usize, Option<usize>) {
79 let (_, left_max) = self.left.size_hint();
82 let (_, right_max) = self.right.size_hint();
83
84 if (left_max == Some(0)) | (right_max == Some(0)) {
85 (0, Some(0))
87 } else {
88 (
89 0,
90 left_max
91 .unwrap_or(usize::MAX)
92 .checked_add(right_max.unwrap_or(usize::MAX)),
93 )
94 }
95 }
96}
97
98impl<T, X, Y> crate::private::Sealed for LinearIntersectionIterator<T, X, Y>
99where
100 T: Endpoint,
101 X: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
102 Y: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
103{
104}
105
106impl<T, X, Y> NormalizedRangeIter for LinearIntersectionIterator<T, X, Y>
107where
108 T: Endpoint,
109 X: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
110 Y: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
111{
112}
113
114impl<T, X, Y> core::iter::FusedIterator for LinearIntersectionIterator<T, X, Y>
116where
117 T: Endpoint,
118 X: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
119 Y: Sized + NormalizedRangeIter + Iterator<Item: ClosedRange<EndT = T>>,
120{
121}
122
123impl<T: Endpoint> RangeVec<T> {
124 #[inline(always)]
132 #[must_use]
133 pub fn intersect(
134 &self,
135 other: impl IntoNormalizedRangeIter<Item: ClosedRange<EndT = T>>,
136 ) -> Self {
137 #[inline(never)]
138 fn doit<T: Endpoint>(
139 this: &RangeVec<T>,
140 other: impl NormalizedRangeIter<Item: ClosedRange<EndT = T>>,
141 ) -> RangeVec<T> {
142 let iter = this.iter().intersect(other);
143 let size_hint = iter.size_hint();
144 if this.is_empty() {
145 debug_assert_eq!(size_hint, (0, Some(0)));
146 }
147
148 let ret = iter.collect_range_vec();
149
150 debug_assert!(ret.len() >= size_hint.0);
151 debug_assert!(ret.len() <= size_hint.1.unwrap_or(usize::MAX));
152
153 ret
154 }
155
156 doit(self, other.into_iter())
157 }
158}
159
160#[cfg(test)]
161#[cfg_attr(coverage_nightly, coverage(off))]
162mod test {
163 use super::*;
164 use alloc::vec;
165 use alloc::vec::Vec;
166
167 #[test]
168 fn smoke_test() {
169 let empty: RangeVec<u8> = RangeVec::default();
171 let other = RangeVec::from_vec(vec![(u8::MIN, u8::MAX)]);
172
173 {
174 let empty_empty = empty.iter().intersect(empty.iter());
175
176 assert_eq!(empty_empty.size_hint(), (0, Some(0)));
177 assert_eq!(&empty_empty.collect_range_vec(), &empty);
178 }
179
180 {
181 let empty_other = empty.iter().intersect(other.iter());
182
183 assert_eq!(empty_other.size_hint(), (0, Some(0)));
184 assert_eq!(&empty_other.collect_range_vec(), &empty);
185 }
186
187 {
188 let other_empty = other.iter().intersect(empty.iter());
189
190 assert_eq!(other_empty.size_hint(), (0, Some(0)));
191 assert_eq!(&other_empty.collect_range_vec(), &empty);
192 }
193
194 {
196 let mut other_empty = other.iter().intersect(other.iter());
197
198 assert!(other_empty.size_hint() != (0, Some(0)));
200
201 assert!(other_empty.next().is_some());
202 assert_eq!(other_empty.next(), None);
204 assert_eq!(other_empty.next(), None);
206 }
207 }
208
209 #[cfg(test)]
210 proptest::proptest! {
211 #[test]
212 fn test_intersection_iterator(xs: Vec<(u8, u8)>, ys: Vec<(u8, u8)>)
213 {
214 use crate::ranges_to_bits;
215
216 let bits = {
217 let x_bits = ranges_to_bits(&xs);
218 let y_bits = ranges_to_bits(&ys);
219
220 x_bits.into_iter().zip(y_bits.into_iter()).map(|(x, y)| x & y).collect::<Vec<bool>>()
221 };
222
223 {
224 let out = RangeVec::from_vec(xs.clone()).iter().intersect(
225 RangeVec::from_vec(ys.clone()).iter()).collect_range_vec();
226 assert_eq!(&bits, &ranges_to_bits(&out));
227 }
228
229 {
230 let out = RangeVec::from_vec(ys.clone()).iter().intersect(&RangeVec::from_vec(xs.clone())).collect_range_vec();
231 assert_eq!(&bits, &ranges_to_bits(&out));
232 }
233 }
234
235 #[test]
236 fn test_intersection_identity(xs: Vec<(u8, u8)>, ys: Vec<(u8, u8)>)
237 {
238 let xs = RangeVec::from_vec(xs.into_iter().map(|(a, b)| (a.min(b), a.max(b))).collect::<Vec<_>>());
240 let ys = RangeVec::from_vec(ys.into_iter().map(|(a, b)| (a.min(b), a.max(b))).collect::<Vec<_>>());
241
242 {
248 let not_and = xs.iter().intersect(&ys).complement().collect_range_vec();
249 let or_not = crate::union_vec(xs.iter().complement().collect_range_vec(),
250 ys.iter().complement());
251
252 assert_eq!(not_and, or_not);
253 }
254
255 {
256 let and = xs.iter().intersect(&ys).collect_range_vec();
257 let not_or_not = crate::union_vec(xs.iter().complement().collect_range_vec(),
258 ys.iter().complement()).iter().complement().collect_range_vec();
259
260 assert_eq!(and, not_or_not);
261 }
262 }
263 }
264}