range_set_blaze/
dyn_sorted_disjoint.rs

1use core::{iter::FusedIterator, ops::RangeInclusive};
2
3use crate::{Integer, SortedDisjoint};
4use alloc::boxed::Box;
5
6/// Gives [`SortedDisjoint`] iterators a uniform type. Used by the [`union_dyn`], etc. macros to give all
7/// their input iterators the same type.
8///
9/// [`SortedDisjoint`]: crate::SortedDisjoint.html#table-of-contents
10/// [`union_dyn`]: crate::union_dyn
11/// [`intersection_dyn`]: crate::intersection_dyn
12///
13/// # Example
14/// ```
15/// use range_set_blaze::prelude::*;
16///
17/// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
18/// let b = CheckSortedDisjoint::new([5..=13, 18..=29]);
19/// let c = RangeSetBlaze::from_iter([38..=42]);
20/// let union = [
21///     DynSortedDisjoint::new(a.ranges()),
22///     DynSortedDisjoint::new(b),
23///     DynSortedDisjoint::new(c.ranges()),
24/// ]
25/// .union();
26/// assert_eq!(union.into_string(), "1..=15, 18..=29, 38..=42");
27/// ```
28#[must_use = "iterators are lazy and do nothing unless consumed"]
29pub struct DynSortedDisjoint<'a, T: Integer> {
30    iter: Box<dyn SortedDisjoint<T> + 'a>,
31}
32
33impl<'a, T: Integer> DynSortedDisjoint<'a, T> {
34    /// Create a [`DynSortedDisjoint`] from any [`SortedDisjoint`] iterator. See [`DynSortedDisjoint`] for an example.
35    ///
36    /// [`SortedDisjoint`]: crate::SortedDisjoint.html#table-of-contents
37    #[inline]
38    pub fn new<I>(iter: I) -> Self
39    where
40        I: SortedDisjoint<T> + 'a,
41    {
42        Self {
43            iter: Box::new(iter),
44        }
45    }
46}
47
48impl<T: Integer> FusedIterator for DynSortedDisjoint<'_, T> {}
49
50impl<T: Integer> Iterator for DynSortedDisjoint<'_, T> {
51    type Item = RangeInclusive<T>;
52
53    fn next(&mut self) -> Option<Self::Item> {
54        self.iter.next()
55    }
56
57    fn size_hint(&self) -> (usize, Option<usize>) {
58        self.iter.size_hint()
59    }
60}
61
62/// Intersects zero or more [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
63/// The input iterators need not be of the same type.
64///
65/// For input iterators of the same type, [`intersection`] may be slightly faster.
66///
67/// # Performance
68///   All work is done on demand, in one pass through the input iterators. Minimal memory is used.
69///
70/// [`SortedDisjoint`]: crate::SortedDisjoint.html#table-of-contents
71/// [`intersection`]: crate::MultiwaySortedDisjoint::intersection
72/// # Examples
73/// ```
74/// use range_set_blaze::prelude::*;
75///
76/// let a = RangeSetBlaze::from_iter([1u8..=6, 8..=9, 11..=15]);
77/// let b = CheckSortedDisjoint::new([5..=13, 18..=29]);
78/// let c = RangeSetBlaze::from_iter([38..=42]);
79/// let not_c = !c.ranges();
80///
81/// let intersection = intersection_dyn!(a.ranges(), b, not_c);
82/// assert_eq!(intersection.into_string(), "5..=6, 8..=9, 11..=13");
83/// ```
84#[macro_export]
85macro_rules! intersection_dyn {
86    ($($val:expr),*) => {$crate::MultiwaySortedDisjoint::intersection([$($crate::DynSortedDisjoint::new($val)),*])}
87}
88
89/// Unions zero or more [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
90/// The input iterators need not be of the same type.
91///
92/// For input iterators of the same type, [`union`] may be slightly faster.
93///
94/// # Performance
95///   All work is done on demand, in one pass through the input iterators. Minimal memory is used.
96///
97/// [`SortedDisjoint`]: crate::SortedDisjoint.html#table-of-contents
98/// [`union`]: crate::MultiwaySortedDisjoint::union
99/// # Examples
100/// ```
101/// use range_set_blaze::prelude::*;
102///
103/// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
104/// let b = CheckSortedDisjoint::new([5..=13, 18..=29]);
105/// let c = RangeSetBlaze::from_iter([38..=42]);
106/// let union = union_dyn!(a.ranges(), b, c.ranges());
107/// assert_eq!(union.into_string(), "1..=15, 18..=29, 38..=42");
108/// ```
109#[macro_export]
110macro_rules! union_dyn {
111    ($($val:expr),*) => {
112                        $crate::MultiwaySortedDisjoint::union([$($crate::DynSortedDisjoint::new($val)),*])
113                        }
114}
115
116/// Computes the symmetric difference of zero or more [`SortedDisjoint`] iterators, creating a new [`SortedDisjoint`] iterator.
117/// The input iterators need not be of the same type.
118///
119/// For input iterators of the same type, [`symmetric_difference`] may be slightly faster.
120///
121/// # Performance
122///   All work is done on demand, in one pass through the input iterators. Minimal memory is used.
123///
124/// [`SortedDisjoint`]: crate::SortedDisjoint.html#table-of-contents
125/// [`symmetric_difference`]: crate::MultiwaySortedDisjoint::symmetric_difference
126/// # Examples
127/// ```
128/// use range_set_blaze::prelude::*;
129///
130/// let a = RangeSetBlaze::from_iter([1..=6, 8..=9, 11..=15]);
131/// let b = CheckSortedDisjoint::new([5..=13, 18..=29]);
132/// let c = RangeSetBlaze::from_iter([38..=42]);
133/// let sym_diff = symmetric_difference_dyn!(a.ranges(), b, c.ranges());
134/// assert_eq!(sym_diff.into_string(), "1..=4, 7..=7, 10..=10, 14..=15, 18..=29, 38..=42");
135/// ```
136#[macro_export]
137macro_rules! symmetric_difference_dyn {
138    ($($val:expr),*) => {
139                        $crate::MultiwaySortedDisjoint::symmetric_difference([$($crate::DynSortedDisjoint::new($val)),*])
140                        }
141}