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}