range_set_blaze/rog.rs
1#![deprecated(
2 note = "The rog ('range or gap') module is experimental and may be changed or removed in future versions.
3 Changes may not be reflected in the semantic versioning."
4)]
5
6use alloc::collections::btree_map;
7use alloc::vec::Vec;
8use core::{
9 iter::FusedIterator,
10 ops::{RangeBounds, RangeInclusive},
11};
12
13use crate::{Integer, RangeSetBlaze, set::extract_range};
14
15/// Experimental: This struct is created by the [`rogs_range`] method on [`RangeSetBlaze`].
16/// See [`rogs_range`] for more information.
17///
18/// [`RangeSetBlaze`]: crate::RangeSetBlaze
19/// [`rogs_range`]: crate::RangeSetBlaze::rogs_range
20#[must_use = "iterators are lazy and do nothing unless consumed"]
21pub struct RogsIter<'a, T: Integer> {
22 end_in: T,
23 next_rog: Option<Rog<T>>,
24 final_gap_start: Option<T>,
25 btree_map_iter: btree_map::Range<'a, T, T>,
26}
27
28impl<T: Integer> Iterator for RogsIter<'_, T> {
29 type Item = Rog<T>;
30
31 fn next(&mut self) -> Option<Self::Item> {
32 if let Some(rog) = self.next_rog.take() {
33 return Some(rog);
34 }
35
36 if let Some((start_el, end_el)) = self.btree_map_iter.next() {
37 if self.end_in < *start_el {
38 self.btree_map_iter = btree_map::Range::default();
39 } else {
40 debug_assert!(self.final_gap_start.is_some()); // final_gap_start should be Some if we're in this branch
41 debug_assert!(
42 self.final_gap_start.expect("Real Assert: So -1 is safe") < *start_el
43 );
44 let result = Rog::Gap(self.final_gap_start.expect("Real Assert: final_gap_start should be Some if we're in this branch, so -1 is safe")..=start_el.sub_one());
45 if end_el < &self.end_in {
46 self.next_rog = Some(Rog::Range(*start_el..=*end_el));
47 debug_assert!(end_el < &self.end_in); // so +1 is safe
48 self.final_gap_start = Some(end_el.add_one());
49 } else {
50 self.next_rog = Some(Rog::Range(*start_el..=self.end_in));
51 self.final_gap_start = None;
52 }
53 return Some(result);
54 }
55 }
56
57 if let Some(gap_start) = self.final_gap_start.take() {
58 return Some(Rog::Gap(gap_start..=self.end_in));
59 }
60
61 None
62 }
63}
64
65impl<T: Integer> FusedIterator for RogsIter<'_, T> {}
66
67// We can't implement ExactSizeIterator for RogsIter because it doesn't track
68// the number of items that will be returned
69//
70// impl<T: Integer> ExactSizeIterator for RogsIter<'_, T> {
71// fn len(&self) -> usize {
72// // This would need to calculate the number of ranges and gaps
73// }
74// }
75
76/// Experimental: Represents an range or gap in a [`RangeSetBlaze`].
77///
78/// See [`RangeSetBlaze::rogs_range`] and [`RangeSetBlaze::rogs_get`] for more information.
79///
80/// # Example
81///
82/// ```
83/// use range_set_blaze::{RangeSetBlaze, Rog};
84///
85/// let range_set_blaze = RangeSetBlaze::from([1, 2, 3]);
86/// assert_eq!(range_set_blaze.rogs_get(2), Rog::Range(1..=3));
87/// assert_eq!(range_set_blaze.rogs_get(4), Rog::Gap(4..=2_147_483_647));
88/// ```
89
90#[derive(Debug, PartialEq, Eq)]
91pub enum Rog<T: Integer> {
92 /// A range of integers in a [`RangeSetBlaze`].
93 Range(RangeInclusive<T>),
94 /// A gap between integers in a [`RangeSetBlaze`].
95 Gap(RangeInclusive<T>),
96}
97
98impl<T: Integer> Rog<T> {
99 /// Returns the start of a [`Rog`] (range or gap).
100 ///
101 /// # Examples
102 ///
103 /// ```
104 /// use range_set_blaze::Rog;
105 /// assert_eq!(Rog::Gap(1..=3).start(), 1);
106 /// ```
107 pub const fn start(&self) -> T {
108 match self {
109 Self::Gap(r) | Self::Range(r) => *r.start(),
110 }
111 }
112
113 /// Returns the inclusive end of a [`Rog`] (range or gap).
114 ///
115 /// # Examples
116 ///
117 /// ```
118 /// use range_set_blaze::Rog;
119 /// assert_eq!(Rog::Gap(1..=3).end(), 3);
120 /// ```
121 pub const fn end(&self) -> T {
122 match self {
123 Self::Gap(r) | Self::Range(r) => *r.end(),
124 }
125 }
126
127 /// Returns `true` if the [`Rog`] (range or gap) contains the given integer.
128 ///
129 /// # Examples
130 ///
131 /// ```
132 /// use range_set_blaze::Rog;
133 /// assert!(Rog::Gap(1..=3).contains(2));
134 /// assert!(!Rog::Gap(1..=3).contains(4));
135 /// ```
136 pub fn contains(&self, value: T) -> bool {
137 match self {
138 Self::Gap(r) | Self::Range(r) => r.contains(&value),
139 }
140 }
141}
142
143impl<T: Integer> RangeSetBlaze<T> {
144 /// Experimental: Returns the [`Rog`] (range or gap) containing the given integer. If the
145 /// [`RangeSetBlaze`] contains the integer, returns a [`Rog::Range`]. If the
146 /// [`RangeSetBlaze`] does not contain the integer, returns a [`Rog::Gap`].
147 ///
148 /// # Enabling
149 ///
150 /// This method is experimental and must be enabled with the `rog_experimental` feature.
151 /// ```bash
152 /// cargo add range-set-blaze --features "rog_experimental"
153 /// ```
154 ///
155 /// # Examples
156 ///
157 /// ```
158 /// use range_set_blaze::{RangeSetBlaze, Rog};
159 ///
160 /// let range_set_blaze = RangeSetBlaze::from([1, 2, 3]);
161 /// assert_eq!(range_set_blaze.rogs_get(2), Rog::Range(1..=3));
162 /// assert_eq!(range_set_blaze.rogs_get(4), Rog::Gap(4..=2_147_483_647));
163 /// ```
164 pub fn rogs_get(&self, value: T) -> Rog<T> {
165 let mut before = self.btree_map.range(..=value).rev();
166 if let Some((start_before, end_before)) = before.next() {
167 if end_before < &value {
168 // case 1: range doesn't touch the before range
169 let start_out = end_before.add_one();
170 if let Some((start_next, _)) = self.btree_map.range(value..).next() {
171 debug_assert!(start_before < start_next); // so -1 is safe
172 Rog::Gap(start_out..=start_next.sub_one())
173 } else {
174 Rog::Gap(start_out..=T::max_value())
175 }
176 } else {
177 // case 2&3: the range touches the before range
178 Rog::Range(*start_before..=*end_before)
179 }
180 } else {
181 // case 4: there is no before range
182 if let Some((start_next, _)) = self.btree_map.range(value..).next() {
183 debug_assert!(value < *start_next); // so -1 is safe
184 Rog::Gap(T::min_value()..=start_next.sub_one())
185 } else {
186 Rog::Gap(T::min_value()..=T::max_value())
187 }
188 }
189 }
190
191 /// Experimental: Constructs an iterator over a sub-range of [`Rog`]'s (ranges and gaps) in the [`RangeSetBlaze`].
192 /// The simplest way is to use the range syntax `min..=max`, thus `range(min..=max)` will
193 /// yield elements from min (inclusive) to max (inclusive).
194 /// The range may also be entered as `(Bound<T>, Bound<T>)`, so for example
195 /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive
196 /// range from 4 to 10.
197 ///
198 /// # Panics
199 ///
200 /// Panics if range `start > end`.
201 ///
202 /// Panics if range `start == end` and both bounds are `Excluded`.
203 ///
204 /// # Enabling
205 ///
206 /// This method is experimental and must be enabled with the `rog_experimental` feature.
207 /// ```bash
208 /// cargo add range-set-blaze --features "rog_experimental"
209 /// ```
210 ///
211 /// # Examples
212 ///
213 /// ```
214 /// use range_set_blaze::{RangeSetBlaze, Rog};
215 /// use core::ops::Bound::Included;
216 ///
217 /// let mut set = RangeSetBlaze::new();
218 /// set.insert(3);
219 /// set.insert(5);
220 /// set.insert(6);
221 /// for rog in set.rogs_range((Included(4), Included(8))) {
222 /// println!("{rog:?}");
223 /// } // prints: Gap(4..=4)\nRange(5..=6)\nGap(7..=8)
224 ///
225 /// assert_eq!(Some(Rog::Gap(4..=4)), set.rogs_range(4..).next());
226 ///
227 /// let a = RangeSetBlaze::from_iter([1..=6, 11..=15]);
228 /// assert_eq!(
229 /// a.rogs_range(-5..=8).collect::<Vec<_>>(),
230 /// vec![Rog::Gap(-5..=0), Rog::Range(1..=6), Rog::Gap(7..=8)]
231 /// );
232 ///
233 /// let empty = RangeSetBlaze::<u8>::new();
234 /// assert_eq!(
235 /// empty.rogs_range(..).collect::<Vec<_>>(),
236 /// vec![Rog::Gap(0..=255)]
237 /// );
238 /// ```
239 pub fn rogs_range<R>(&self, range: R) -> RogsIter<'_, T>
240 where
241 R: RangeBounds<T>,
242 {
243 let (start_in, end_in) = extract_range(range);
244 assert!(
245 start_in <= end_in,
246 "start must be less than or equal to end"
247 );
248
249 let mut before = self.btree_map.range(..=start_in).rev();
250 if let Some((_, end_before)) = before.next() {
251 if end_before < &start_in {
252 // case 1: range doesn't touch the before range
253 RogsIter {
254 end_in,
255 next_rog: None,
256 final_gap_start: Some(start_in),
257 btree_map_iter: self.btree_map.range(start_in..),
258 }
259 } else if end_before < &end_in {
260 // case 2: the range touches and extends beyond the before range
261 debug_assert!(*end_before < end_in); // so +1 is safe
262 debug_assert!(start_in <= *end_before); // so +1 is safe
263 RogsIter {
264 end_in,
265 next_rog: Some(Rog::Range(start_in..=*end_before)),
266 final_gap_start: Some(end_before.add_one()),
267 btree_map_iter: self.btree_map.range(start_in.add_one()..),
268 }
269 } else {
270 // case 3 the range is completely contained in the before range
271 RogsIter {
272 end_in,
273 next_rog: Some(Rog::Range(start_in..=end_in)),
274 final_gap_start: None,
275 btree_map_iter: btree_map::Range::default(),
276 }
277 }
278 } else {
279 // case 4: there is no before range
280 RogsIter {
281 end_in,
282 next_rog: None,
283 final_gap_start: Some(start_in),
284 btree_map_iter: self.btree_map.range(start_in..),
285 }
286 }
287 }
288
289 /// Used internally to test `rogs_range`.
290 #[doc(hidden)]
291 pub fn rogs_range_slow<R>(&self, range: R) -> Vec<Rog<T>>
292 where
293 R: RangeBounds<T>,
294 {
295 let (start_in, end_in) = extract_range(range);
296
297 assert!(
298 start_in <= end_in,
299 "start must be less than or equal to end"
300 );
301
302 let rsb_in = Self::from_iter([start_in..=end_in]);
303 let ranges = &rsb_in & self;
304 let gaps = rsb_in - self;
305 let ranges = ranges.ranges().map(|r| Rog::Range(r));
306 let gaps = gaps.ranges().map(|r| Rog::Gap(r));
307 let mut result = ranges.chain(gaps).collect::<Vec<Rog<T>>>();
308 result.sort_by_key(Rog::start);
309 result
310 }
311
312 /// Used internally to test `rogs_get`.
313 #[doc(hidden)]
314 pub fn rogs_get_slow(&self, value: T) -> Rog<T> {
315 let all_rogs = self.rogs_range_slow(..);
316 for rog in all_rogs {
317 if rog.contains(value) {
318 return rog;
319 }
320 }
321 unreachable!("value must be in something");
322 }
323}