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}