Skip to main content

range_set_blaze/
intersection_iter_map.rs

1use core::{
2    cmp::{max, min},
3    iter::FusedIterator,
4    ops::RangeInclusive,
5};
6
7use crate::Integer;
8use crate::{SortedDisjoint, SortedDisjointMap, map::ValueRef};
9
10/// This `struct` is created by the [`intersection`] and [`map_and_set_intersection`] methods on [`SortedDisjointMap`].
11/// See the methods' documentation for more.
12///
13/// [`SortedDisjointMap`]: crate::SortedDisjointMap
14/// [`intersection`]: crate::SortedDisjointMap::intersection
15/// [`map_and_set_intersection`]: crate::SortedDisjointMap::map_and_set_intersection
16#[must_use = "iterators are lazy and do nothing unless consumed"]
17#[derive(Clone, Debug)]
18pub struct IntersectionIterMap<T, VR, IM, IS> {
19    iter_left: IM,
20    iter_right: IS,
21    right: Option<RangeInclusive<T>>,
22    left: Option<(RangeInclusive<T>, VR)>,
23}
24
25impl<T, VR, IM, IS> IntersectionIterMap<T, VR, IM, IS>
26where
27    T: Integer,
28    VR: ValueRef,
29    IM: SortedDisjointMap<T, VR>,
30    IS: SortedDisjoint<T>,
31{
32    pub(crate) const fn new(iter_map: IM, iter_set: IS) -> Self {
33        Self {
34            iter_left: iter_map,
35            iter_right: iter_set,
36            right: None,
37            left: None,
38        }
39    }
40}
41
42impl<T, VR, IM, IS> FusedIterator for IntersectionIterMap<T, VR, IM, IS>
43where
44    T: Integer,
45    VR: ValueRef,
46    IM: SortedDisjointMap<T, VR> + FusedIterator,
47    IS: SortedDisjoint<T> + FusedIterator,
48{
49}
50
51// Note: ExactSizeIterator cannot be safely implemented for IntersectionIterMap
52// because we can't determine the exact number of items that will be produced
53// by the intersection without fully processing both iterators.
54// An upper bound would be min(left.len(), right.len()), but that's not exact.
55
56impl<T, VR, IM, IS> Iterator for IntersectionIterMap<T, VR, IM, IS>
57where
58    T: Integer,
59    VR: ValueRef,
60    IM: SortedDisjointMap<T, VR>,
61    IS: SortedDisjoint<T>,
62{
63    type Item = (RangeInclusive<T>, VR);
64
65    fn next(&mut self) -> Option<(RangeInclusive<T>, VR)> {
66        // println!("begin next");
67        loop {
68            // Be sure both currents are loaded.
69            self.left = self.left.take().or_else(|| self.iter_left.next());
70            self.right = self.right.take().or_else(|| self.iter_right.next());
71
72            // If either is still none, we are done.
73            let (Some(left), Some(right)) = (self.left.take(), self.right.take()) else {
74                return None;
75            };
76            let (left_range, left_value) = left;
77            let (left_start, left_end) = left_range.clone().into_inner();
78            let (right_start, right_end) = right.into_inner();
79            // println!("{:?} {:?}", current_range, current_range_value.0);
80
81            // if current_range ends before current_range_value, clear it and loop for a new value.
82            if right_end < left_start {
83                // println!("getting new range");
84                self.right = None;
85                self.left = Some((left_range, left_value));
86                continue;
87            }
88
89            // if current_range_value ends before current_range, clear it and loop for a new value.
90            if left_end < right_start {
91                // println!("getting new range value");
92                self.right = Some(RangeInclusive::new(right_start, right_end));
93                self.left = None;
94                continue;
95            }
96
97            // Thus, they overlap
98            let start = max(right_start, left_start);
99            let end = min(right_end, left_end);
100
101            // Modified logic: Now prioritize right range boundaries instead of left
102            let value = if left_end != end {
103                // right_end != end, left_end != end is impossible
104                debug_assert!(right_end == end);
105
106                // right_end == end, left_end != end
107                let value = left_value.clone();
108                self.right = None;
109                self.left = Some((left_range, left_value));
110                value
111            } else if right_end == end {
112                // right_end == end, left_end == end
113                self.left = None;
114                self.right = None;
115                left_value
116            } else {
117                // right_end != end, left_end == end
118                self.right = Some(RangeInclusive::new(right_start, right_end));
119                self.left = None;
120                left_value
121            };
122
123            let range_value = (start..=end, value);
124            return Some(range_value);
125        }
126    }
127
128    // TODO: Implement size_hint -- this is similar code from the set version.
129    // // There could be a few as 1 (or 0 if the iter is empty) or as many as the iter.
130    // // Plus, possibly one more if we have a range is in progress.
131    // fn size_hint(&self) -> (usize, Option<usize>) {
132    //     let (low, high) = self.iter.size_hint();
133    //     let low = low.min(1);
134    //     if self.option_range_value.is_some() {
135    //         (low, high.map(|x| x + 1))
136    //     } else {
137    //         (low, high)
138    //     }
139    // }
140}