Skip to main content

range_set_blaze/
unsorted_priority_map.rs

1use crate::map::ValueRef;
2use crate::range_values::ExpectDebugUnwrapRelease;
3use crate::sorted_disjoint_map::{Priority, PrioritySortedStartsMap};
4use crate::{Integer, map::EndValue, sorted_disjoint_map::SortedDisjointMap};
5use core::ops::RangeInclusive;
6use core::{
7    cmp::{max, min},
8    iter::FusedIterator,
9    marker::PhantomData,
10};
11use num_traits::Zero;
12
13#[must_use = "iterators are lazy and do nothing unless consumed"]
14#[allow(clippy::redundant_pub_crate)]
15pub(crate) struct UnsortedPriorityMap<T, VR, I> {
16    iter: I,
17    option_priority: Option<Priority<T, VR>>,
18    min_value_plus_2: T,
19    priority_number: usize,
20}
21
22impl<T, VR, I> UnsortedPriorityMap<T, VR, I>
23where
24    T: Integer,
25    VR: ValueRef,
26    I: Iterator<Item = (RangeInclusive<T>, VR)>, // Any iterator is fine
27{
28    #[inline]
29    pub(crate) fn new(into_iter: I) -> Self {
30        Self {
31            iter: into_iter,
32            option_priority: None,
33            min_value_plus_2: T::min_value().add_one().add_one(),
34            priority_number: 0,
35        }
36    }
37}
38
39impl<T, VR, I> FusedIterator for UnsortedPriorityMap<T, VR, I>
40where
41    T: Integer,
42    VR: ValueRef,
43    I: Iterator<Item = (RangeInclusive<T>, VR)>,
44{
45}
46
47impl<T, VR, I> Iterator for UnsortedPriorityMap<T, VR, I>
48where
49    T: Integer,
50    VR: ValueRef,
51    I: Iterator<Item = (RangeInclusive<T>, VR)>,
52{
53    type Item = Priority<T, VR>;
54
55    fn next(&mut self) -> Option<Self::Item> {
56        loop {
57            // Get the next range_value, if none, return the current range_value
58            let Some(next_range_value) = self.iter.next() else {
59                return self.option_priority.take();
60            };
61            let next_priority = Priority::new(next_range_value, self.priority_number);
62            self.priority_number = self
63                .priority_number
64                .checked_add(1)
65                .expect_debug_unwrap_release("underflow");
66
67            // check the next range is valid and non-empty
68            let (next_start, next_end) = next_priority.start_and_end();
69            if next_start > next_end {
70                continue;
71            }
72
73            // get the current range (if none, set the current range to the next range and loop)
74            let Some(mut current_priority) = self.option_priority.take() else {
75                self.option_priority = Some(next_priority);
76                continue;
77            };
78
79            // If the values are different or the ranges do not touch or overlap,
80            // return the current range and set the current range to the next range
81            let (current_start, current_end) = current_priority.start_and_end();
82            if current_priority.value().borrow() != next_priority.value().borrow()
83                || (next_start >= self.min_value_plus_2
84                    && current_end <= next_start.sub_one().sub_one())
85                || (current_start >= self.min_value_plus_2
86                    && next_end <= current_start.sub_one().sub_one())
87            {
88                self.option_priority = Some(next_priority);
89                return Some(current_priority);
90            }
91
92            // They touch or overlap and have the same value, so merge
93            current_priority.set_range(min(current_start, next_start)..=max(current_end, next_end));
94            self.option_priority = Some(current_priority);
95
96            // return to the top of the loop
97        }
98    }
99
100    // As few as one (or zero if iter is empty) and as many as iter.len()
101    // There could be one extra if option_range is Some.
102    fn size_hint(&self) -> (usize, Option<usize>) {
103        let (lower, upper) = self.iter.size_hint();
104        let lower = min(lower, 1);
105        if self.option_priority.is_some() {
106            (lower, upper.map(|x| x + 1))
107        } else {
108            (lower, upper)
109        }
110    }
111}
112
113#[must_use = "iterators are lazy and do nothing unless consumed"]
114#[allow(clippy::redundant_pub_crate)]
115pub(crate) struct SortedDisjointMapWithLenSoFar<T: Integer, VR, I> {
116    iter: I,
117    len: <T as Integer>::SafeLen,
118    phantom: PhantomData<VR>,
119}
120
121impl<T, VR, I> SortedDisjointMapWithLenSoFar<T, VR, I>
122where
123    T: Integer,
124    VR: ValueRef,
125    I: SortedDisjointMap<T, VR>,
126{
127    pub(crate) const fn len_so_far(&self) -> <T as Integer>::SafeLen {
128        self.len
129    }
130
131    pub(crate) fn new(iter: I) -> Self {
132        Self {
133            iter,
134            len: <T as Integer>::SafeLen::zero(),
135            phantom: PhantomData,
136        }
137    }
138}
139
140impl<T, VR, I> FusedIterator for SortedDisjointMapWithLenSoFar<T, VR, I>
141where
142    T: Integer,
143    VR: ValueRef,
144    I: SortedDisjointMap<T, VR>,
145{
146}
147
148impl<T, VR, I> Iterator for SortedDisjointMapWithLenSoFar<T, VR, I>
149where
150    T: Integer,
151    VR: ValueRef,
152    I: SortedDisjointMap<T, VR>,
153{
154    type Item = (T, EndValue<T, VR::Target>);
155
156    fn next(&mut self) -> Option<Self::Item> {
157        if let Some((range, value)) = self.iter.next() {
158            let (start, end) = range.clone().into_inner();
159            debug_assert!(start <= end);
160            self.len += T::safe_len(&range);
161            let end_value = EndValue {
162                end,
163                value: value.into_value(),
164            };
165            Some((start, end_value))
166        } else {
167            None
168        }
169    }
170    fn size_hint(&self) -> (usize, Option<usize>) {
171        self.iter.size_hint()
172    }
173}
174
175#[derive(Clone, Debug)]
176#[must_use = "iterators are lazy and do nothing unless consumed"]
177/// Used internally by [`UnionIterMap`] and [`SymDiffIterMap`].
178///
179/// [`UnionIterMap`]: crate::UnionIterMap
180/// [`SymDiffIterMap`]: crate::SymDiffIterMap
181pub struct AssumePrioritySortedStartsMap<I> {
182    iter: I,
183}
184
185impl<T, VR, I> PrioritySortedStartsMap<T, VR> for AssumePrioritySortedStartsMap<I>
186where
187    T: Integer,
188    VR: ValueRef,
189    I: Iterator<Item = Priority<T, VR>> + FusedIterator,
190{
191}
192
193impl<T, VR, I> AssumePrioritySortedStartsMap<I>
194where
195    T: Integer,
196    VR: ValueRef,
197    I: Iterator<Item = Priority<T, VR>> + FusedIterator,
198{
199    pub(crate) const fn new(iter: I) -> Self {
200        Self { iter }
201    }
202}
203
204impl<T, VR, I> FusedIterator for AssumePrioritySortedStartsMap<I>
205where
206    T: Integer,
207    VR: ValueRef,
208    I: Iterator<Item = Priority<T, VR>> + FusedIterator,
209{
210}
211
212impl<T, VR, I> Iterator for AssumePrioritySortedStartsMap<I>
213where
214    T: Integer,
215    VR: ValueRef,
216    I: Iterator<Item = Priority<T, VR>> + FusedIterator,
217{
218    type Item = Priority<T, VR>;
219
220    fn next(&mut self) -> Option<Self::Item> {
221        self.iter.next()
222    }
223
224    fn size_hint(&self) -> (usize, Option<usize>) {
225        self.iter.size_hint()
226    }
227}