range_set_blaze/dyn_sorted_disjoint_map.rs
1use core::{iter::FusedIterator, ops::RangeInclusive};
2
3use crate::{Integer, SortedDisjointMap, map::ValueRef};
4use alloc::boxed::Box;
5
6/// Gives [`SortedDisjointMap`] iterators a uniform type. Used by the [`union_map_dyn`], etc. macros to give all
7/// their input iterators the same type.
8///
9/// [`SortedDisjointMap`]: trait.SortedDisjointMap.html#table-of-contents
10/// [`union_map_dyn`]: crate::union_map_dyn
11/// [`intersection_map_dyn`]: crate::intersection_map_dyn
12///
13/// # Example
14/// ```
15/// use range_set_blaze::prelude::*;
16///
17/// let a = RangeMapBlaze::from_iter([(38..=42, "a")]);
18/// let b = CheckSortedDisjointMap::new([(5..=13, &"b"), (18..=29, &"b")]);
19/// let c = RangeMapBlaze::from_iter([(1..=6, "c"), (8..=9, "c"), (11..=15, "c")]);
20/// let union = [
21/// DynSortedDisjointMap::new(a.range_values()),
22/// DynSortedDisjointMap::new(b),
23/// DynSortedDisjointMap::new(c.range_values()),
24/// ].union();
25/// assert_eq!(union.into_string(), r#"(1..=6, "c"), (7..=7, "b"), (8..=9, "c"), (10..=10, "b"), (11..=15, "c"), (18..=29, "b"), (38..=42, "a")"#);
26/// ```
27#[must_use = "iterators are lazy and do nothing unless consumed"]
28pub struct DynSortedDisjointMap<'a, T, VR>
29where
30 T: Integer,
31 VR: ValueRef,
32{
33 iter: Box<dyn SortedDisjointMap<T, VR> + 'a>,
34}
35
36// Constructs a `DynSortedDisjointMap` encapsulating a `SortedDisjointMap` iterator.
37// The lifetime `'a` ensures that any references held by the iterator are valid
38// for the duration of the `DynSortedDisjointMap`'s existence. This is crucial for
39// preventing dangling references and ensuring memory safety when the iterator
40// contains references to data outside of itself.
41impl<'a, T, VR> DynSortedDisjointMap<'a, T, VR>
42where
43 T: Integer,
44 VR: ValueRef,
45{
46 /// Create a [`DynSortedDisjointMap`] from any [`SortedDisjointMap`] iterator. See [`DynSortedDisjointMap`] for an example.
47 ///
48 /// [`SortedDisjointMap`]: trait.SortedDisjointMap.html#table-of-contents
49 #[inline]
50 pub fn new<I>(iter: I) -> Self
51 where
52 I: SortedDisjointMap<T, VR> + 'a,
53 {
54 Self {
55 iter: Box::new(iter),
56 }
57 }
58}
59
60impl<T, VR> FusedIterator for DynSortedDisjointMap<'_, T, VR>
61where
62 T: Integer,
63 VR: ValueRef,
64{
65}
66
67impl<T, VR> Iterator for DynSortedDisjointMap<'_, T, VR>
68where
69 T: Integer,
70 VR: ValueRef,
71{
72 type Item = (RangeInclusive<T>, VR);
73
74 fn next(&mut self) -> Option<Self::Item> {
75 self.iter.next()
76 }
77
78 fn size_hint(&self) -> (usize, Option<usize>) {
79 self.iter.size_hint()
80 }
81}
82
83/// Intersects zero or more [`SortedDisjointMap`] iterators,
84/// creating a new [`SortedDisjointMap`] iterator.
85/// The input iterators need not be of the same type.
86///
87/// For input iterators of the same type, [`intersection`] may be slightly faster.
88///
89/// # Performance
90/// All work is done on demand, in one pass through the input iterators. Minimal memory is used.
91///
92/// [`SortedDisjointMap`]: crate::SortedDisjointMap.html#table-of-contents
93/// [`intersection`]: crate::MultiwaySortedDisjointMap::intersection
94/// # Examples
95///
96/// ```
97/// use range_set_blaze::prelude::*;
98///
99/// let a = RangeMapBlaze::from_iter([(2..=2, "a"), (6..=200, "a")]);
100/// let b = CheckSortedDisjointMap::new([(2..=6, &"b")]);
101/// let c = RangeMapBlaze::from_iter([(1..=2, "c"), (5..=100, "c")]);
102/// let intersection = intersection_map_dyn!(a.range_values(), b, c.range_values());
103/// assert_eq!(intersection.into_string(), r#"(2..=2, "c"), (6..=6, "c")"#);
104/// ```
105#[macro_export]
106macro_rules! intersection_map_dyn {
107 ($($val:expr),*) => {$crate::MultiwaySortedDisjointMap::intersection([$($crate::DynSortedDisjointMap::new($val)),*])}
108}
109
110/// Unions zero or more [`SortedDisjointMap`] iterators,
111/// creating a new [`SortedDisjointMap`] iterator.
112/// The input iterators need not be of the same type.
113///
114/// For input iterators of the same type, [`union`] may be slightly faster.
115///
116/// # Performance
117/// All work is done on demand, in one pass through the input iterators. Minimal memory is used.
118///
119/// [`SortedDisjointMap`]: crate::SortedDisjointMap.html#table-of-contents
120/// [`union`]: crate::MultiwaySortedDisjointMap::union
121/// # Examples
122///
123/// ```
124/// use range_set_blaze::prelude::*;
125///
126/// let a = RangeMapBlaze::from_iter([(2..=2, "a"), (6..=200, "a")]);
127/// let b = CheckSortedDisjointMap::new([(2..=6, &"b")]);
128/// let c = RangeMapBlaze::from_iter([(1..=2, "c"), (5..=100, "c")]);
129/// let union = union_map_dyn!(a.range_values(), b, c.range_values());
130/// assert_eq!(union.into_string(), r#"(1..=2, "c"), (3..=4, "b"), (5..=100, "c"), (101..=200, "a")"#);
131/// ```
132#[macro_export]
133macro_rules! union_map_dyn {
134 ($($val:expr),*) => {
135 $crate::MultiwaySortedDisjointMap::union([$($crate::DynSortedDisjointMap::new($val)),*])
136 }
137}
138
139/// Computes the symmetric difference of zero or more [`SortedDisjointMap`] iterators,
140/// creating a new [`SortedDisjointMap`] iterator.
141/// The input iterators need not be of the same type.
142///
143/// For input iterators of the same type, [`symmetric_difference`] may be slightly faster.
144///
145/// # Performance
146/// All work is done on demand, in one pass through the input iterators. Minimal memory is used.
147///
148/// [`SortedDisjointMap`]: crate::SortedDisjointMap.html#table-of-contents
149/// [`symmetric_difference`]: crate::MultiwaySortedDisjointMap::symmetric_difference
150/// # Examples
151///
152/// ```
153/// use range_set_blaze::prelude::*;
154///
155/// let a = RangeMapBlaze::from_iter([(2..=2, "a"), (6..=200, "a")]);
156/// let b = CheckSortedDisjointMap::new([(2..=6, &"b")]);
157/// let c = RangeMapBlaze::from_iter([(1..=2, "c"), (5..=100, "c")]);
158/// let sym_diff = symmetric_difference_map_dyn!(a.range_values(), b, c.range_values());
159/// assert_eq!(sym_diff.into_string(), r#"(1..=2, "c"), (3..=4, "b"), (6..=6, "c"), (101..=200, "a")"#);
160/// ```
161#[macro_export]
162macro_rules! symmetric_difference_map_dyn {
163 ($($val:expr),*) => {
164 $crate::MultiwaySortedDisjointMap::symmetric_difference([$($crate::DynSortedDisjointMap::new($val)),*])
165 }
166}