Skip to main content

range_set_blaze/
sorted_disjoint.rs

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