s2n_quic_core/interval_set/intersection.rs
1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::interval_set::{Interval, IntervalBound};
5use alloc::collections::vec_deque::{self, VecDeque};
6use core::cmp::Ordering;
7
8/// An iterator of `Intervals` over the intersection of two sets,
9/// i.e. the values in both `A` and `B` will be returned.
10#[derive(Debug)]
11pub struct Intersection<'a, T> {
12 set_a: vec_deque::Iter<'a, Interval<T>>,
13 set_b: vec_deque::Iter<'a, Interval<T>>,
14 interval_a: Option<Interval<T>>,
15 interval_b: Option<Interval<T>>,
16}
17
18impl<'a, T: Copy> Intersection<'a, T> {
19 pub(crate) fn new(set_a: &'a VecDeque<Interval<T>>, set_b: &'a VecDeque<Interval<T>>) -> Self {
20 let mut set_a = set_a.iter();
21 let interval_a = set_a.next().cloned();
22
23 let mut set_b = set_b.iter();
24 let interval_b = set_b.next().cloned();
25
26 Self {
27 set_a,
28 set_b,
29 interval_a,
30 interval_b,
31 }
32 }
33}
34
35impl<'a, T: 'a + IntervalBound + Ord> Iterator for Intersection<'a, T> {
36 type Item = Interval<T>;
37
38 fn next(&mut self) -> Option<Self::Item> {
39 use Ordering::*;
40
41 let interval_a = self.interval_a.as_mut()?;
42 let interval_b = self.interval_b.as_mut()?;
43
44 macro_rules! advance_set_a {
45 () => {
46 self.interval_a = self.set_a.next().cloned();
47 };
48 }
49
50 macro_rules! advance_set_b {
51 () => {
52 self.interval_b = self.set_b.next().cloned();
53 };
54 }
55
56 loop {
57 match (
58 interval_a.start.cmp(&interval_b.start),
59 interval_a.end.cmp(&interval_b.end),
60 ) {
61 // interval A is a subset of interval B
62 //
63 // interval A: |-----|
64 // interval B: |---------|
65 //
66 // Returns:
67 // |-----|
68 //
69 (Equal, Less) |
70
71 // interval A is a subset of interval B
72 //
73 // interval A: |----|
74 // interval B: |---------|
75 //
76 // Returns:
77 // |----|
78 //
79 (Greater, Less) => {
80 let item = *interval_a;
81 interval_b.start = interval_a.end_exclusive();
82 advance_set_a!();
83 return Some(item);
84 }
85
86 // interval A contains interval B, spilling over into the next slot
87 //
88 // interval A: |---------|
89 // interval B: |---|
90 //
91 // Returns:
92 // |---|
93 //
94 (Equal, Greater) |
95
96 // interval A contains interval B, spilling over into the next slot
97 //
98 // interval A: |---------|
99 // interval B: |---|
100 //
101 // Returns:
102 // |---|
103 //
104 (Less, Greater) => {
105 let item = *interval_b;
106 interval_a.start = interval_b.end_exclusive();
107 advance_set_b!();
108 return Some(item);
109 }
110
111 // interval A is a subset of interval B
112 //
113 // interval A: |-----|
114 // interval B: |---------|
115 //
116 // Returns:
117 // |-----|
118 //
119 (Greater, Equal) |
120
121 // the intervals are equal
122 //
123 // interval A: |---------|
124 // interval B: |---------|
125 //
126 // Returns:
127 // |---------|
128 //
129 (Equal, Equal) => {
130 let item = *interval_a;
131 advance_set_a!();
132 advance_set_b!();
133 return Some(item);
134 }
135
136 // interval A ends with interval B
137 //
138 // interval A: |---------|
139 // interval B: |---|
140 //
141 // Returns:
142 // |---|
143 //
144 (Less, Equal) => {
145 let item = *interval_b;
146 advance_set_a!();
147 advance_set_b!();
148 return Some(item);
149 }
150
151 // interval A is part of interval B.
152 //
153 // interval A: |--------|
154 // interval B: |--------|
155 //
156 // Returns:
157 // |---|
158 //
159 (Greater, Greater) if interval_a.start <= interval_b.end => {
160 let mut item = *interval_a;
161 item.end = interval_b.end;
162 interval_a.start = item.end_exclusive();
163 advance_set_b!();
164 return Some(item);
165 }
166
167 // interval A overlaps part of interval B
168 //
169 // interval A: |--------|
170 // interval B: |--------|
171 //
172 // Returns:
173 // |---|
174 //
175 (Less, Less) if interval_a.end >= interval_b.start => {
176 let mut item = *interval_b;
177 item.end = interval_a.end;
178 interval_b.start = item.end_exclusive();
179 advance_set_a!();
180 return Some(item);
181 }
182
183 // interval A comes later
184 //
185 // interval A: |-----|
186 // interval B: |----|
187 //
188 // continue to next B
189 //
190 (Greater, Greater) => {
191 *interval_b = self.set_b.next().cloned()?;
192 continue;
193 }
194
195 // interval A comes before interval B
196 //
197 // interval A: |---|
198 // interval B: |--------|
199 //
200 // continue to next A
201 //
202 (Less, Less) => {
203 *interval_a = self.set_a.next().cloned()?;
204 continue;
205 }
206 }
207 }
208 }
209}
210
211/// Apply the intersection of `set_a` with `set_b` to `set_a`
212#[inline]
213pub(super) fn apply<T: IntervalBound>(
214 set_a: &mut VecDeque<Interval<T>>,
215 set_b: &VecDeque<Interval<T>>,
216) {
217 use Ordering::*;
218
219 if set_a.is_empty() {
220 return;
221 }
222
223 if set_b.is_empty() {
224 set_a.clear();
225 return;
226 }
227
228 let mut set_b = set_b.iter();
229 let mut interval_b = set_b.next().expect("set_b is not empty");
230 let mut a_index = 0;
231
232 macro_rules! advance_set_a {
233 () => {
234 a_index += 1;
235 };
236 }
237
238 macro_rules! advance_set_b {
239 () => {
240 if let Some(next_interval_b) = set_b.next() {
241 interval_b = next_interval_b;
242 } else {
243 // the remainder of set_a is not in the intersection, since we've
244 // reached the end of set_b
245 set_a.truncate(a_index);
246 return;
247 }
248 };
249 }
250
251 // Inserts a new interval into the next index of set_a that starts where the current interval b
252 // ends (with a gap of 1) and ends where the current interval a ends
253 macro_rules! split_off_a {
254 ($interval_a:ident) => {
255 // step_up_saturating is used because the next intersecting interval should not be
256 // contiguous with the current interval, so we can expect a gap of at least 1.
257 let new_interval_a: Interval<T> =
258 (interval_b.end_exclusive().step_up_saturating()..=$interval_a.end).into();
259
260 if new_interval_a.is_valid() {
261 // if interval_a had only overlapped interval_b by 1, then the new interval
262 // will not be valid and we can skip inserting it
263 // for example: interval_a = [0..=48], interval_b = [0..=47]
264 // new_interval_a = [49..=48] since we know 48 is not in interval_b
265 set_a.insert(a_index + 1, new_interval_a);
266 }
267 };
268 }
269
270 while let Some(interval_a) = set_a.get(a_index) {
271 match (interval_a.start.cmp(&interval_b.start),
272 interval_a.end.cmp(&interval_b.end),
273 ) {
274 // interval A is a subset of interval B
275 //
276 // interval A: |-----|
277 // interval B: |---------|
278 //
279 // End state:
280 // |-----|
281 // a_index: ^
282 (Equal, Less) |
283
284 // interval A is a subset of interval B
285 //
286 // interval A: |----|
287 // interval B: |---------|
288 //
289 // End state:
290 // |----|
291 // a_index: ^
292 (Greater, Less) => {
293 advance_set_a!();
294 }
295
296 // interval A contains interval B, spilling over into the next slot
297 //
298 // interval A: |---------|
299 // interval B: |---|
300 //
301 // End state:
302 // |---| |---|
303 // a_index: ^
304 (Equal, Greater) |
305
306 // interval A contains interval B, spilling over into the next slot
307 //
308 // interval A: |---------|
309 // interval B: |---|
310 //
311 // End state:
312 // |---| |-|
313 // a_index: ^
314 (Less, Greater) => {
315 // split off the part of interval A that is spilling into the next slot
316 split_off_a!(interval_a);
317 set_a[a_index] = *interval_b;
318 advance_set_a!();
319 advance_set_b!();
320 }
321
322 // interval A is a subset of interval B
323 //
324 // interval A: |-----|
325 // interval B: |---------|
326 //
327 // End state:
328 // |-----|
329 // a_index: ^
330 (Greater, Equal) |
331
332 // the intervals are equal
333 //
334 // interval A: |---------|
335 // interval B: |---------|
336 //
337 // End state:
338 // |---------|
339 // a_index: ^
340 (Equal, Equal) => {
341 advance_set_a!();
342 advance_set_b!();
343 }
344
345 // interval A ends with interval B
346 //
347 // interval A: |---------|
348 // interval B: |---|
349 //
350 // End state:
351 // |---|
352 // a_index: ^
353 (Less, Equal) => {
354 set_a[a_index].start = interval_b.start;
355 advance_set_a!();
356 advance_set_b!();
357 }
358
359 // interval A overlaps part of interval B.
360 //
361 // interval A: |--------|
362 // interval B: |--------|
363 //
364 // End state:
365 // |---| |--|
366 // a_index: ^
367 (Greater, Greater) if interval_a.start <= interval_b.end => {
368 // split off the part of interval A that is spilling into the next slot
369 split_off_a!(interval_a);
370 set_a[a_index].end = interval_b.end;
371 advance_set_a!();
372 advance_set_b!();
373 }
374
375 // interval A overlaps part of interval B
376 //
377 // interval A: |--------|
378 // interval B: |--------|
379 //
380 // End state:
381 // |---|
382 // a_index: ^
383 (Less, Less) if interval_a.end >= interval_b.start => {
384 set_a[a_index].start = interval_b.start;
385 advance_set_a!();
386 }
387
388 // interval A comes later
389 //
390 // interval A: |-----|
391 // interval B: |----|
392 //
393 // continue to next B
394 //
395 (Greater, Greater) => {
396 advance_set_b!();
397 }
398
399 // interval A comes before interval B
400 //
401 // interval A: |---|
402 // interval B: |--------|
403 //
404 // remove A and continue to next A
405 //
406 (Less, Less) => {
407 set_a.remove(a_index);
408 }
409 }
410 }
411}