Skip to main content

range_set_blaze/
sorted_disjoint.rs

1use crate::FillGapsIter;
2use crate::RangeSetBlaze;
3use crate::map::ValueCarrier;
4use crate::range_values::{MapIntoRangesIter, MapRangesIter, RangeValuesToRangesIter};
5use crate::ranges_iter::RangesIter;
6use crate::sorted_disjoint_map::IntoString;
7use crate::{IntoRangesIter, UnionIter, UnionMerge};
8use alloc::string::String;
9use core::{
10    array,
11    iter::{
12        Empty, Filter, FlatMap, Flatten, Fuse, FusedIterator, Once, Peekable, Skip, SkipWhile,
13        Take, TakeWhile,
14    },
15    ops::{self, RangeInclusive},
16    option,
17};
18
19use crate::SortedDisjointMap;
20
21use crate::{
22    DifferenceMerge, DynSortedDisjoint, Integer, IntersectionMerge, Merge, NotIter, SymDiffIter,
23    SymDiffMerge,
24};
25
26/// Used internally. Marks iterators that provide ranges sorted by start, but
27/// that are not necessarily disjoint. The ranges are non-empty.
28pub trait SortedStarts<T: Integer>: Iterator<Item = RangeInclusive<T>> + FusedIterator {}
29
30impl<T: Integer, I, P> SortedStarts<T> for Filter<I, P>
31where
32    I: SortedStarts<T>,
33    P: FnMut(&I::Item) -> bool,
34{
35}
36
37impl<T: Integer, I, P> SortedDisjoint<T> for Filter<I, P>
38where
39    I: SortedDisjoint<T>,
40    P: FnMut(&I::Item) -> bool,
41{
42}
43
44impl<T: Integer, I, P> SortedStarts<T> for TakeWhile<I, P>
45where
46    I: SortedStarts<T>,
47    P: FnMut(&I::Item) -> bool,
48{
49}
50
51impl<T: Integer, I, P> SortedDisjoint<T> for TakeWhile<I, P>
52where
53    I: SortedDisjoint<T>,
54    P: FnMut(&I::Item) -> bool,
55{
56}
57
58impl<T: Integer, I, P> SortedStarts<T> for SkipWhile<I, P>
59where
60    I: SortedStarts<T>,
61    P: FnMut(&I::Item) -> bool,
62{
63}
64
65impl<T: Integer, I, P> SortedDisjoint<T> for SkipWhile<I, P>
66where
67    I: SortedDisjoint<T>,
68    P: FnMut(&I::Item) -> bool,
69{
70}
71
72impl<T, I> SortedStarts<T> for Flatten<option::IntoIter<I>>
73where
74    T: Integer,
75    I: SortedStarts<T>,
76{
77}
78
79impl<T, I> SortedDisjoint<T> for Flatten<option::IntoIter<I>>
80where
81    T: Integer,
82    I: SortedDisjoint<T>,
83{
84}
85impl<T, I, IInner, TMap> SortedStarts<T> for FlatMap<option::IntoIter<I>, IInner, TMap>
86where
87    T: Integer,
88    IInner: SortedStarts<T>,
89    I: SortedStarts<T>,
90    TMap: FnMut(I) -> IInner,
91{
92}
93
94impl<T, I, IInner, TMap> SortedDisjoint<T> for FlatMap<option::IntoIter<I>, IInner, TMap>
95where
96    T: Integer,
97    IInner: SortedDisjoint<T>,
98    I: SortedDisjoint<T>,
99    TMap: FnMut(I) -> IInner,
100{
101}
102
103// Potential future support for core::iter::StepBy once it implements FusedIterator:
104// https://internals.rust-lang.org/t/implement-fusediterator-for-core-stepby/24074
105//
106// Check if core::iter::StepBy implements FusedIterator if it's inner is. Seems like it could be upstreamed
107// https://internals.rust-lang.org/t/implement-fusediterator-for-core-stepby/24074
108// impl<T: Integer, I> SortedStarts<T> for core::iter::Fuse<core::iter::StepBy<I>> where
109//     I: SortedStarts<T>
110// {
111// }
112// impl<T: Integer, I> SortedDisjoint<T> for core::iter::Fuse<core::iter::StepBy<I>> where
113//     I: SortedDisjoint<T>
114// {
115// }
116
117impl<T: Integer, I> SortedStarts<T> for Fuse<I> where I: SortedStarts<T> {}
118impl<T: Integer, I> SortedDisjoint<T> for Fuse<I> where I: SortedDisjoint<T> {}
119
120impl<T: Integer, I> SortedStarts<T> for Skip<I> where I: SortedStarts<T> {}
121impl<T: Integer, I> SortedDisjoint<T> for Skip<I> where I: SortedDisjoint<T> {}
122
123impl<T: Integer, I> SortedStarts<T> for Take<I> where I: SortedStarts<T> {}
124impl<T: Integer, I> SortedDisjoint<T> for Take<I> where I: SortedDisjoint<T> {}
125
126impl<T: Integer, I> SortedStarts<T> for Peekable<I> where I: SortedStarts<T> {}
127impl<T: Integer, I> SortedDisjoint<T> for Peekable<I> where I: SortedDisjoint<T> {}
128
129impl<T: Integer> SortedStarts<T> for Empty<RangeInclusive<T>> {}
130impl<T: Integer> SortedDisjoint<T> for Empty<RangeInclusive<T>> {}
131
132impl<T: Integer> SortedStarts<T> for Once<RangeInclusive<T>> {}
133impl<T: Integer> SortedDisjoint<T> for Once<RangeInclusive<T>> {}
134
135/// Marks iterators that provide ranges that are sorted by start and disjoint. Set operations on
136/// iterators that implement this trait can be performed in linear time.
137///
138/// # Table of Contents
139/// * [`SortedDisjoint` Constructors](#sorteddisjoint-constructors)
140///   * [Examples](#constructor-examples)
141/// * [`SortedDisjoint` Set Operations](#sorteddisjoint-set-operations)
142///   * [Performance](#performance)
143///   * [Examples](#examples)
144/// * [How to mark your type as `SortedDisjoint`](#how-to-mark-your-type-as-sorteddisjoint)
145///   * [Example – Find the ordinal weekdays in September 2023](#example--find-the-ordinal-weekdays-in-september-2023)
146///
147/// # `SortedDisjoint` Constructors
148///
149/// You'll usually construct a `SortedDisjoint` iterator from a [`RangeSetBlaze`] or a [`CheckSortedDisjoint`].
150/// Here is a summary table, followed by [examples](#constructor-examples). You can also [define your own
151/// `SortedDisjoint`](#how-to-mark-your-type-as-sorteddisjoint).
152///
153/// | Input type | Method |
154/// |------------|--------|
155/// | [`RangeSetBlaze`] | [`ranges`] |
156/// | [`RangeSetBlaze`] | [`into_ranges`] |
157/// | sorted & disjoint ranges | [`CheckSortedDisjoint::new`] |
158/// | [`RangeInclusive`] | [`RangeOnce::new`] |
159/// |  *your iterator type* | *[How to mark your type as `SortedDisjoint`][1]* |
160///
161/// [`ranges`]: RangeSetBlaze::ranges
162/// [`into_ranges`]: RangeSetBlaze::into_ranges
163/// [1]: #how-to-mark-your-type-as-sorteddisjoint
164/// [`RangesIter`]: crate::RangesIter
165/// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
166///
167/// ## Constructor Examples
168/// ```
169/// use range_set_blaze::prelude::*;
170///
171/// // RangeSetBlaze's .ranges() and .into_ranges()
172/// let r = RangeSetBlaze::from_iter([3, 2, 1, 100, 1]);
173/// let a = r.ranges();
174/// assert!(a.into_string() == "1..=3, 100..=100");
175/// // 'into_ranges' takes ownership of the 'RangeSetBlaze'
176/// let a = RangeSetBlaze::from_iter([3, 2, 1, 100, 1]).into_ranges();
177/// assert!(a.into_string() == "1..=3, 100..=100");
178///
179/// // CheckSortedDisjoint -- unsorted or overlapping input ranges will cause a panic.
180/// let a = CheckSortedDisjoint::new([1..=3, 100..=100]);
181/// assert!(a.into_string() == "1..=3, 100..=100");
182/// ```
183///
184/// # `SortedDisjoint` Set Operations
185///
186/// You can perform set operations on `SortedDisjoint`s using operators.
187///
188/// | Set Operators                             | Operator    | Multiway (same type)                              | Multiway (different types)           |
189/// |------------------------------------|-------------|---------------------------------------------------|--------------------------------------|
190/// | [`union`]                      | [`a` &#124; `b`] | <code>[a, b, c].[union][multiway_union]() </code>        | <code>[union_dyn!][union_dyn_macro](a, b, c)</code>         |
191/// | [`intersection`]               | [`a & b`]     | <code>[a, b, c].[intersection][multiway_intersection]() </code> | <code>[intersection_dyn!][intersection_dyn_macro](a, b, c)</code>|
192/// | [`difference`]                 | [`a - b`]     | *n/a*                                             | *n/a*                                |
193/// | [`symmetric_difference`]       | [`a ^ b`]     | <code>[a, b, c].[symmetric_difference][multiway_symmetric_difference]() </code> | <code>[symmetric_difference_dyn!][symmetric_difference_dyn_macro](a, b, c)</code> |
194/// | [`complement`]                 | [`!a`]        | *n/a*                                             | *n/a*                                |
195///
196/// [`a` &#124; `b`]: trait.SortedDisjoint.html#method.union
197/// [`a & b`]: trait.SortedDisjoint.html#method.intersection
198/// [`a - b`]: trait.SortedDisjoint.html#method.difference
199/// [`a ^ b`]: trait.SortedDisjoint.html#method.symmetric_difference
200/// [`!a`]: trait.SortedDisjoint.html#method.complement
201/// [multiway_union]: trait.MultiwaySortedDisjoint.html#method.union
202/// [multiway_intersection]: trait.MultiwaySortedDisjoint.html#method.intersection
203/// [multiway_symmetric_difference]: trait.MultiwaySortedDisjoint.html#method.symmetric_difference
204/// [union_dyn_macro]: macro@crate::union_dyn
205/// [intersection_dyn_macro]: macro@crate::intersection_dyn
206/// [symmetric_difference_dyn_macro]: macro@crate::symmetric_difference_dyn
207/// ## Performance
208///
209/// Every operation is implemented as a single pass over the sorted & disjoint ranges, with minimal memory.
210///
211/// This is true even when applying multiple operations. The last example below demonstrates this.
212///
213/// ## Standard Iterators
214///
215/// Many `core::iter` adapters preserve this marker trait when the inner iterator already
216/// implements it, including `filter`, `take_while`, `skip_while`, `fuse`, `skip`, `take`,
217/// and `peekable`. `empty`/`once` iterators and `Option`-based `flatten`/`flat_map` are also
218/// supported.
219///
220/// ## Examples
221///
222/// ```
223/// use range_set_blaze::prelude::*;
224///
225/// let a0 = RangeSetBlaze::from_iter([1..=2, 5..=100]);
226/// let b0 = RangeSetBlaze::from_iter([2..=6]);
227///
228/// // 'union' method and 'to_string' method
229/// let (a, b) = (a0.ranges(), b0.ranges());
230/// let result = a.union(b);
231/// assert_eq!(result.into_string(), "1..=100");
232///
233/// // '|' operator and 'equal' method
234/// let (a, b) = (a0.ranges(), b0.ranges());
235/// let result = a | b;
236/// assert!(result.equal(CheckSortedDisjoint::new([1..=100])));
237///
238/// // multiway union of same type
239/// let c0 = RangeSetBlaze::from_iter([2..=2, 6..=200]);
240/// let (a, b, c) = (a0.ranges(), b0.ranges(), c0.ranges());
241/// let result = [a, b, c].union();
242/// assert_eq!(result.into_string(), "1..=200");
243///
244/// // multiway union of different types
245/// let (a, b, c) = (a0.ranges(), b0.ranges(), c0.ranges());
246/// let result = union_dyn!(a, b, !c);
247/// assert_eq!(result.into_string(), "-2147483648..=100, 201..=2147483647");
248///
249/// // Applying multiple operators makes only one pass through the inputs with minimal memory.
250/// let (a, b, c) = (a0.ranges(), b0.ranges(), c0.ranges());
251/// let result = a - (b | c);
252/// assert!(result.into_string() == "1..=1");
253/// ```
254///
255/// # How to mark your type as `SortedDisjoint`
256///
257/// To mark your iterator type as `SortedDisjoint`, you implement the `SortedStarts` and `SortedDisjoint` traits.
258/// This is your promise to the compiler that your iterator will provide inclusive ranges that are
259/// disjoint and sorted by start.
260///
261/// When you do this, your iterator will get access to the
262/// efficient set operations methods, such as [`intersection`] and [`complement`]. The example below shows this.
263///
264/// > To use operators such as `&` and `!`, you must also implement the [`BitAnd`], [`Not`], etc. traits.
265/// >
266/// > If you want others to use your marked iterator type, reexport:
267/// > `pub use range_set_blaze::{SortedDisjoint, SortedStarts};`
268///
269/// [`BitAnd`]: core::ops::BitAnd
270/// [`Not`]: core::ops::Not
271/// [`intersection`]: SortedDisjoint::intersection
272/// [`complement`]: SortedDisjoint::complement
273/// [`union`]: SortedDisjoint::union
274/// [`symmetric_difference`]: SortedDisjoint::symmetric_difference
275/// [`difference`]: SortedDisjoint::difference
276/// [`to_string`]: SortedDisjoint::to_string
277/// [`equal`]: SortedDisjoint::equal
278/// [multiway_union]: crate::MultiwaySortedDisjoint::union
279/// [multiway_intersection]: crate::MultiwaySortedDisjoint::intersection
280///
281/// ## Example -- Find the ordinal weekdays in September 2023
282/// ```
283/// use core::ops::RangeInclusive;
284/// use core::iter::FusedIterator;
285/// pub use range_set_blaze::{SortedDisjoint, SortedStarts};
286///
287/// // Ordinal dates count January 1 as day 1, February 1 as day 32, etc.
288/// struct OrdinalWeekends2023 {
289///     next_range: RangeInclusive<i32>,
290/// }
291///
292/// // We promise the compiler that our iterator will provide
293/// // ranges that are sorted and disjoint.
294/// impl FusedIterator for OrdinalWeekends2023 {}
295/// impl SortedStarts<i32> for OrdinalWeekends2023 {}
296/// impl SortedDisjoint<i32> for OrdinalWeekends2023 {}
297///
298/// impl OrdinalWeekends2023 {
299///     fn new() -> Self {
300///         Self { next_range: 0..=1 }
301///     }
302/// }
303/// impl Iterator for OrdinalWeekends2023 {
304///     type Item = RangeInclusive<i32>;
305///     fn next(&mut self) -> Option<Self::Item> {
306///         let (start, end) = self.next_range.clone().into_inner();
307///         if start > 365 {
308///             None
309///         } else {
310///             self.next_range = (start + 7)..=(end + 7);
311///             Some(start.max(1)..=end.min(365))
312///         }
313///     }
314/// }
315///
316/// use range_set_blaze::prelude::*;
317///
318/// let weekends = OrdinalWeekends2023::new();
319/// let september = CheckSortedDisjoint::new([244..=273]);
320/// let september_weekdays = september.intersection(weekends.complement());
321/// assert_eq!(
322///     september_weekdays.into_string(),
323///     "244..=244, 247..=251, 254..=258, 261..=265, 268..=272"
324/// );
325/// ```
326pub trait SortedDisjoint<T: Integer>: SortedStarts<T> {
327    // I think this is 'Sized' because will sometimes want to create a struct (e.g. BitOrIter) that contains a field of this type
328
329    /// Given two [`SortedDisjoint`] iterators, efficiently returns a [`SortedDisjoint`] iterator of their union.
330    ///
331    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
332    ///
333    /// # Examples
334    ///
335    /// ```
336    /// use range_set_blaze::prelude::*;
337    ///
338    /// let a = CheckSortedDisjoint::new([1..=1]);
339    /// let b = RangeSetBlaze::from_iter([2..=2]).into_ranges();
340    /// let union = a.union(b);
341    /// assert_eq!(union.into_string(), "1..=2");
342    ///
343    /// // Alternatively, we can use "|" because CheckSortedDisjoint defines
344    /// // ops::bitor as SortedDisjoint::union.
345    /// let a = CheckSortedDisjoint::new([1..=1]);
346    /// let b = RangeSetBlaze::from_iter([2..=2]).into_ranges();
347    /// let union = a | b;
348    /// assert_eq!(union.into_string(), "1..=2");
349    /// ```
350    #[inline]
351    fn union<R>(self, other: R) -> UnionMerge<T, Self, R::IntoIter>
352    where
353        R: IntoIterator<Item = Self::Item>,
354        R::IntoIter: SortedDisjoint<T>,
355        Self: Sized,
356    {
357        UnionMerge::new2(self, other.into_iter())
358    }
359
360    /// Given two [`SortedDisjoint`] iterators, efficiently returns a [`SortedDisjoint`] iterator of their intersection.
361    ///
362    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
363    ///
364    /// # Examples
365    ///
366    /// ```
367    /// use range_set_blaze::prelude::*;
368    ///
369    /// let a = CheckSortedDisjoint::new([1..=2]);
370    /// let b = RangeSetBlaze::from_iter([2..=3]).into_ranges();
371    /// let intersection = a.intersection(b);
372    /// assert_eq!(intersection.into_string(), "2..=2");
373    ///
374    /// // Alternatively, we can use "&" because CheckSortedDisjoint defines
375    /// // ops::bitand as SortedDisjoint::intersection.
376    /// let a = CheckSortedDisjoint::new([1..=2]);
377    /// let b = RangeSetBlaze::from_iter([2..=3]).into_ranges();
378    /// let intersection = a & b;
379    /// assert_eq!(intersection.into_string(), "2..=2");
380    /// ```
381    #[inline]
382    fn intersection<R>(self, other: R) -> IntersectionMerge<T, Self, R::IntoIter>
383    where
384        R: IntoIterator<Item = Self::Item>,
385        R::IntoIter: SortedDisjoint<T>,
386        Self: Sized,
387    {
388        !(self.complement() | other.into_iter().complement())
389    }
390
391    /// Given two [`SortedDisjoint`] iterators, efficiently returns a [`SortedDisjoint`] iterator of their set difference.
392    ///
393    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
394    ///
395    /// # Examples
396    ///
397    /// ```
398    /// use range_set_blaze::prelude::*;
399    ///
400    /// let a = CheckSortedDisjoint::new([1..=2]);
401    /// let b = RangeSetBlaze::from_iter([2..=3]).into_ranges();
402    /// let difference = a.difference(b);
403    /// assert_eq!(difference.into_string(), "1..=1");
404    ///
405    /// // Alternatively, we can use "-" because CheckSortedDisjoint defines
406    /// // ops::sub as SortedDisjoint::difference.
407    /// let a = CheckSortedDisjoint::new([1..=2]);
408    /// let b = RangeSetBlaze::from_iter([2..=3]).into_ranges();
409    /// let difference = a - b;
410    /// assert_eq!(difference.into_string(), "1..=1");
411    /// ```
412    #[inline]
413    fn difference<R>(self, other: R) -> DifferenceMerge<T, Self, R::IntoIter>
414    where
415        R: IntoIterator<Item = Self::Item>,
416        R::IntoIter: SortedDisjoint<T>,
417        Self: Sized,
418    {
419        !(self.complement() | other.into_iter())
420    }
421
422    /// Given a [`SortedDisjoint`] iterator, efficiently returns a [`SortedDisjoint`] iterator of its complement.
423    ///
424    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
425    ///
426    /// # Examples
427    ///
428    /// ```
429    /// use range_set_blaze::prelude::*;
430    ///
431    /// let a = CheckSortedDisjoint::new([10_u8..=20, 100..=200]);
432    /// let complement = a.complement();
433    /// assert_eq!(complement.into_string(), "0..=9, 21..=99, 201..=255");
434    ///
435    /// // Alternatively, we can use "!" because CheckSortedDisjoint defines
436    /// // `ops::Not` as `SortedDisjoint::complement`.
437    /// let a = CheckSortedDisjoint::new([10_u8..=20, 100..=200]);
438    /// let complement = !a;
439    /// assert_eq!(complement.into_string(), "0..=9, 21..=99, 201..=255");
440    /// ```
441    #[inline]
442    fn complement(self) -> NotIter<T, Self>
443    where
444        Self: Sized,
445    {
446        NotIter::new(self)
447    }
448
449    /// Fills the gaps in this sorted, disjoint set stream with `false` values.
450    ///
451    /// The returned stream covers the full integer domain from `T::min_value()`
452    /// through `T::max_value()`. Existing ranges are returned with `true` and
453    /// gaps with `false`.
454    ///
455    /// This is the lazy streaming form of the operation. To obtain a
456    /// materialized [`RangeMapBlaze<T, bool>`] instead, use
457    /// [`RangeSetBlaze::fill_gaps`].
458    ///
459    /// See the [Ranges and gaps guide][crate::gaps] for set and map examples,
460    /// including the leading and trailing gaps at the integer-domain bounds.
461    ///
462    /// [`RangeMapBlaze<T, bool>`]: crate::RangeMapBlaze
463    /// [`RangeSetBlaze::fill_gaps`]: crate::RangeSetBlaze::fill_gaps
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// use range_set_blaze::{CheckSortedDisjoint, SortedDisjoint};
469    ///
470    /// let stream = CheckSortedDisjoint::new([1_u8..=3, 7..=10]);
471    /// assert_eq!(
472    ///     stream.fill_gaps().collect::<Vec<_>>(),
473    ///     vec![
474    ///         (0..=0, false),
475    ///         (1..=3, true),
476    ///         (4..=6, false),
477    ///         (7..=10, true),
478    ///         (11..=u8::MAX, false),
479    ///     ]
480    /// );
481    /// ```
482    #[inline]
483    fn fill_gaps(self) -> FillGapsIter<T, Self>
484    where
485        Self: Sized,
486    {
487        FillGapsIter::new(self)
488    }
489
490    /// Given two [`SortedDisjoint`] iterators, efficiently returns a [`SortedDisjoint`] iterator
491    /// of their symmetric difference.
492    ///
493    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
494    /// # Examples
495    ///
496    /// ```
497    /// use range_set_blaze::prelude::*;
498    ///
499    /// let a = CheckSortedDisjoint::new([1..=2]);
500    /// let b = RangeSetBlaze::from_iter([2..=3]).into_ranges();
501    /// let symmetric_difference = a.symmetric_difference(b);
502    /// assert_eq!(symmetric_difference.into_string(), "1..=1, 3..=3");
503    ///
504    /// // Alternatively, we can use "^" because CheckSortedDisjoint defines
505    /// // ops::bitxor as SortedDisjoint::symmetric_difference.
506    /// let a = CheckSortedDisjoint::new([1..=2]);
507    /// let b = RangeSetBlaze::from_iter([2..=3]).into_ranges();
508    /// let symmetric_difference = a ^ b;
509    /// assert_eq!(symmetric_difference.into_string(), "1..=1, 3..=3");
510    /// ```
511    #[inline]
512    fn symmetric_difference<R>(self, other: R) -> SymDiffMerge<T, Self, R::IntoIter>
513    where
514        R: IntoIterator<Item = Self::Item>,
515        R::IntoIter: SortedDisjoint<T>,
516        <R as IntoIterator>::IntoIter:,
517        Self: Sized,
518    {
519        let result: SymDiffIter<T, Merge<T, Self, <R as IntoIterator>::IntoIter>> =
520            SymDiffIter::new2(self, other.into_iter());
521        result
522    }
523
524    /// Given two [`SortedDisjoint`] iterators, efficiently tells if they are equal. Unlike most equality testing in Rust,
525    /// this method takes ownership of the iterators and consumes them.
526    ///
527    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
528    ///
529    /// # Examples
530    ///
531    /// ```
532    /// use range_set_blaze::prelude::*;
533    ///
534    /// let a = CheckSortedDisjoint::new([1..=2]);
535    /// let b = RangeSetBlaze::from_iter([1..=2]).into_ranges();
536    /// assert!(a.equal(b));
537    /// ```
538    fn equal<R>(self, other: R) -> bool
539    where
540        R: IntoIterator<Item = Self::Item>,
541        R::IntoIter: SortedDisjoint<T>,
542        Self: Sized,
543    {
544        itertools::equal(self, other)
545    }
546
547    /// Deprecated. Use [`into_string`] instead.
548    ///
549    /// [`into_string`]: trait.IntoString.html
550    #[deprecated(since = "0.2.0", note = "Use `into_string` instead")]
551    fn to_string(self) -> String
552    where
553        Self: Sized,
554    {
555        self.into_string()
556    }
557
558    /// Returns `true` if the set contains no elements.
559    ///
560    /// # Examples
561    ///
562    /// ```
563    /// use range_set_blaze::prelude::*;
564    ///
565    /// let a = CheckSortedDisjoint::new([1..=2]);
566    /// assert!(!a.is_empty());
567    /// ```
568    #[inline]
569    #[allow(clippy::wrong_self_convention)]
570    fn is_empty(mut self) -> bool
571    where
572        Self: Sized,
573    {
574        self.next().is_none()
575    }
576
577    /// Returns `true` if the set contains all possible integers.
578    ///
579    /// For type `T`, this means exactly one range spanning `T::min_value()`..=`T::max_value()`.
580    /// Complexity: O(1) on the first item.
581    ///
582    /// # Examples
583    ///
584    /// ```
585    /// use range_set_blaze::prelude::*;
586    ///
587    /// let a = CheckSortedDisjoint::new([1_u8..=2]);
588    /// assert!(!a.is_universal());
589    ///
590    /// let universal = CheckSortedDisjoint::new([0_u8..=255]);
591    /// assert!(universal.is_universal());
592    /// ```
593    #[inline]
594    #[allow(clippy::wrong_self_convention)]
595    fn is_universal(mut self) -> bool
596    where
597        Self: Sized,
598    {
599        self.next().is_some_and(|range| {
600            let (start, end) = range.into_inner();
601            start == T::min_value() && end == T::max_value()
602        })
603    }
604
605    /// Returns `true` if the set is a subset of another,
606    /// i.e., `other` contains at least all the elements in `self`.
607    ///
608    /// # Examples
609    ///
610    /// ```
611    /// use range_set_blaze::prelude::*;
612    ///
613    /// let sup = CheckSortedDisjoint::new([1..=3]);
614    /// let set: CheckSortedDisjoint<i32, _> = [].into();
615    /// assert_eq!(set.is_subset(sup), true);
616    ///
617    /// let sup = CheckSortedDisjoint::new([1..=3]);
618    /// let set = CheckSortedDisjoint::new([2..=2]);
619    /// assert_eq!(set.is_subset(sup), true);
620    ///
621    /// let sup = CheckSortedDisjoint::new([1..=3]);
622    /// let set = CheckSortedDisjoint::new([2..=2, 4..=4]);
623    /// assert_eq!(set.is_subset(sup), false);
624    /// ```
625    #[must_use]
626    #[inline]
627    #[allow(clippy::wrong_self_convention)]
628    fn is_subset<R>(self, other: R) -> bool
629    where
630        R: IntoIterator<Item = Self::Item>,
631        R::IntoIter: SortedDisjoint<T>,
632        Self: Sized,
633    {
634        // LATER: Could be made a little more efficient by coding the logic directly into the iterators.
635        self.difference(other).is_empty()
636    }
637
638    /// Returns `true` if the set is a superset of another,
639    /// i.e., `self` contains at least all the elements in `other`.
640    ///
641    /// # Examples
642    ///
643    /// ```
644    /// use range_set_blaze::RangeSetBlaze;
645    ///
646    /// let sub = RangeSetBlaze::from_iter([1, 2]);
647    /// let mut set = RangeSetBlaze::new();
648    ///
649    /// assert_eq!(set.is_superset(&sub), false);
650    ///
651    /// set.insert(0);
652    /// set.insert(1);
653    /// assert_eq!(set.is_superset(&sub), false);
654    ///
655    /// set.insert(2);
656    /// assert_eq!(set.is_superset(&sub), true);
657    /// ```
658    #[inline]
659    #[must_use]
660    #[allow(clippy::wrong_self_convention)]
661    fn is_superset<R>(self, other: R) -> bool
662    where
663        R: IntoIterator<Item = Self::Item>,
664        R::IntoIter: SortedDisjoint<T>,
665        Self: Sized,
666    {
667        other.into_iter().is_subset(self)
668    }
669
670    /// Returns `true` if `self` has no elements in common with `other`.
671    /// This is equivalent to checking for an empty intersection.
672    ///
673    /// # Examples
674    ///
675    /// ```
676    /// use range_set_blaze::RangeSetBlaze;
677    ///
678    /// let a = RangeSetBlaze::from_iter([1..=3]);
679    /// let mut b = RangeSetBlaze::new();
680    ///
681    /// assert_eq!(a.is_disjoint(&b), true);
682    /// b.insert(4);
683    /// assert_eq!(a.is_disjoint(&b), true);
684    /// b.insert(1);
685    /// assert_eq!(a.is_disjoint(&b), false);
686    /// ```
687    #[must_use]
688    #[inline]
689    #[allow(clippy::wrong_self_convention)]
690    fn is_disjoint<R>(self, other: R) -> bool
691    where
692        R: IntoIterator<Item = Self::Item>,
693        R::IntoIter: SortedDisjoint<T>,
694        Self: Sized,
695    {
696        self.intersection(other).is_empty()
697    }
698
699    /// Create a [`RangeSetBlaze`] from a [`SortedDisjoint`] iterator.
700    ///
701    /// *For more about constructors and performance, see [`RangeSetBlaze` Constructors](struct.RangeSetBlaze.html#rangesetblaze-constructors).*
702    ///
703    /// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
704    ///
705    /// # Examples
706    ///
707    /// ```
708    /// use range_set_blaze::prelude::*;
709    ///
710    /// let a0 = RangeSetBlaze::from_sorted_disjoint(CheckSortedDisjoint::new([-10..=-5, 1..=2]));
711    /// let a1: RangeSetBlaze<i32> = CheckSortedDisjoint::new([-10..=-5, 1..=2]).into_range_set_blaze();
712    /// assert!(a0 == a1 && a0.to_string() == "-10..=-5, 1..=2");
713    /// ```
714    fn into_range_set_blaze(self) -> RangeSetBlaze<T>
715    where
716        Self: Sized,
717    {
718        RangeSetBlaze::from_sorted_disjoint(self)
719    }
720}
721
722/// Gives the [`SortedDisjoint`] trait to any iterator of ranges. The iterator will panic
723/// if/when it finds that the ranges are not actually sorted and disjoint.
724///
725/// [SortedDisjoint]: crate::SortedDisjoint.html#table-of-contents
726///
727/// # Performance
728///
729/// All checking is done at runtime, but it should still be fast.
730///
731/// # Example
732///
733/// ```
734/// use range_set_blaze::prelude::*;
735///
736/// let a = CheckSortedDisjoint::new([1..=2, 5..=100]);
737/// let b = CheckSortedDisjoint::new([2..=6]);
738/// let union = a | b;
739/// assert_eq!(union.into_string(), "1..=100");
740/// ```
741///
742/// Here the ranges are not sorted and disjoint, so the iterator will panic.
743///```should_panic
744/// use range_set_blaze::prelude::*;
745///
746/// let a = CheckSortedDisjoint::new([1..=2, 5..=100]);
747/// let b = CheckSortedDisjoint::new([2..=6,-10..=-5]);
748/// let union = a | b;
749/// assert_eq!(union.into_string(), "1..=100");
750/// ```
751#[derive(Debug, Clone)]
752#[must_use = "iterators are lazy and do nothing unless consumed"]
753#[allow(clippy::module_name_repetitions)]
754pub struct CheckSortedDisjoint<T, I> {
755    pub(crate) iter: I,
756    prev_end: Option<T>,
757    seen_none: bool,
758}
759
760impl<T, I> CheckSortedDisjoint<T, I>
761where
762    T: Integer,
763    I: Iterator<Item = RangeInclusive<T>> + FusedIterator,
764{
765    /// Creates a new [`CheckSortedDisjoint`] from an iterator of ranges. See [`CheckSortedDisjoint`] for details and examples.
766    #[inline]
767    pub fn new<J: IntoIterator<IntoIter = I>>(iter: J) -> Self {
768        Self {
769            iter: iter.into_iter(),
770            prev_end: None,
771            seen_none: false,
772        }
773    }
774}
775
776impl<T: Integer> Default for CheckSortedDisjoint<T, array::IntoIter<RangeInclusive<T>, 0>> {
777    // Default is an empty iterator.
778    fn default() -> Self {
779        Self::new([])
780    }
781}
782
783impl<T, I> FusedIterator for CheckSortedDisjoint<T, I>
784where
785    T: Integer,
786    I: Iterator<Item = RangeInclusive<T>> + FusedIterator,
787{
788}
789
790impl<T, I> Iterator for CheckSortedDisjoint<T, I>
791where
792    T: Integer,
793    I: Iterator<Item = RangeInclusive<T>> + FusedIterator,
794{
795    type Item = RangeInclusive<T>;
796
797    fn next(&mut self) -> Option<Self::Item> {
798        let next = self.iter.next();
799
800        let Some(range) = next.as_ref() else {
801            self.seen_none = true;
802            return next;
803        };
804
805        assert!(
806            !self.seen_none,
807            "iterator cannot return Some after returning None"
808        );
809        let (start, end) = range.clone().into_inner();
810        assert!(start <= end, "start must be less or equal to end");
811        if let Some(prev_end) = self.prev_end {
812            assert!(
813                prev_end < T::max_value() && prev_end.add_one() < start,
814                "ranges must be disjoint"
815            );
816        }
817        self.prev_end = Some(end);
818
819        next
820    }
821
822    fn size_hint(&self) -> (usize, Option<usize>) {
823        self.iter.size_hint()
824    }
825}
826
827impl<T: Integer, const N: usize> From<[RangeInclusive<T>; N]>
828    for CheckSortedDisjoint<T, array::IntoIter<RangeInclusive<T>, N>>
829{
830    /// Deprecated: Use `new` instead.
831    fn from(arr: [RangeInclusive<T>; N]) -> Self {
832        Self::new(arr)
833    }
834}
835
836pub trait AnythingGoes<T: Integer>: Iterator<Item = RangeInclusive<T>> + FusedIterator {}
837impl<T: Integer, I> AnythingGoes<T> for I where I: Iterator<Item = RangeInclusive<T>> + FusedIterator
838{}
839
840/// `RangeOnce` is an iterator which emits a single `RangeInclusive` value before
841/// fusing.
842///
843/// `RangeOnce` is analogous to [`core::iter::Once`], but modified to treat an
844/// empty [`RangeInclusive`] as an empty [`Iterator`]. This allows `RangeOnce`
845/// to be safely used as a [`SortedDisjoint`] Iterator.
846///
847/// # Example
848///
849/// ```
850/// use range_set_blaze::{ RangeSetBlaze, RangeOnce };
851///
852/// let a = RangeOnce::new(0..=10);
853/// let b = RangeOnce::new(3..=2); // empty range
854/// let c = RangeOnce::new(5..=15);
855///
856/// let combined = RangeSetBlaze::from_sorted_disjoint(a | b | c);
857/// assert_eq!(combined.into_string(), "0..=15");
858/// ```
859pub struct RangeOnce<T>(option::IntoIter<RangeInclusive<T>>);
860
861impl<T: Integer> RangeOnce<T> {
862    /// Creates a new [`RangeOnce`] from a single range. See [`RangeOnce`] for details and examples.
863    pub fn new(range: RangeInclusive<T>) -> Self {
864        Self((!range.is_empty()).then_some(range).into_iter())
865    }
866}
867
868impl<T: Integer> From<RangeInclusive<T>> for RangeOnce<T> {
869    #[inline]
870    fn from(value: RangeInclusive<T>) -> Self {
871        Self::new(value)
872    }
873}
874
875impl<T: Integer> Iterator for RangeOnce<T> {
876    type Item = RangeInclusive<T>;
877
878    fn next(&mut self) -> Option<Self::Item> {
879        self.0.next()
880    }
881
882    fn size_hint(&self) -> (usize, Option<usize>) {
883        self.0.size_hint()
884    }
885}
886
887impl<T: Integer> DoubleEndedIterator for RangeOnce<T> {
888    fn next_back(&mut self) -> Option<Self::Item> {
889        self.0.next_back()
890    }
891}
892
893impl<T: Integer> ExactSizeIterator for RangeOnce<T> {
894    fn len(&self) -> usize {
895        self.0.len()
896    }
897}
898
899impl<T: Integer> FusedIterator for RangeOnce<T> {}
900
901macro_rules! impl_sorted_traits_and_ops {
902    ($IterType:ty, $($more_generics:tt)*) => {
903        #[allow(single_use_lifetimes)]
904        impl<$($more_generics)*, T: Integer> SortedStarts<T> for $IterType {}
905        #[allow(single_use_lifetimes)]
906        impl<$($more_generics)*, T: Integer> SortedDisjoint<T> for $IterType {}
907
908        #[allow(single_use_lifetimes)]
909        impl<$($more_generics)*, T: Integer> ops::Not for $IterType
910        {
911            type Output = NotIter<T, Self>;
912
913            fn not(self) -> Self::Output {
914                self.complement()
915            }
916        }
917
918        #[allow(single_use_lifetimes)]
919        impl<$($more_generics)*, T: Integer, R> ops::BitOr<R> for $IterType
920        where
921            R: SortedDisjoint<T>,
922        {
923            type Output = UnionMerge<T, Self, R>;
924
925            fn bitor(self, other: R) -> Self::Output {
926                SortedDisjoint::union(self, other)
927            }
928        }
929
930        #[allow(single_use_lifetimes)]
931        impl<$($more_generics)*, T: Integer, R> ops::Sub<R> for $IterType
932        where
933            R: SortedDisjoint<T>,
934        {
935            type Output = DifferenceMerge<T, Self, R>;
936
937            fn sub(self, other: R) -> Self::Output {
938                // It would be fun to optimize !!self.iter into self.iter
939                // but that would require also considering fields 'start_not' and 'next_time_return_none'.
940                SortedDisjoint::difference(self, other)
941            }
942        }
943
944        #[allow(single_use_lifetimes)]
945        impl<$($more_generics)*, T: Integer, R> ops::BitXor<R> for $IterType
946        where
947            R: SortedDisjoint<T>,
948        {
949            type Output = SymDiffMerge<T, Self, R>;
950
951            #[allow(clippy::suspicious_arithmetic_impl)]
952            fn bitxor(self, other: R) -> Self::Output {
953                SortedDisjoint::symmetric_difference(self, other)
954            }
955        }
956
957        #[allow(single_use_lifetimes)]
958        impl<$($more_generics)*, T: Integer, R> ops::BitAnd<R> for $IterType
959        where
960            R: SortedDisjoint<T>,
961        {
962            type Output = IntersectionMerge<T, Self, R>;
963
964            fn bitand(self, other: R) -> Self::Output {
965                SortedDisjoint::intersection(self, other)
966            }
967        }
968    };
969}
970
971//CheckList: Be sure that these are all tested in 'test_every_sorted_disjoint_method'
972impl_sorted_traits_and_ops!(CheckSortedDisjoint<T, I>, I: AnythingGoes<T>);
973impl_sorted_traits_and_ops!(DynSortedDisjoint<'a, T>, 'a);
974impl_sorted_traits_and_ops!(IntoRangesIter<T>, 'ignore);
975impl_sorted_traits_and_ops!(MapIntoRangesIter<T, V>, V: Eq + Clone);
976impl_sorted_traits_and_ops!(MapRangesIter<'a, T, V>, 'a, V: Eq + Clone);
977impl_sorted_traits_and_ops!(NotIter<T, I>, I: SortedDisjoint<T>);
978impl_sorted_traits_and_ops!(RangesIter<'a, T>, 'a);
979impl_sorted_traits_and_ops!(RangeValuesToRangesIter<T, VC, I>, VC: ValueCarrier, I: SortedDisjointMap<T, VC>);
980impl_sorted_traits_and_ops!(SymDiffIter<T, I>, I: SortedStarts<T>);
981impl_sorted_traits_and_ops!(UnionIter<T, I>, I: SortedStarts<T>);
982impl_sorted_traits_and_ops!(RangeOnce<T>, 'ignore);
983
984#[cfg(test)]
985mod tests {
986    use super::*;
987    use core::iter::{empty, once};
988
989    #[test]
990    fn test_union_std_iters() {
991        let a = empty::<RangeInclusive<u64>>();
992        #[allow(clippy::iter_skip_zero)]
993        let b = once(10u64..=20)
994            .skip_while(|_| false)
995            .take_while(|_| true)
996            //.step_by(1)
997            .fuse()
998            .skip(0)
999            .peekable();
1000        #[allow(clippy::iter_on_single_items)]
1001        let b = Some(b).into_iter().flat_map(|x| x.filter(|_| true));
1002        assert_eq!(Some(10u64..=20), a.union(b).next());
1003    }
1004}