prefix_trie/joint/map/
iter.rs

1//! Module that contains the implementation for the iterators
2
3use crate::joint::JointPrefix;
4
5use super::JointPrefixMap;
6
7/// An iterator over all entries of a [`JointPrefixMap`] in lexicographic order.
8pub struct Iter<'a, P: JointPrefix, T> {
9    pub(crate) i1: Option<crate::map::Iter<'a, P::P1, T>>,
10    pub(crate) i2: Option<crate::map::Iter<'a, P::P2, T>>,
11}
12
13impl<P: JointPrefix, T> Default for Iter<'_, P, T> {
14    /// The default iterator is empty.
15    ///
16    /// ```
17    /// use prefix_trie::joint;
18    /// # #[cfg(feature = "ipnet")]
19    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
20    /// assert_eq!(joint::map::Iter::<ipnet::IpNet, usize>::default().count(), 0);
21    /// # Ok(())
22    /// # }
23    /// # #[cfg(not(feature = "ipnet"))]
24    /// # fn main() {}
25    /// ```
26    fn default() -> Self {
27        Self { i1: None, i2: None }
28    }
29}
30
31impl<P: JointPrefix, T> Clone for Iter<'_, P, T> {
32    /// You can clone an iterator, which maintains its state.
33    ///
34    /// ```
35    /// # use prefix_trie::joint::*;
36    /// # #[cfg(feature = "ipnet")]
37    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
38    /// let mut pm: JointPrefixMap<ipnet::IpNet, _> = JointPrefixMap::new();
39    /// pm.insert("2001::1:0:0/96".parse()?, 1);
40    /// pm.insert("192.168.0.0/22".parse()?, 2);
41    /// pm.insert("192.168.0.0/23".parse()?, 3);
42    /// let mut iter = pm.iter();
43    ///
44    /// assert_eq!(iter.next(), Some(("192.168.0.0/22".parse()?, &2)));
45    ///
46    /// let clone = iter.clone();
47    /// assert_eq!(
48    ///     iter.collect::<Vec<_>>(),
49    ///     vec![
50    ///         ("192.168.0.0/23".parse()?, &3),
51    ///         ("2001::1:0:0/96".parse()?, &1),
52    ///     ]
53    /// );
54    /// assert_eq!(
55    ///     clone.collect::<Vec<_>>(),
56    ///     vec![
57    ///         ("192.168.0.0/23".parse()?, &3),
58    ///         ("2001::1:0:0/96".parse()?, &1),
59    ///     ]
60    /// );
61    /// # Ok(())
62    /// # }
63    /// # #[cfg(not(feature = "ipnet"))]
64    /// # fn main() {}
65    /// ```
66    fn clone(&self) -> Self {
67        Self {
68            i1: self.i1.clone(),
69            i2: self.i2.clone(),
70        }
71    }
72}
73
74impl<'a, P: JointPrefix, T> Iterator for Iter<'a, P, T> {
75    type Item = (P, &'a T);
76
77    fn next(&mut self) -> Option<(P, &'a T)> {
78        if let Some(i1) = self.i1.as_mut() {
79            if let Some((p, t)) = i1.next() {
80                return Some((P::from_p1(p), t));
81            }
82            // iterator 1 is empty
83            self.i1 = None;
84        }
85        if let Some(i2) = self.i2.as_mut() {
86            if let Some((p, t)) = i2.next() {
87                return Some((P::from_p2(p), t));
88            }
89            // iterator 1 is empty
90            self.i2 = None;
91        }
92        None
93    }
94}
95
96/// An iterator over all prefixes of a [`JointPrefixMap`] in lexicographic order.
97#[derive(Clone, Default)]
98pub struct Keys<'a, P: JointPrefix, T> {
99    pub(crate) inner: Iter<'a, P, T>,
100}
101
102impl<P: JointPrefix, T> Iterator for Keys<'_, P, T> {
103    type Item = P;
104
105    fn next(&mut self) -> Option<P> {
106        self.inner.next().map(|(k, _)| k)
107    }
108}
109
110/// An iterator over all values of a [`JointPrefixMap`] in lexicographic order of their associated
111/// prefixes.
112#[derive(Clone, Default)]
113pub struct Values<'a, P: JointPrefix, T> {
114    pub(crate) inner: Iter<'a, P, T>,
115}
116
117impl<'a, P: JointPrefix, T> Iterator for Values<'a, P, T> {
118    type Item = &'a T;
119
120    fn next(&mut self) -> Option<&'a T> {
121        self.inner.next().map(|(_, v)| v)
122    }
123}
124
125/// An iterator over all owned entries of a [`JointPrefixMap`] in lexicographic order.
126#[derive(Clone)]
127pub struct IntoIter<P: JointPrefix, T> {
128    pub(crate) i1: Option<crate::map::IntoIter<P::P1, T>>,
129    pub(crate) i2: Option<crate::map::IntoIter<P::P2, T>>,
130}
131
132impl<P: JointPrefix, T> Iterator for IntoIter<P, T> {
133    type Item = (P, T);
134
135    fn next(&mut self) -> Option<(P, T)> {
136        if let Some(i1) = self.i1.as_mut() {
137            if let Some((p, t)) = i1.next() {
138                return Some((P::from_p1(&p), t));
139            }
140            // iterator 1 is empty
141            self.i1 = None;
142        }
143        if let Some(i2) = self.i2.as_mut() {
144            if let Some((p, t)) = i2.next() {
145                return Some((P::from_p2(&p), t));
146            }
147            // iterator 1 is empty
148            self.i2 = None;
149        }
150        None
151    }
152}
153
154/// An iterator over all prefixes of a [`JointPrefixMap`] in lexicographic order.
155#[derive(Clone)]
156pub struct IntoKeys<P: JointPrefix, T> {
157    pub(crate) inner: IntoIter<P, T>,
158}
159
160impl<P: JointPrefix, T> Iterator for IntoKeys<P, T> {
161    type Item = P;
162
163    fn next(&mut self) -> Option<P> {
164        self.inner.next().map(|(k, _)| k)
165    }
166}
167
168/// An iterator over all values of a [`JointPrefixMap`] in lexicographic order of their associated
169/// prefix.
170#[derive(Clone)]
171pub struct IntoValues<P: JointPrefix, T> {
172    pub(crate) inner: IntoIter<P, T>,
173}
174
175impl<P: JointPrefix, T> Iterator for IntoValues<P, T> {
176    type Item = T;
177
178    fn next(&mut self) -> Option<T> {
179        self.inner.next().map(|(_, v)| v)
180    }
181}
182
183impl<P: JointPrefix, T> IntoIterator for JointPrefixMap<P, T> {
184    type Item = (P, T);
185
186    type IntoIter = IntoIter<P, T>;
187
188    fn into_iter(self) -> Self::IntoIter {
189        IntoIter {
190            i1: Some(self.t1.into_iter()),
191            i2: Some(self.t2.into_iter()),
192        }
193    }
194}
195
196impl<'a, P: JointPrefix, T> IntoIterator for &'a JointPrefixMap<P, T> {
197    type Item = (P, &'a T);
198
199    type IntoIter = Iter<'a, P, T>;
200
201    fn into_iter(self) -> Self::IntoIter {
202        Iter {
203            i1: Some(self.t1.iter()),
204            i2: Some(self.t2.iter()),
205        }
206    }
207}
208
209/// A mutable iterator over a [`JointPrefixMap`]. This iterator yields elements in lexicographic order of
210/// their associated prefix.
211pub struct IterMut<'a, P: JointPrefix, T> {
212    pub(super) i1: Option<crate::map::IterMut<'a, P::P1, T>>,
213    pub(super) i2: Option<crate::map::IterMut<'a, P::P2, T>>,
214}
215
216impl<P: JointPrefix, T> Default for IterMut<'_, P, T> {
217    /// The default iterator is empty.
218    ///
219    /// ```
220    /// use prefix_trie::joint;
221    /// # #[cfg(feature = "ipnet")]
222    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
223    /// assert_eq!(joint::map::IterMut::<ipnet::IpNet, usize>::default().count(), 0);
224    /// # Ok(())
225    /// # }
226    /// # #[cfg(not(feature = "ipnet"))]
227    /// # fn main() {}
228    /// ```
229    fn default() -> Self {
230        Self { i1: None, i2: None }
231    }
232}
233
234impl<'a, P: JointPrefix, T> Iterator for IterMut<'a, P, T> {
235    type Item = (P, &'a mut T);
236
237    fn next(&mut self) -> Option<Self::Item> {
238        if let Some(i1) = self.i1.as_mut() {
239            if let Some((p, t)) = i1.next() {
240                return Some((P::from_p1(p), t));
241            }
242            // iterator 1 is empty
243            self.i1 = None;
244        }
245        if let Some(i2) = self.i2.as_mut() {
246            if let Some((p, t)) = i2.next() {
247                return Some((P::from_p2(p), t));
248            }
249            // iterator 1 is empty
250            self.i2 = None;
251        }
252        None
253    }
254}
255
256/// A mutable iterator over values of [`JointPrefixMap`]. This iterator yields elements in
257/// lexicographic order.
258#[derive(Default)]
259pub struct ValuesMut<'a, P: JointPrefix, T> {
260    // # Safety
261    // You must ensure that there only ever exists one such iterator for each tree. You may create
262    // multiple such iterators for the same tree if you start with distinct starting nodes! This
263    // ensures that any one iteration will never yield elements of the other iterator.
264    pub(crate) inner: IterMut<'a, P, T>,
265}
266
267impl<'a, P: JointPrefix, T> Iterator for ValuesMut<'a, P, T> {
268    type Item = &'a mut T;
269
270    fn next(&mut self) -> Option<Self::Item> {
271        self.inner.next().map(|(_, v)| v)
272    }
273}
274
275impl<P: JointPrefix, T> FromIterator<(P, T)> for JointPrefixMap<P, T> {
276    fn from_iter<I: IntoIterator<Item = (P, T)>>(iter: I) -> Self {
277        let mut map = Self::new();
278        iter.into_iter().for_each(|(p, v)| {
279            map.insert(p, v);
280        });
281        map
282    }
283}
284
285/// An iterator that yields all items in a `JointPrefixMap` that covers a given prefix (including
286/// the prefix itself if preseint). See [`crate::joint::JointPrefixMap::cover`] for how to create
287/// this iterator.
288pub enum Cover<'a, 'p, P: JointPrefix, T> {
289    /// Cover of the first prefix variant
290    P1(crate::map::Cover<'a, 'p, P::P1, T>),
291    /// Cover of the second prefix variant
292    P2(crate::map::Cover<'a, 'p, P::P2, T>),
293}
294
295impl<'a, P: JointPrefix, T> Iterator for Cover<'a, '_, P, T> {
296    type Item = (P, &'a T);
297
298    fn next(&mut self) -> Option<Self::Item> {
299        match self {
300            Cover::P1(cover) => cover.next().map(|(p, t)| (P::from_p1(p), t)),
301            Cover::P2(cover) => cover.next().map(|(p, t)| (P::from_p2(p), t)),
302        }
303    }
304}
305
306/// An iterator that yields all keys (prefixes) in a `JointPrefixMap` that covers a given prefix
307/// (including the prefix itself if preseint). See [`crate::joint::JointPrefixMap::cover_keys`] for
308/// how to create this iterator.
309pub struct CoverKeys<'a, 'p, P: JointPrefix, T>(pub(crate) Cover<'a, 'p, P, T>);
310
311impl<P: JointPrefix, T> Iterator for CoverKeys<'_, '_, P, T> {
312    type Item = P;
313
314    fn next(&mut self) -> Option<Self::Item> {
315        self.0.next().map(|(p, _)| p)
316    }
317}
318
319/// An iterator that yields all values in a `JointPrefixMap` that covers a given prefix (including
320/// the prefix itself if preseint). See [`crate::joint::JointPrefixMap::cover_values`] for how to
321/// create this iterator.
322pub struct CoverValues<'a, 'p, P: JointPrefix, T>(pub(super) Cover<'a, 'p, P, T>);
323
324impl<'a, P: JointPrefix, T> Iterator for CoverValues<'a, '_, P, T> {
325    type Item = &'a T;
326
327    fn next(&mut self) -> Option<Self::Item> {
328        self.0.next().map(|(_, t)| t)
329    }
330}
331
332/// An iterator over the union of two [`JointPrefixMap`]s. The iterator yields first prefixes of
333/// `P1`, followed by those of `P2`.
334pub struct Union<'a, P: JointPrefix, L, R> {
335    pub(crate) i1: Option<crate::trieview::Union<'a, P::P1, L, R>>,
336    pub(crate) i2: Option<crate::trieview::Union<'a, P::P2, L, R>>,
337}
338
339impl<'a, P: JointPrefix, L, R> Iterator for Union<'a, P, L, R> {
340    type Item = UnionItem<'a, P, L, R>;
341
342    fn next(&mut self) -> Option<Self::Item> {
343        if let Some(i1) = self.i1.as_mut() {
344            if let Some(next) = i1.next() {
345                return Some(UnionItem::from_p1(next));
346            }
347            self.i1 = None;
348        }
349        if let Some(i2) = self.i2.as_mut() {
350            if let Some(next) = i2.next() {
351                return Some(UnionItem::from_p2(next));
352            }
353            self.i2 = None;
354        }
355        None
356    }
357}
358
359/// An item of the [`Union`] iterator (over a [`JointPrefixMap`]).
360#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
361
362pub enum UnionItem<'a, P, L, R> {
363    /// The prefix is only present in the left TrieView (`self`).
364    Left {
365        /// The prefix of the element.
366        prefix: P,
367        /// The value of the element in the left TrieView (`self`).
368        left: &'a L,
369        /// The longest prefix match in the right TrieView (`other`).
370        right: Option<(P, &'a R)>,
371    },
372
373    /// The prefix is only present in the right TrieView (`other`).
374    Right {
375        /// The prefix of the element.
376        prefix: P,
377        /// The longest prefix match in the left TrieView (`self`).
378        left: Option<(P, &'a L)>,
379        /// The value of the element in the right TrieView (`other`).
380        right: &'a R,
381    },
382
383    /// The prefix is only present in the right TrieView (`other`).
384    Both {
385        /// The prefix of the element.
386        prefix: P,
387        /// The value of the element in the left TrieView (`self`).
388        left: &'a L,
389        /// The value of the element in the right TrieView (`other`).
390        right: &'a R,
391    },
392}
393
394impl<'a, P, L, R> UnionItem<'a, P, L, R> {
395    /// Get the prefix of the current element (in the exact match).
396    ///
397    /// ```
398    /// # use prefix_trie::joint::*;
399    /// # use prefix_trie::joint::map::UnionItem;
400    /// # #[cfg(feature = "ipnet")]
401    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
402    ///
403    /// # #[cfg(feature = "ipnet")]
404    /// # {
405    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
406    ///     (net!("2001::1:0:0/96"), 1),
407    ///     (net!("192.168.0.0/22"), 2),
408    ///     (net!("192.168.0.0/24"), 3),
409    /// ]);
410    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
411    ///     (net!("192.168.0.0/22"), "a"),
412    ///     (net!("192.168.0.0/23"), "b"),
413    /// ]);
414    /// assert_eq!(
415    ///     map_a.union(&map_b).map(|x| *x.prefix()).collect::<Vec<_>>(),
416    ///     vec![
417    ///         net!("192.168.0.0/22"),
418    ///         net!("192.168.0.0/23"),
419    ///         net!("192.168.0.0/24"),
420    ///         net!("2001::1:0:0/96"),
421    ///     ]
422    /// );
423    /// # }
424    /// ```
425    pub fn prefix(&self) -> &P {
426        match self {
427            UnionItem::Left { prefix, .. }
428            | UnionItem::Right { prefix, .. }
429            | UnionItem::Both { prefix, .. } => prefix,
430        }
431    }
432
433    /// Get the prefix of the current element (in the exact match).
434    ///
435    /// ```
436    /// # use prefix_trie::joint::*;
437    /// # use prefix_trie::joint::map::UnionItem;
438    /// # #[cfg(feature = "ipnet")]
439    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
440    ///
441    /// # #[cfg(feature = "ipnet")]
442    /// # {
443    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
444    ///     (net!("2001::1:0:0/96"), 1),
445    ///     (net!("192.168.0.0/22"), 2),
446    ///     (net!("192.168.0.0/24"), 3),
447    /// ]);
448    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
449    ///     (net!("192.168.0.0/22"), "a"),
450    ///     (net!("192.168.0.0/23"), "b"),
451    /// ]);
452    /// assert_eq!(
453    ///     map_a.union(&map_b).map(|x| x.into_prefix()).collect::<Vec<_>>(),
454    ///     vec![
455    ///         net!("192.168.0.0/22"),
456    ///         net!("192.168.0.0/23"),
457    ///         net!("192.168.0.0/24"),
458    ///         net!("2001::1:0:0/96"),
459    ///     ]
460    /// );
461    /// # }
462    /// ```
463    pub fn into_prefix(self) -> P {
464        match self {
465            UnionItem::Left { prefix, .. }
466            | UnionItem::Right { prefix, .. }
467            | UnionItem::Both { prefix, .. } => prefix,
468        }
469    }
470
471    /// Get the element in both the left and right map, but only if they are both present. By
472    /// doing `a.union(b).filter_map(|x| x.both)`, you get an iterator that yields only elements
473    /// that are present in both tries.
474    ///
475    /// ```
476    /// # use prefix_trie::joint::*;
477    /// # use prefix_trie::joint::map::UnionItem;
478    /// # #[cfg(feature = "ipnet")]
479    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
480    ///
481    /// # #[cfg(feature = "ipnet")]
482    /// # {
483    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
484    ///     (net!("2001::1:0:0/96"), 1),
485    ///     (net!("192.168.0.0/22"), 2),
486    ///     (net!("192.168.0.0/24"), 3),
487    /// ]);
488    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
489    ///     (net!("192.168.0.0/22"), "a"),
490    ///     (net!("192.168.0.0/23"), "b"),
491    /// ]);
492    /// assert_eq!(
493    ///     map_a
494    ///         .union(&map_b)
495    ///         .filter_map(|x| x.both().map(|(p, l, r)| (*p, l, r)))
496    ///         .collect::<Vec<_>>(),
497    ///     vec![(net!("192.168.0.0/22"), &2, &"a")]
498    /// );
499    /// # }
500    /// ```
501    pub fn both(&self) -> Option<(&P, &'a L, &'a R)> {
502        match self {
503            UnionItem::Left { .. } | UnionItem::Right { .. } => None,
504            UnionItem::Both {
505                prefix,
506                left,
507                right,
508            } => Some((prefix, left, right)),
509        }
510    }
511
512    /// Get the element in both the left and right map, but only if they are both present. By
513    /// doing `a.union(b).filter_map(|x| x.both)`, you get an iterator that yields only elements
514    /// that are present in both tries.
515    ///
516    /// ```
517    /// # use prefix_trie::joint::*;
518    /// # use prefix_trie::joint::map::UnionItem;
519    /// # #[cfg(feature = "ipnet")]
520    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
521    ///
522    /// # #[cfg(feature = "ipnet")]
523    /// # {
524    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
525    ///     (net!("2001::1:0:0/96"), 1),
526    ///     (net!("192.168.0.0/22"), 2),
527    ///     (net!("192.168.0.0/24"), 3),
528    /// ]);
529    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
530    ///     (net!("192.168.0.0/22"), "a"),
531    ///     (net!("192.168.0.0/23"), "b"),
532    /// ]);
533    /// assert_eq!(
534    ///     map_a.union(&map_b).filter_map(|x| x.into_both()).collect::<Vec<_>>(),
535    ///     vec![(net!("192.168.0.0/22"), &2, &"a")]
536    /// );
537    /// # }
538    /// ```
539    pub fn into_both(self) -> Option<(P, &'a L, &'a R)> {
540        match self {
541            UnionItem::Left { .. } | UnionItem::Right { .. } => None,
542            UnionItem::Both {
543                prefix,
544                left,
545                right,
546            } => Some((prefix, left, right)),
547        }
548    }
549
550    /// Get the value of the left item (`self`). This either returns the exact match or the
551    /// longest-prefix match.
552    ///
553    /// ```
554    /// # use prefix_trie::joint::*;
555    /// # use prefix_trie::joint::map::UnionItem;
556    /// # #[cfg(feature = "ipnet")]
557    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
558    ///
559    /// # #[cfg(feature = "ipnet")]
560    /// # {
561    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
562    ///     (net!("2001::1:0:0/96"), 1),
563    ///     (net!("192.168.0.0/22"), 2),
564    ///     (net!("192.168.0.0/24"), 3),
565    /// ]);
566    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
567    ///     (net!("192.168.0.0/22"), "a"),
568    ///     (net!("192.168.0.0/23"), "b"),
569    /// ]);
570    /// assert_eq!(
571    ///     map_a
572    ///         .union(&map_b)
573    ///         .map(|x| x.left().map(|(p, l)| (*p, l)))
574    ///         .collect::<Vec<_>>(),
575    ///     vec![
576    ///         Some((net!("192.168.0.0/22"), &2)),
577    ///         Some((net!("192.168.0.0/22"), &2)),
578    ///         Some((net!("192.168.0.0/24"), &3)),
579    ///         Some((net!("2001::1:0:0/96"), &1)),
580    ///     ]
581    /// );
582    /// # }
583    /// ```
584    pub fn left(&self) -> Option<(&P, &'a L)> {
585        match self {
586            UnionItem::Right { left, .. } => left.as_ref().map(|(p, l)| (p, *l)),
587            UnionItem::Left { prefix, left, .. } | UnionItem::Both { prefix, left, .. } => {
588                Some((prefix, left))
589            }
590        }
591    }
592
593    /// Get the value of the left item (`self`). This either returns the exact match or the
594    /// longest-prefix match.
595    ///
596    /// ```
597    /// # use prefix_trie::joint::*;
598    /// # use prefix_trie::joint::map::UnionItem;
599    /// # #[cfg(feature = "ipnet")]
600    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
601    ///
602    /// # #[cfg(feature = "ipnet")]
603    /// # {
604    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
605    ///     (net!("2001::1:0:0/96"), 1),
606    ///     (net!("2001::2:0:0/96"), 2),
607    ///     (net!("2001::2:0:0/98"), 3),
608    /// ]);
609    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
610    ///     (net!("2001::2:0:0/96"), "a"),
611    ///     (net!("2001::2:0:0/97"), "b"),
612    /// ]);
613    /// assert_eq!(
614    ///     map_a.union(&map_b).map(|x| x.into_left()).collect::<Vec<_>>(),
615    ///     vec![
616    ///         Some((net!("2001::1:0:0/96"), &1)),
617    ///         Some((net!("2001::2:0:0/96"), &2)),
618    ///         Some((net!("2001::2:0:0/96"), &2)),
619    ///         Some((net!("2001::2:0:0/98"), &3)),
620    ///     ]
621    /// );
622    /// # }
623    /// ```
624    pub fn into_left(self) -> Option<(P, &'a L)> {
625        match self {
626            UnionItem::Right { left, .. } => left,
627            UnionItem::Left { prefix, left, .. } | UnionItem::Both { prefix, left, .. } => {
628                Some((prefix, left))
629            }
630        }
631    }
632
633    /// Get the value of the right item (`other`). This either returns the exact match or the
634    /// longest-prefix match.
635    ///
636    /// ```
637    /// # use prefix_trie::joint::*;
638    /// # use prefix_trie::joint::map::UnionItem;
639    /// # #[cfg(feature = "ipnet")]
640    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
641    ///
642    /// # #[cfg(feature = "ipnet")]
643    /// # {
644    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
645    ///     (net!("2001::1:0:0/96"), 1),
646    ///     (net!("192.168.0.0/22"), 2),
647    ///     (net!("192.168.0.0/24"), 3),
648    /// ]);
649    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
650    ///     (net!("192.168.0.0/22"), "a"),
651    ///     (net!("192.168.0.0/23"), "b"),
652    /// ]);
653    /// assert_eq!(
654    ///     map_a
655    ///         .union(&map_b)
656    ///         .map(|x| x.right().map(|(p, r)| (*p, r)))
657    ///         .collect::<Vec<_>>(),
658    ///     vec![
659    ///         Some((net!("192.168.0.0/22"), &"a")),
660    ///         Some((net!("192.168.0.0/23"), &"b")),
661    ///         Some((net!("192.168.0.0/23"), &"b")),
662    ///         None,
663    ///     ]
664    /// );
665    /// # }
666    /// ```
667    pub fn right(&self) -> Option<(&P, &'a R)> {
668        match self {
669            UnionItem::Left { right, .. } => right.as_ref().map(|(p, r)| (p, *r)),
670            UnionItem::Right { prefix, right, .. } | UnionItem::Both { prefix, right, .. } => {
671                Some((prefix, right))
672            }
673        }
674    }
675
676    /// Get the value of the right item (`other`). This either returns the exact match or the
677    /// longest-prefix match.
678    ///
679    /// ```
680    /// # use prefix_trie::joint::*;
681    /// # use prefix_trie::joint::map::UnionItem;
682    /// # #[cfg(feature = "ipnet")]
683    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
684    ///
685    /// # #[cfg(feature = "ipnet")]
686    /// # {
687    /// let mut map_a: JointPrefixMap<ipnet::IpNet, usize> = JointPrefixMap::from_iter([
688    ///     (net!("2001::1:0:0/96"), 1),
689    ///     (net!("2001::2:0:0/96"), 2),
690    ///     (net!("2001::2:0:0/98"), 3),
691    /// ]);
692    /// let mut map_b: JointPrefixMap<ipnet::IpNet, &'static str> = JointPrefixMap::from_iter([
693    ///     (net!("2001::2:0:0/96"), "a"),
694    ///     (net!("2001::2:0:0/97"), "b"),
695    /// ]);
696    /// assert_eq!(
697    ///     map_a.union(&map_b).map(|x| x.into_right()).collect::<Vec<_>>(),
698    ///     vec![
699    ///         None,
700    ///         Some((net!("2001::2:0:0/96"), &"a")),
701    ///         Some((net!("2001::2:0:0/97"), &"b")),
702    ///         Some((net!("2001::2:0:0/97"), &"b")),
703    ///     ]
704    /// );
705    /// # }
706    /// ```
707    pub fn into_right(self) -> Option<(P, &'a R)> {
708        match self {
709            UnionItem::Left { right, .. } => right,
710            UnionItem::Right { prefix, right, .. } | UnionItem::Both { prefix, right, .. } => {
711                Some((prefix, right))
712            }
713        }
714    }
715}
716
717impl<'a, P: JointPrefix, L, R> UnionItem<'a, P, L, R> {
718    fn from_p1(value: crate::trieview::UnionItem<'a, P::P1, L, R>) -> Self {
719        match value {
720            crate::trieview::UnionItem::Left {
721                prefix,
722                left,
723                right,
724            } => UnionItem::Left {
725                prefix: P::from_p1(prefix),
726                left,
727                right: right.map(|(p, r)| (P::from_p1(p), r)),
728            },
729            crate::trieview::UnionItem::Right {
730                prefix,
731                left,
732                right,
733            } => UnionItem::Right {
734                prefix: P::from_p1(prefix),
735                left: left.map(|(p, l)| (P::from_p1(p), l)),
736                right,
737            },
738            crate::trieview::UnionItem::Both {
739                prefix,
740                left,
741                right,
742            } => UnionItem::Both {
743                prefix: P::from_p1(prefix),
744                left,
745                right,
746            },
747        }
748    }
749
750    fn from_p2(value: crate::trieview::UnionItem<'a, P::P2, L, R>) -> Self {
751        match value {
752            crate::trieview::UnionItem::Left {
753                prefix,
754                left,
755                right,
756            } => UnionItem::Left {
757                prefix: P::from_p2(prefix),
758                left,
759                right: right.map(|(p, r)| (P::from_p2(p), r)),
760            },
761            crate::trieview::UnionItem::Right {
762                prefix,
763                left,
764                right,
765            } => UnionItem::Right {
766                prefix: P::from_p2(prefix),
767                left: left.map(|(p, l)| (P::from_p2(p), l)),
768                right,
769            },
770            crate::trieview::UnionItem::Both {
771                prefix,
772                left,
773                right,
774            } => UnionItem::Both {
775                prefix: P::from_p2(prefix),
776                left,
777                right,
778            },
779        }
780    }
781}
782
783/// An iterator over the intersection of two [`JointPrefixMap`]s. The iterator yields first prefixes
784/// of `P1`, followed by those of `P2`.
785pub struct Intersection<'a, P: JointPrefix, L, R> {
786    pub(crate) i1: Option<crate::trieview::Intersection<'a, P::P1, L, R>>,
787    pub(crate) i2: Option<crate::trieview::Intersection<'a, P::P2, L, R>>,
788}
789
790impl<'a, P: JointPrefix, L, R> Iterator for Intersection<'a, P, L, R> {
791    type Item = (P, &'a L, &'a R);
792
793    fn next(&mut self) -> Option<Self::Item> {
794        if let Some(i1) = self.i1.as_mut() {
795            if let Some((p, l, r)) = i1.next() {
796                return Some((P::from_p1(p), l, r));
797            }
798            self.i1 = None;
799        }
800        if let Some(i2) = self.i2.as_mut() {
801            if let Some((p, l, r)) = i2.next() {
802                return Some((P::from_p2(p), l, r));
803            }
804            self.i2 = None;
805        }
806        None
807    }
808}
809
810/// An iterator over the difference of two [`JointPrefixMap`]s, i.e., prefixes that are in `self`
811/// but not in `other`. The iterator yields first prefixes of `P1`, followed by those of `P2`.
812pub struct Difference<'a, P: JointPrefix, L, R> {
813    pub(crate) i1: Option<crate::trieview::Difference<'a, P::P1, L, R>>,
814    pub(crate) i2: Option<crate::trieview::Difference<'a, P::P2, L, R>>,
815}
816
817impl<'a, P: JointPrefix, L, R> Iterator for Difference<'a, P, L, R> {
818    type Item = DifferenceItem<'a, P, L, R>;
819
820    fn next(&mut self) -> Option<Self::Item> {
821        if let Some(i1) = self.i1.as_mut() {
822            if let Some(next) = i1.next() {
823                return Some(DifferenceItem::from_p1(next));
824            }
825            self.i1 = None;
826        }
827        if let Some(i2) = self.i2.as_mut() {
828            if let Some(next) = i2.next() {
829                return Some(DifferenceItem::from_p2(next));
830            }
831            self.i2 = None;
832        }
833        None
834    }
835}
836
837/// An iterator over the covering difference of two [`JointPrefixMap`]s, i.e., prefixes of `self` that
838/// are not covered by `other`. The iterator yields first prefixes of `P1`, followed by those of
839/// `P2`.
840pub struct CoveringDifference<'a, P: JointPrefix, L, R> {
841    pub(crate) i1: Option<crate::trieview::CoveringDifference<'a, P::P1, L, R>>,
842    pub(crate) i2: Option<crate::trieview::CoveringDifference<'a, P::P2, L, R>>,
843}
844
845impl<'a, P: JointPrefix, L, R> Iterator for CoveringDifference<'a, P, L, R> {
846    type Item = (P, &'a L);
847
848    fn next(&mut self) -> Option<Self::Item> {
849        if let Some(i1) = self.i1.as_mut() {
850            if let Some((p, l)) = i1.next() {
851                return Some((P::from_p1(p), l));
852            }
853            self.i1 = None;
854        }
855        if let Some(i2) = self.i2.as_mut() {
856            if let Some((p, l)) = i2.next() {
857                return Some((P::from_p2(p), l));
858            }
859            self.i2 = None;
860        }
861        None
862    }
863}
864
865/// An item of the [`Difference`] iterator.
866#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
867pub struct DifferenceItem<'a, P, L, R> {
868    /// The prefix that is present in `self` but not in `other`.
869    pub prefix: P,
870    /// The value stored in `self`.
871    pub value: &'a L,
872    /// The longest-prefix-match that is present in `other`.
873    pub right: Option<(P, &'a R)>,
874}
875
876impl<'a, P: JointPrefix, L, R> DifferenceItem<'a, P, L, R> {
877    fn from_p1(value: crate::trieview::DifferenceItem<'a, P::P1, L, R>) -> Self {
878        Self {
879            prefix: P::from_p1(value.prefix),
880            value: value.value,
881            right: value.right.map(|(p, r)| (P::from_p1(p), r)),
882        }
883    }
884
885    fn from_p2(value: crate::trieview::DifferenceItem<'a, P::P2, L, R>) -> Self {
886        Self {
887            prefix: P::from_p2(value.prefix),
888            value: value.value,
889            right: value.right.map(|(p, r)| (P::from_p2(p), r)),
890        }
891    }
892}