1use core::{iter::FusedIterator, ops::RangeInclusive};
2
3use alloc::collections::btree_map;
4
5use crate::{
6 Integer, SortedDisjointMap,
7 map::{EndValue, ValueRef},
8};
9
10#[must_use = "iterators are lazy and do nothing unless consumed"]
18#[derive(Clone, Debug)]
19pub struct IterMap<T, VR, I> {
20 iter: I,
21 option_range_value_front: Option<(RangeInclusive<T>, VR)>,
22 option_range_value_back: Option<(RangeInclusive<T>, VR)>,
23}
24
25impl<T, VR, I> IterMap<T, VR, I>
26where
27 T: Integer,
28 VR: ValueRef,
29 I: SortedDisjointMap<T, VR>,
30{
31 pub(crate) const fn new(iter: I) -> Self {
32 Self {
33 iter,
34 option_range_value_front: None,
35 option_range_value_back: None,
36 }
37 }
38}
39
40impl<T, VR, I> FusedIterator for IterMap<T, VR, I>
41where
42 T: Integer,
43 VR: ValueRef,
44 I: SortedDisjointMap<T, VR> + FusedIterator,
45{
46}
47
48impl<T, VR, I> Iterator for IterMap<T, VR, I>
49where
50 T: Integer,
51 VR: ValueRef,
52 I: SortedDisjointMap<T, VR>,
53{
54 type Item = (T, VR);
55
56 fn next(&mut self) -> Option<Self::Item> {
57 let mut range_value = self
58 .option_range_value_front
59 .take()
60 .or_else(|| self.iter.next())
61 .or_else(|| self.option_range_value_back.take())?;
62
63 let (start, end) = range_value.0.into_inner();
64 debug_assert!(start <= end);
65 let value = range_value.1.clone();
66 if start < end {
67 range_value.0 = start.add_one()..=end;
68 self.option_range_value_front = Some(range_value);
69 }
70 Some((start, value))
71 }
72
73 fn size_hint(&self) -> (usize, Option<usize>) {
76 let (low, _high) = self.iter.size_hint();
77 (low, None)
78 }
79}
80
81impl<T, VR, I> DoubleEndedIterator for IterMap<T, VR, I>
82where
83 T: Integer,
84 VR: ValueRef,
85 I: SortedDisjointMap<T, VR> + DoubleEndedIterator,
86{
87 fn next_back(&mut self) -> Option<Self::Item> {
88 let mut range_value = self
89 .option_range_value_back
90 .take()
91 .or_else(|| self.iter.next_back())
92 .or_else(|| self.option_range_value_front.take())?;
93 let (start, end) = range_value.0.into_inner();
94 debug_assert!(start <= end);
95 let value = range_value.1.clone();
96 if start < end {
97 range_value.0 = start..=end.sub_one();
98 self.option_range_value_back = Some(range_value);
99 }
100
101 Some((end, value))
102 }
103}
104
105#[derive(Debug)]
113#[must_use = "iterators are lazy and do nothing unless consumed"]
114pub struct IntoIterMap<T, V> {
115 option_start_end_value_front: Option<(T, EndValue<T, V>)>,
116 option_start_end_value_back: Option<(T, EndValue<T, V>)>,
117 into_iter: btree_map::IntoIter<T, EndValue<T, V>>,
118}
119
120impl<T, V> IntoIterMap<T, V>
121where
122 T: Integer,
123 V: Eq + Clone,
124{
125 pub(crate) const fn new(into_iter: btree_map::IntoIter<T, EndValue<T, V>>) -> Self {
126 Self {
127 option_start_end_value_front: None,
128 option_start_end_value_back: None,
129 into_iter,
130 }
131 }
132}
133
134impl<T, V> FusedIterator for IntoIterMap<T, V>
135where
136 T: Integer,
137 V: Eq + Clone,
138{
139}
140
141impl<T, V> Iterator for IntoIterMap<T, V>
142where
143 T: Integer,
144 V: Eq + Clone,
145{
146 type Item = (T, V);
147
148 fn next(&mut self) -> Option<Self::Item> {
149 let (start, end_value) = self
150 .option_start_end_value_front
151 .take()
152 .or_else(|| self.into_iter.next())
153 .or_else(|| self.option_start_end_value_back.take())?;
154
155 let end = end_value.end;
156 let value = end_value.value.clone();
157 debug_assert!(start <= end);
158 if start < end {
159 let start_plus1_end_value = (start.add_one(), end_value);
160 self.option_start_end_value_front = Some(start_plus1_end_value);
161 }
162 Some((start, value))
163 }
164
165 fn size_hint(&self) -> (usize, Option<usize>) {
168 let (low, _high) = self.into_iter.size_hint();
169 (low, None)
170 }
171}
172
173impl<T, V> DoubleEndedIterator for IntoIterMap<T, V>
174where
175 T: Integer,
176 V: Eq + Clone,
177{
178 fn next_back(&mut self) -> Option<Self::Item> {
179 let (start, mut end_value) = self
180 .option_start_end_value_back
181 .take()
182 .or_else(|| self.into_iter.next_back())
183 .or_else(|| self.option_start_end_value_front.take())?;
184
185 let end = end_value.end;
186 let value = end_value.value.clone();
187 debug_assert!(start <= end);
188
189 if start < end {
190 end_value.end.assign_sub_one();
191 let start_end_less1_value = (start, end_value);
192 self.option_start_end_value_back = Some(start_end_less1_value);
193 }
194
195 Some((end, value))
196 }
197}