Skip to main content

prefix_trie/joint/
set.rs

1//! JointPrefixSet, that is implemened as a simple binary tree, based on the
2//! [`super::JointPrefixMap`].
3
4use crate::PrefixSet;
5use crate::{AsView, TrieView};
6use either::{Left, Right};
7
8use super::{map::CoverKeys, JointPrefix};
9
10/// Set of prefixes, organized in a tree. This structure gives efficient access to the longest
11/// prefix in the set that contains another prefix.
12///
13/// Access the individual sets `self.t1` and `self.t2` to perform set operations (using
14/// [`crate::AsView`]).
15#[derive(Clone, Debug)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17#[cfg_attr(
18    feature = "serde",
19    serde(bound(
20        serialize = "P::P1: serde::Serialize, P::P2: serde::Serialize",
21        deserialize = "P::P1: serde::Deserialize<'de>, P::P2: serde::Deserialize<'de>",
22    ))
23)]
24pub struct JointPrefixSet<P: JointPrefix> {
25    /// PrefixSet that corresponds to the first prefix type
26    pub t1: PrefixSet<P::P1>,
27    /// PrefixSet that corresponds to the second prefix type
28    pub t2: PrefixSet<P::P2>,
29}
30
31impl<P: JointPrefix> JointPrefixSet<P> {
32    /// Create a new, empty prefixset.
33    pub fn new() -> Self {
34        Self {
35            t1: PrefixSet::new(),
36            t2: PrefixSet::new(),
37        }
38    }
39
40    /// Returns the number of elements stored in `self`.
41    ///
42    /// ```
43    /// # use prefix_trie::joint::*;
44    /// # #[cfg(feature = "ipnet")]
45    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
46    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::default();
47    /// set.insert("192.168.1.0/24".parse()?);
48    /// set.insert("192.168.1.0/25".parse()?);
49    /// set.insert("2001::1:0:0/96".parse()?);
50    /// # let set = set.clone();
51    /// assert_eq!(set.len(), 3);
52    /// # Ok(())
53    /// # }
54    /// # #[cfg(not(feature = "ipnet"))]
55    /// # fn main() {}
56    /// ```
57    #[inline(always)]
58    pub fn len(&self) -> usize {
59        self.t1.len() + self.t2.len()
60    }
61
62    /// Returns `true` if the set contains no elements.
63    ///
64    /// ```
65    /// # use prefix_trie::joint::*;
66    /// # #[cfg(feature = "ipnet")]
67    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
68    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
69    /// assert!(set.is_empty());
70    /// set.insert("2001::1:0:0/96".parse()?);
71    /// assert!(!set.is_empty());
72    /// # Ok(())
73    /// # }
74    /// # #[cfg(not(feature = "ipnet"))]
75    /// # fn main() {}
76    /// ```
77    #[inline(always)]
78    pub fn is_empty(&self) -> bool {
79        self.len() == 0
80    }
81
82    /// Check whether some prefix is present in the set, without using longest prefix match.
83    ///
84    /// ```
85    /// # use prefix_trie::joint::*;
86    /// # #[cfg(feature = "ipnet")]
87    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
88    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
89    /// set.insert("192.168.1.0/24".parse()?);
90    /// assert!(set.contains(&"192.168.1.0/24".parse()?));
91    /// assert!(!set.contains(&"192.168.2.0/24".parse()?));
92    /// assert!(!set.contains(&"192.168.0.0/23".parse()?));
93    /// assert!(!set.contains(&"192.168.1.128/25".parse()?));
94    /// assert!(!set.contains(&"c0a8:1::/24".parse()?));
95    /// # Ok(())
96    /// # }
97    /// # #[cfg(not(feature = "ipnet"))]
98    /// # fn main() {}
99    /// ```
100    pub fn contains(&self, prefix: &P) -> bool {
101        fork_ref!(self, prefix, contains)
102    }
103
104    /// Get the canonical reconstructed prefix by exact prefix matching.
105    ///
106    /// Prefixes are not stored verbatim. They are reconstructed from the trie position, so host
107    /// bits masked out by the prefix length are not preserved.
108    ///
109    /// ```
110    /// # use prefix_trie::joint::*;
111    /// # #[cfg(feature = "ipnet")]
112    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
113    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
114    /// set.insert("192.168.0.254/24".parse()?);
115    /// assert_eq!(set.get(&"192.168.0.0/24".parse()?), Some("192.168.0.0/24".parse()?));
116    /// # Ok(())
117    /// # }
118    /// # #[cfg(not(feature = "ipnet"))]
119    /// # fn main() {}
120    /// ```
121    pub fn get(&self, prefix: &P) -> Option<P> {
122        fork_ref!(self, prefix as P, get)
123    }
124
125    /// Get the longest prefix in the set that contains the given prefix.
126    ///
127    /// ```
128    /// # use prefix_trie::joint::*;
129    /// # #[cfg(feature = "ipnet")]
130    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
131    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
132    /// set.insert("192.168.1.0/24".parse()?);
133    /// set.insert("192.168.0.0/23".parse()?);
134    /// assert_eq!(set.get_lpm(&"192.168.1.1/32".parse()?), Some("192.168.1.0/24".parse()?));
135    /// assert_eq!(set.get_lpm(&"192.168.1.0/24".parse()?), Some("192.168.1.0/24".parse()?));
136    /// assert_eq!(set.get_lpm(&"192.168.0.0/24".parse()?), Some("192.168.0.0/23".parse()?));
137    /// assert_eq!(set.get_lpm(&"192.168.2.0/24".parse()?), None);
138    /// # Ok(())
139    /// # }
140    /// # #[cfg(not(feature = "ipnet"))]
141    /// # fn main() {}
142    /// ```
143    pub fn get_lpm(&self, prefix: &P) -> Option<P> {
144        fork_ref!(self, prefix as P, get_lpm)
145    }
146
147    /// Get the shortest prefix in the set that contains the given prefix.
148    ///
149    /// ```
150    /// # use prefix_trie::joint::*;
151    /// # #[cfg(feature = "ipnet")]
152    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
153    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
154    /// set.insert("192.168.1.0/24".parse()?);
155    /// set.insert("192.168.0.0/23".parse()?);
156    /// assert_eq!(set.get_spm(&"192.168.1.1/32".parse()?), Some("192.168.0.0/23".parse()?));
157    /// assert_eq!(set.get_spm(&"192.168.1.0/24".parse()?), Some("192.168.0.0/23".parse()?));
158    /// assert_eq!(set.get_spm(&"192.168.0.0/23".parse()?), Some("192.168.0.0/23".parse()?));
159    /// assert_eq!(set.get_spm(&"192.168.2.0/24".parse()?), None);
160    /// # Ok(())
161    /// # }
162    /// # #[cfg(not(feature = "ipnet"))]
163    /// # fn main() {}
164    /// ```
165    pub fn get_spm(&self, prefix: &P) -> Option<P> {
166        fork_ref!(self, prefix as P, get_spm)
167    }
168
169    /// Adds a value to the set.
170    ///
171    /// Returns whether the value was newly inserted. That is:
172    /// - If the set did not previously contain this value, `true` is returned.
173    /// - If the set already contained this value, `false` is returned.
174    ///
175    /// Prefixes are not stored verbatim. They are reconstructed from the trie position, so host
176    /// bits masked out by the prefix length are not preserved.
177    ///
178    /// ```
179    /// # use prefix_trie::joint::*;
180    /// # #[cfg(feature = "ipnet")]
181    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
182    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
183    /// assert!(set.insert("192.168.0.0/23".parse()?));
184    /// assert!(set.insert("192.168.1.0/24".parse()?));
185    /// assert!(!set.insert("192.168.1.0/24".parse()?));
186    /// # Ok(())
187    /// # }
188    /// # #[cfg(not(feature = "ipnet"))]
189    /// # fn main() {}
190    /// ```
191    pub fn insert(&mut self, prefix: P) -> bool {
192        fork!(self, prefix, insert)
193    }
194
195    /// Removes a value from the set. Returns whether the value was present in the set.
196    ///
197    /// ```
198    /// # use prefix_trie::joint::*;
199    /// # #[cfg(feature = "ipnet")]
200    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
201    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
202    /// let prefix = "192.168.1.0/24".parse()?;
203    /// set.insert(prefix);
204    /// assert!(set.contains(&prefix));
205    /// assert!(set.remove(&prefix));
206    /// assert!(!set.contains(&prefix));
207    /// # Ok(())
208    /// # }
209    /// # #[cfg(not(feature = "ipnet"))]
210    /// # fn main() {}
211    /// ```
212    pub fn remove(&mut self, prefix: &P) -> bool {
213        fork_ref!(self, prefix, remove)
214    }
215
216    /// Removes a prefix from the set, returning whether the prefix was present or not. In contrast
217    /// to [`Self::remove`], this operation only removes the stored value and may leave empty trie
218    /// nodes in place.
219    ///
220    /// ```
221    /// # use prefix_trie::joint::*;
222    /// # #[cfg(feature = "ipnet")]
223    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
224    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
225    /// let prefix = "192.168.1.0/24".parse()?;
226    /// set.insert(prefix);
227    /// assert!(set.contains(&prefix));
228    /// assert!(set.remove_keep_tree(&prefix));
229    /// assert!(!set.contains(&prefix));
230    /// # Ok(())
231    /// # }
232    /// # #[cfg(not(feature = "ipnet"))]
233    /// # fn main() {}
234    /// ```
235    pub fn remove_keep_tree(&mut self, prefix: &P) -> bool {
236        fork_ref!(self, prefix, remove_keep_tree)
237    }
238
239    /// Remove all elements that are contained within `prefix`. This will change the tree
240    /// structure. This operation is `O(n)`, as the entries must be freed up one-by-one.
241    ///
242    /// ```
243    /// # use prefix_trie::joint::*;
244    /// # #[cfg(feature = "ipnet")]
245    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
246    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
247    /// set.insert("192.168.0.0/22".parse()?);
248    /// set.insert("192.168.0.0/23".parse()?);
249    /// set.insert("192.168.0.0/24".parse()?);
250    /// set.insert("192.168.2.0/23".parse()?);
251    /// set.insert("192.168.2.0/24".parse()?);
252    /// set.insert("c0a8::/24".parse()?);
253    /// set.remove_children(&"192.168.0.0/23".parse()?);
254    /// assert!(!set.contains(&"192.168.0.0/23".parse()?));
255    /// assert!(!set.contains(&"192.168.0.0/24".parse()?));
256    /// assert!(set.contains(&"192.168.2.0/23".parse()?));
257    /// assert!(set.contains(&"192.168.2.0/24".parse()?));
258    /// assert!(set.contains(&"c0a8::/24".parse()?));
259    /// # Ok(())
260    /// # }
261    /// # #[cfg(not(feature = "ipnet"))]
262    /// # fn main() {}
263    /// ```
264    pub fn remove_children(&mut self, prefix: &P) {
265        fork_ref!(self, prefix, remove_children)
266    }
267
268    /// Clear the set but keep the allocated memory.
269    ///
270    /// ```
271    /// # use prefix_trie::joint::*;
272    /// # #[cfg(feature = "ipnet")]
273    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
274    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
275    /// set.insert("192.168.0.0/24".parse()?);
276    /// set.insert("192.168.1.0/24".parse()?);
277    /// set.insert("2001::1:0:0/96".parse()?);
278    /// set.clear();
279    /// assert!(!set.contains(&"192.168.0.0/24".parse()?));
280    /// assert!(!set.contains(&"192.168.1.0/24".parse()?));
281    /// assert!(!set.contains(&"2001::1:0:0/96".parse()?));
282    /// # Ok(())
283    /// # }
284    /// # #[cfg(not(feature = "ipnet"))]
285    /// # fn main() {}
286    /// ```
287    pub fn clear(&mut self) {
288        self.t1.clear();
289        self.t2.clear();
290    }
291
292    /// Iterate over all prefixes in the set. It iterates over the first, and then over the second
293    /// set.
294    ///
295    /// ```
296    /// # use prefix_trie::joint::*;
297    /// # #[cfg(feature = "ipnet")]
298    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
299    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
300    /// set.insert("192.168.1.0/24".parse()?);
301    /// set.insert("192.168.0.0/24".parse()?);
302    /// set.insert("2001::1:0:0/96".parse()?);
303    /// assert_eq!(
304    ///     set.iter().collect::<Vec<_>>(),
305    ///     vec![
306    ///         "192.168.0.0/24".parse()?,
307    ///         "192.168.1.0/24".parse()?,
308    ///         "2001::1:0:0/96".parse()?
309    ///     ],
310    /// );
311    /// # Ok(())
312    /// # }
313    /// # #[cfg(not(feature = "ipnet"))]
314    /// # fn main() {}
315    /// ```
316    pub fn iter(&self) -> Iter<'_, P> {
317        self.into_iter()
318    }
319
320    /// Return an iterator starting at the given prefix in lexicographic order. If `inclusive` is
321    /// `true`, the iterator includes `prefix` itself (if present); otherwise it starts just after
322    /// it. This is useful for cursor-based pagination over a [`JointPrefixSet`].
323    ///
324    /// ```
325    /// # use prefix_trie::joint::*;
326    /// # #[cfg(feature = "ipnet")]
327    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
328    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
329    /// set.insert("192.168.0.0/24".parse()?);
330    /// set.insert("192.168.1.0/24".parse()?);
331    /// set.insert("192.168.2.0/24".parse()?);
332    /// set.insert("2001::1:0:0/96".parse()?);
333    ///
334    /// // Get the next 2 entries after a cursor
335    /// let page: Vec<_> = set.iter_from(&"192.168.0.0/24".parse()?, false).take(2).collect();
336    /// assert_eq!(page, vec!["192.168.1.0/24".parse()?, "192.168.2.0/24".parse()?]);
337    ///
338    /// // Starting from an IPv6 prefix skips all IPv4 entries
339    /// let page: Vec<_> = set.iter_from(&"2001::1:0:0/96".parse()?, true).take(1).collect();
340    /// assert_eq!(page, vec!["2001::1:0:0/96".parse()?]);
341    /// # Ok(())
342    /// # }
343    /// # #[cfg(not(feature = "ipnet"))]
344    /// # fn main() {}
345    /// ```
346    pub fn iter_from<'a>(&'a self, prefix: &P, inclusive: bool) -> Iter<'a, P> {
347        Iter(match prefix.p1_or_p2_ref() {
348            Left(p1) => super::map::Iter {
349                i1: Some(self.t1.0.iter_from(p1, inclusive)),
350                i2: Some(self.t2.0.iter()),
351            },
352            Right(p2) => super::map::Iter {
353                i1: None,
354                i2: Some(self.t2.0.iter_from(p2, inclusive)),
355            },
356        })
357    }
358
359    /// Keep only the elements in the map that satisfy the given condition `f`.
360    ///
361    /// ```
362    /// # use prefix_trie::joint::*;
363    /// # #[cfg(feature = "ipnet")]
364    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
365    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
366    /// set.insert("192.168.0.0/24".parse()?);
367    /// set.insert("192.168.1.0/24".parse()?);
368    /// set.insert("192.168.2.0/24".parse()?);
369    /// set.insert("192.168.2.0/25".parse()?);
370    /// set.insert("2001::/24".parse()?);
371    /// set.insert("2001::/25".parse()?);
372    /// set.retain(|p| p.prefix_len() == 24);
373    /// assert!(set.contains(&"192.168.0.0/24".parse()?));
374    /// assert!(set.contains(&"192.168.1.0/24".parse()?));
375    /// assert!(set.contains(&"192.168.2.0/24".parse()?));
376    /// assert!(!set.contains(&"192.168.2.0/25".parse()?));
377    /// assert!(set.contains(&"2001::/24".parse()?));
378    /// assert!(!set.contains(&"2001::/25".parse()?));
379    /// # Ok(())
380    /// # }
381    /// # #[cfg(not(feature = "ipnet"))]
382    /// # fn main() {}
383    /// ```
384    pub fn retain<F>(&mut self, mut f: F)
385    where
386        F: FnMut(P) -> bool,
387    {
388        self.t1.retain(|p| f(P::from_p1(p)));
389        self.t2.retain(|p| f(P::from_p2(p)));
390    }
391
392    /// Get an iterator over the node itself and all children. All elements returned have a prefix
393    /// that is contained within `prefix` itself (or are the same). The iterator yields elements in
394    /// lexicographic order.
395    ///
396    /// **Info**: Use the [`crate::trieview::TrieView`] abstraction that provides more flexibility.
397    ///
398    /// ```
399    /// # use prefix_trie::joint::*;
400    /// # #[cfg(feature = "ipnet")]
401    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
402    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
403    /// set.insert("192.168.0.0/22".parse()?);
404    /// set.insert("192.168.0.0/23".parse()?);
405    /// set.insert("192.168.2.0/23".parse()?);
406    /// set.insert("192.168.0.0/24".parse()?);
407    /// set.insert("192.168.2.0/24".parse()?);
408    /// assert_eq!(
409    ///     set.children(&"192.168.0.0/23".parse()?).collect::<Vec<_>>(),
410    ///     vec![
411    ///         "192.168.0.0/23".parse()?,
412    ///         "192.168.0.0/24".parse()?,
413    ///     ]
414    /// );
415    /// # Ok(())
416    /// # }
417    /// # #[cfg(not(feature = "ipnet"))]
418    /// # fn main() {}
419    /// ```
420    pub fn children<'a>(&'a self, prefix: &P) -> Iter<'a, P> {
421        Iter(match prefix.p1_or_p2_ref() {
422            Left(p1) => super::map::Iter {
423                i1: Some(self.t1.0.children(p1)),
424                i2: None,
425            },
426            Right(p2) => super::map::Iter {
427                i1: None,
428                i2: Some(self.t2.0.children(p2)),
429            },
430        })
431    }
432
433    /// Iterate over all prefixes in the set that covers the given `prefix` (including `prefix`
434    /// itself if that is present in the set). The returned iterator yields reconstructed prefixes
435    /// `P`.
436    ///
437    /// The iterator will always yield elements ordered by their prefix length, i.e., their depth in
438    /// the tree.
439    ///
440    /// ```
441    /// # use prefix_trie::joint::*;
442    /// # #[cfg(feature = "ipnet")]
443    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
444    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
445    /// let p0 = "10.0.0.0/8".parse()?;
446    /// let p1 = "10.1.0.0/16".parse()?;
447    /// let p2 = "10.1.1.0/24".parse()?;
448    /// set.insert(p0);
449    /// set.insert(p1);
450    /// set.insert(p2);
451    /// set.insert("10.1.2.0/24".parse()?); // disjoint prefixes are not covered
452    /// set.insert("10.1.1.0/25".parse()?); // more specific prefixes are not covered
453    /// set.insert("11.0.0.0/8".parse()?);  // Branch points that don't contain values are skipped
454    /// assert_eq!(set.cover(&p2).collect::<Vec<_>>(), vec![p0, p1, p2]);
455    /// # Ok(())
456    /// # }
457    /// # #[cfg(not(feature = "ipnet"))]
458    /// # fn main() {}
459    /// ```
460    pub fn cover<'a>(&'a self, prefix: &P) -> CoverKeys<'a, P, ()> {
461        CoverKeys(match prefix.p1_or_p2_ref() {
462            Left(p1) => super::map::Cover::P1(self.t1.0.cover(p1)),
463            Right(p2) => super::map::Cover::P2(self.t2.0.cover(p2)),
464        })
465    }
466
467    /// Iterate over the union of two joint prefix sets. This is roughly equivalent to calling
468    /// `self.t1.view().union(&other.t1).chain(self.t2.view().union(&other.t2))`.
469    ///
470    /// If a prefix is present in both trees, the iterator will yield both elements. Otherwise, the
471    /// iterator will yield the element from the side where it is present. Elements are
472    /// reconstructed prefixes `P`.
473    ///
474    /// ```
475    /// # use prefix_trie::joint::*;
476    /// # use prefix_trie::joint::map::UnionItem;
477    /// # #[cfg(feature = "ipnet")]
478    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
479    ///
480    /// # #[cfg(feature = "ipnet")]
481    /// # {
482    /// let mut set_a: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
483    ///     net!("2001::1:0:0/96"),
484    ///     net!("192.168.0.0/22"),
485    ///     net!("192.168.0.0/24"),
486    /// ]);
487    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
488    ///     net!("192.168.0.0/22"),
489    ///     net!("192.168.0.0/23"),
490    /// ]);
491    /// assert_eq!(
492    ///     set_a.union(&set_b).collect::<Vec<_>>(),
493    ///     vec![
494    ///         net!("192.168.0.0/22"),
495    ///         net!("192.168.0.0/23"),
496    ///         net!("192.168.0.0/24"),
497    ///         net!("2001::1:0:0/96"),
498    ///     ]
499    /// );
500    /// # }
501    /// ```
502    pub fn union<'a>(&'a self, other: &'a JointPrefixSet<P>) -> Union<'a, P> {
503        Union(super::map::Union {
504            i1: Some(self.t1.view().union(&other.t1).into_iter()),
505            i2: Some(self.t2.view().union(&other.t2).into_iter()),
506        })
507    }
508
509    /// Iterate over the intersection of two joint prefix sets. This is roughly equivalent to
510    /// calling `self.t1.view().intersection(&other.t1).chain(self.t2.view().intersection(&other.t2))`.
511    ///
512    /// ```
513    /// # use prefix_trie::joint::*;
514    /// # #[cfg(feature = "ipnet")]
515    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
516    ///
517    /// # #[cfg(feature = "ipnet")]
518    /// # {
519    /// let mut set_a: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
520    ///     net!("192.168.0.0/20"),
521    ///     net!("192.168.0.0/22"),
522    ///     net!("192.168.0.0/24"),
523    ///     net!("192.168.2.0/23"),
524    ///     net!("2001::1:0:0/96"),
525    ///     net!("2001::1:0:0/97"),
526    /// ]);
527    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
528    ///     net!("192.168.0.0/20"),
529    ///     net!("192.168.0.0/22"),
530    ///     net!("192.168.0.0/23"),
531    ///     net!("192.168.0.0/24"),
532    ///     net!("192.168.2.0/24"),
533    ///     net!("2001::1:0:0/96"),
534    ///     net!("2001::0:0:0/97"),
535    /// ]);
536    /// assert_eq!(
537    ///     set_a.intersection(&set_b).collect::<Vec<_>>(),
538    ///     vec![
539    ///         net!("192.168.0.0/20"),
540    ///         net!("192.168.0.0/22"),
541    ///         net!("192.168.0.0/24"),
542    ///         net!("2001::1:0:0/96"),
543    ///     ]
544    /// );
545    /// # }
546    /// ```
547    pub fn intersection<'a>(&'a self, other: &'a JointPrefixSet<P>) -> Intersection<'a, P> {
548        Intersection(super::map::Intersection {
549            i1: self
550                .t1
551                .view()
552                .intersection(&other.t1)
553                .map(IntoIterator::into_iter),
554            i2: self
555                .t2
556                .view()
557                .intersection(&other.t2)
558                .map(IntoIterator::into_iter),
559        })
560    }
561
562    /// Iterate over the all elements in `self` that are not present in `other`.
563    ///
564    /// ```
565    /// # use prefix_trie::joint::*;
566    /// # #[cfg(feature = "ipnet")]
567    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
568    ///
569    /// # #[cfg(feature = "ipnet")]
570    /// # {
571    /// let mut set_a: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
572    ///     net!("192.168.0.0/20"),
573    ///     net!("192.168.0.0/22"),
574    ///     net!("192.168.0.0/24"),
575    ///     net!("192.168.2.0/23"),
576    ///     net!("2001::1:0:0/96"),
577    ///     net!("2001::1:0:0/97"),
578    /// ]);
579    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
580    ///     net!("192.168.0.0/20"),
581    ///     net!("192.168.0.0/22"),
582    ///     net!("192.168.0.0/23"),
583    ///     net!("192.168.2.0/24"),
584    ///     net!("2001::1:0:0/96"),
585    /// ]);
586    /// assert_eq!(
587    ///     set_a.difference(&set_b).collect::<Vec<_>>(),
588    ///     vec![
589    ///         (net!("192.168.0.0/24"), None),
590    ///         (net!("192.168.2.0/23"), None),
591    ///         (net!("2001::1:0:0/97"), None),
592    ///     ]
593    /// );
594    /// # }
595    /// ```
596    pub fn difference<'a>(&'a self, other: &'a JointPrefixSet<P>) -> Difference<'a, P> {
597        Difference(super::map::Difference {
598            i1: Some(self.t1.view().difference(&other.t1).into_iter()),
599            i2: Some(self.t2.view().difference(&other.t2).into_iter()),
600        })
601    }
602
603    /// Iterate over the all elements in `self` that are not covered by `other`.
604    ///
605    /// ```
606    /// # use prefix_trie::joint::*;
607    /// # #[cfg(feature = "ipnet")]
608    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
609    ///
610    /// # #[cfg(feature = "ipnet")]
611    /// # {
612    /// let mut set_a: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
613    ///     net!("192.168.0.0/20"),
614    ///     net!("192.168.0.0/22"),
615    ///     net!("192.168.0.0/24"),
616    ///     net!("192.168.2.0/23"),
617    ///     net!("2001::0:0:0/95"),
618    ///     net!("2001::1:0:0/96"),
619    ///     net!("2001::1:0:0/97"),
620    /// ]);
621    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
622    ///     net!("192.168.0.0/21"),
623    ///     net!("192.168.0.0/22"),
624    ///     net!("192.168.0.0/23"),
625    ///     net!("192.168.2.0/24"),
626    ///     net!("2001::1:0:0/96"),
627    /// ]);
628    /// assert_eq!(
629    ///     set_a.covering_difference(&set_b).collect::<Vec<_>>(),
630    ///     vec![net!("192.168.0.0/20"), net!("2001::0:0:0/95")]
631    /// );
632    /// # }
633    /// ```
634    pub fn covering_difference<'a>(
635        &'a self,
636        other: &'a JointPrefixSet<P>,
637    ) -> CoveringDifference<'a, P> {
638        CoveringDifference(super::map::CoveringDifference {
639            i1: Some(self.t1.view().covering_difference(&other.t1).into_iter()),
640            i2: Some(self.t2.view().covering_difference(&other.t2).into_iter()),
641        })
642    }
643}
644
645impl<P: JointPrefix> Default for JointPrefixSet<P> {
646    fn default() -> Self {
647        Self::new()
648    }
649}
650
651impl<P> PartialEq for JointPrefixSet<P>
652where
653    P: JointPrefix,
654{
655    /// Compare two prefix sets by their canonical reconstructed prefixes.
656    ///
657    /// ```
658    /// # use prefix_trie::joint::*;
659    /// # #[cfg(feature = "ipnet")]
660    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
661    /// let mut set1: JointPrefixSet<ipnet::IpNet> = ["10.0.0.0/8".parse()?].into_iter().collect();
662    /// let mut set2: JointPrefixSet<ipnet::IpNet> = ["10.0.0.1/8".parse()?].into_iter().collect();
663    /// assert_eq!(set1, set2);
664    /// # Ok(())
665    /// # }
666    /// # #[cfg(not(feature = "ipnet"))]
667    /// # fn main() {}
668    /// ```
669    fn eq(&self, other: &Self) -> bool {
670        self.t1 == other.t1 && self.t2 == other.t2
671    }
672}
673
674impl<P> Eq for JointPrefixSet<P> where P: JointPrefix {}
675
676/// An iterator over all entries of a [`JointPrefixSet`] in lexicographic order.
677pub struct Iter<'a, P: JointPrefix>(super::map::Iter<'a, P, ()>);
678
679impl<P: JointPrefix> Default for Iter<'_, P> {
680    /// The default iterator is empty.
681    ///
682    /// ```
683    /// use prefix_trie::joint;
684    /// # #[cfg(feature = "ipnet")]
685    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
686    /// assert_eq!(joint::set::Iter::<ipnet::IpNet>::default().count(), 0);
687    /// # Ok(())
688    /// # }
689    /// # #[cfg(not(feature = "ipnet"))]
690    /// # fn main() {}
691    /// ```
692    fn default() -> Self {
693        Self(Default::default())
694    }
695}
696
697impl<P: JointPrefix> Clone for Iter<'_, P> {
698    /// You can clone an iterator, which maintains its state.
699    ///
700    /// ```
701    /// # use prefix_trie::joint::*;
702    /// # #[cfg(feature = "ipnet")]
703    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
704    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
705    /// set.insert("2001::1:0:0/96".parse()?);
706    /// set.insert("192.168.0.0/22".parse()?);
707    /// set.insert("192.168.0.0/23".parse()?);
708    /// let mut iter = set.iter();
709    ///
710    /// assert_eq!(iter.next(), Some("192.168.0.0/22".parse()?));
711    ///
712    /// let clone = iter.clone();
713    /// assert_eq!(
714    ///     iter.collect::<Vec<_>>(),
715    ///     vec!["192.168.0.0/23".parse()?, "2001::1:0:0/96".parse()?]
716    /// );
717    /// assert_eq!(
718    ///     clone.collect::<Vec<_>>(),
719    ///     vec!["192.168.0.0/23".parse()?, "2001::1:0:0/96".parse()?]
720    /// );
721    /// # Ok(())
722    /// # }
723    /// # #[cfg(not(feature = "ipnet"))]
724    /// # fn main() {}
725    /// ```
726    fn clone(&self) -> Self {
727        Self(self.0.clone())
728    }
729}
730
731impl<P: JointPrefix> Iterator for Iter<'_, P> {
732    type Item = P;
733
734    fn next(&mut self) -> Option<Self::Item> {
735        self.0.next().map(|(p, _)| p)
736    }
737}
738
739#[derive(Clone)]
740/// A consuming iterator over all entries of a [`JointPrefixSet`] in lexicographic order.
741pub struct IntoIter<P: JointPrefix>(super::map::IntoIter<P, ()>);
742
743impl<P: JointPrefix> Iterator for IntoIter<P> {
744    type Item = P;
745
746    fn next(&mut self) -> Option<Self::Item> {
747        self.0.next().map(|(p, _)| p)
748    }
749}
750
751impl<P: JointPrefix> IntoIterator for JointPrefixSet<P> {
752    type Item = P;
753
754    type IntoIter = IntoIter<P>;
755
756    fn into_iter(self) -> Self::IntoIter {
757        IntoIter(super::map::IntoIter {
758            i1: Some(self.t1.0.into_iter()),
759            i2: Some(self.t2.0.into_iter()),
760        })
761    }
762}
763
764impl<'a, P: JointPrefix> IntoIterator for &'a JointPrefixSet<P> {
765    type Item = P;
766
767    type IntoIter = Iter<'a, P>;
768
769    fn into_iter(self) -> Self::IntoIter {
770        Iter(super::map::Iter {
771            i1: Some(self.t1.0.iter()),
772            i2: Some(self.t2.0.iter()),
773        })
774    }
775}
776
777impl<P: JointPrefix> FromIterator<P> for JointPrefixSet<P> {
778    fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> Self {
779        let mut set = Self::new();
780        for p in iter {
781            set.insert(p);
782        }
783        set
784    }
785}
786
787/// An iterator over the union of two [`JointPrefixSet`]s. The iterator yields first prefixes of
788/// `P1`, followed by those of `P2`.
789pub struct Union<'a, P: JointPrefix>(super::map::Union<'a, P, (), ()>);
790
791impl<P: JointPrefix> Iterator for Union<'_, P> {
792    type Item = P;
793
794    fn next(&mut self) -> Option<Self::Item> {
795        self.0.next().map(|x| x.into_prefix())
796    }
797}
798
799/// An iterator over the intersection of two [`JointPrefixSet`]s. The iterator yields first prefixes of
800/// `P1`, followed by those of `P2`.
801pub struct Intersection<'a, P: JointPrefix>(super::map::Intersection<'a, P, (), ()>);
802
803impl<P: JointPrefix> Iterator for Intersection<'_, P> {
804    type Item = P;
805
806    fn next(&mut self) -> Option<Self::Item> {
807        self.0.next().map(|(p, _, _)| p)
808    }
809}
810
811/// An iterator over the difference of two [`JointPrefixSet`]s. The iterator yields prefixes that
812/// are in `self`, but not in `other`. The iterator item type is `(P, Option<P>)`; plain
813/// difference currently yields `None` for the optional right-side prefix. The iterator yields first
814/// prefixes of `P1`, followed by those of `P2`.
815pub struct Difference<'a, P: JointPrefix>(super::map::Difference<'a, P, (), ()>);
816
817impl<P: JointPrefix> Iterator for Difference<'_, P> {
818    type Item = (P, Option<P>);
819
820    fn next(&mut self) -> Option<Self::Item> {
821        self.0.next().map(|x| (x.prefix, x.right.map(|(p, _)| p)))
822    }
823}
824
825/// An iterator over the covering difference of two [`JointPrefixSet`]s. The iterator yields
826/// prefixes that are in `self`, but not covered by any prefix in `other`. The iterator yields first
827/// prefixes of `P1`, followed by those of `P2`.
828pub struct CoveringDifference<'a, P: JointPrefix>(super::map::CoveringDifference<'a, P, (), ()>);
829
830impl<P: JointPrefix> Iterator for CoveringDifference<'_, P> {
831    type Item = P;
832
833    fn next(&mut self) -> Option<Self::Item> {
834        self.0.next().map(|(p, _)| p)
835    }
836}