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