prefix_trie/joint/
set.rs

1//! JointPrefixSet, that is implemened as a simple binary tree, based on the
2//! [`super::JointPrefixMap`].
3
4use crate::AsView;
5use crate::PrefixSet;
6use either::{Left, Right};
7
8use super::{map::CoverKeys, JointPrefix};
9
10/// Set of prefixes, organized in a tree. This strucutre 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 wether 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 a reference to the stored prefix. This function allows you to retrieve the host part of
105    /// the prefix. The returned prefix will always have the same network address and prefix length.
106    ///
107    /// ```
108    /// # use prefix_trie::joint::*;
109    /// # #[cfg(feature = "ipnet")]
110    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
111    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
112    /// set.insert("192.168.0.254/24".parse()?);
113    /// assert_eq!(set.get(&"192.168.0.0/24".parse()?), Some("192.168.0.254/24".parse()?));
114    /// # Ok(())
115    /// # }
116    /// # #[cfg(not(feature = "ipnet"))]
117    /// # fn main() {}
118    /// ```
119    pub fn get(&self, prefix: &P) -> Option<P> {
120        fork_ref!(self, prefix as P, get)
121    }
122
123    /// Get the longest prefix in the set that contains the given preifx.
124    ///
125    /// ```
126    /// # use prefix_trie::joint::*;
127    /// # #[cfg(feature = "ipnet")]
128    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
129    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
130    /// set.insert("192.168.1.0/24".parse()?);
131    /// set.insert("192.168.0.0/23".parse()?);
132    /// assert_eq!(set.get_lpm(&"192.168.1.1/32".parse()?), Some("192.168.1.0/24".parse()?));
133    /// assert_eq!(set.get_lpm(&"192.168.1.0/24".parse()?), Some("192.168.1.0/24".parse()?));
134    /// assert_eq!(set.get_lpm(&"192.168.0.0/24".parse()?), Some("192.168.0.0/23".parse()?));
135    /// assert_eq!(set.get_lpm(&"192.168.2.0/24".parse()?), None);
136    /// # Ok(())
137    /// # }
138    /// # #[cfg(not(feature = "ipnet"))]
139    /// # fn main() {}
140    /// ```
141    pub fn get_lpm(&self, prefix: &P) -> Option<P> {
142        fork_ref!(self, prefix as P, get_lpm)
143    }
144
145    /// Get the shortest prefix in the set that contains the given preifx.
146    ///
147    /// ```
148    /// # use prefix_trie::joint::*;
149    /// # #[cfg(feature = "ipnet")]
150    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
151    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
152    /// set.insert("192.168.1.0/24".parse()?);
153    /// set.insert("192.168.0.0/23".parse()?);
154    /// assert_eq!(set.get_spm(&"192.168.1.1/32".parse()?), Some("192.168.0.0/23".parse()?));
155    /// assert_eq!(set.get_spm(&"192.168.1.0/24".parse()?), Some("192.168.0.0/23".parse()?));
156    /// assert_eq!(set.get_spm(&"192.168.0.0/23".parse()?), Some("192.168.0.0/23".parse()?));
157    /// assert_eq!(set.get_spm(&"192.168.2.0/24".parse()?), None);
158    /// # Ok(())
159    /// # }
160    /// # #[cfg(not(feature = "ipnet"))]
161    /// # fn main() {}
162    /// ```
163    pub fn get_spm(&self, prefix: &P) -> Option<P> {
164        fork_ref!(self, prefix as P, get_spm)
165    }
166
167    /// Adds a value to the set.
168    ///
169    /// Returns whether the value was newly inserted. That is:
170    /// - If the set did not previously contain this value, `true` is returned.
171    /// - If the set already contained this value, `false` is returned.
172    ///
173    /// This operation will always replace the currently stored prefix. This allows you to store
174    /// additional information in the host aprt of the prefix.
175    ///
176    /// ```
177    /// # use prefix_trie::joint::*;
178    /// # #[cfg(feature = "ipnet")]
179    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
180    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
181    /// assert!(set.insert("192.168.0.0/23".parse()?));
182    /// assert!(set.insert("192.168.1.0/24".parse()?));
183    /// assert!(!set.insert("192.168.1.0/24".parse()?));
184    /// # Ok(())
185    /// # }
186    /// # #[cfg(not(feature = "ipnet"))]
187    /// # fn main() {}
188    /// ```
189    pub fn insert(&mut self, prefix: P) -> bool {
190        fork!(self, prefix, insert)
191    }
192
193    /// Removes a value from the set. Returns whether the value was present in the set.
194    ///
195    /// ```
196    /// # use prefix_trie::joint::*;
197    /// # #[cfg(feature = "ipnet")]
198    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
199    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
200    /// let prefix = "192.168.1.0/24".parse()?;
201    /// set.insert(prefix);
202    /// assert!(set.contains(&prefix));
203    /// assert!(set.remove(&prefix));
204    /// assert!(!set.contains(&prefix));
205    /// # Ok(())
206    /// # }
207    /// # #[cfg(not(feature = "ipnet"))]
208    /// # fn main() {}
209    /// ```
210    pub fn remove(&mut self, prefix: &P) -> bool {
211        fork_ref!(self, prefix, remove)
212    }
213
214    /// Removes a prefix from the set, returning wether the prefix was present or not. In contrast
215    /// to [`Self::remove`], his operation will keep the tree structure as is, but only remove the
216    /// element from it. This allows any future `insert` on the same prefix to be faster. However
217    /// future reads from the tree might be a bit slower because they need to traverse more nodes.
218    ///
219    /// ```
220    /// # use prefix_trie::joint::*;
221    /// # #[cfg(feature = "ipnet")]
222    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
223    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
224    /// let prefix = "192.168.1.0/24".parse()?;
225    /// set.insert(prefix);
226    /// assert!(set.contains(&prefix));
227    /// assert!(set.remove_keep_tree(&prefix));
228    /// assert!(!set.contains(&prefix));
229    ///
230    /// // future inserts of the same key are now faster!
231    /// set.insert(prefix);
232    /// # Ok(())
233    /// # }
234    /// # #[cfg(not(feature = "ipnet"))]
235    /// # fn main() {}
236    /// ```
237    pub fn remove_keep_tree(&mut self, prefix: &P) -> bool {
238        fork_ref!(self, prefix, remove_keep_tree)
239    }
240
241    /// Remove all elements that are contained within `prefix`. This will change the tree
242    /// structure. This operation is `O(n)`, as the entries must be freed up one-by-one.
243    ///
244    /// ```
245    /// # use prefix_trie::joint::*;
246    /// # #[cfg(feature = "ipnet")]
247    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
248    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
249    /// set.insert("192.168.0.0/22".parse()?);
250    /// set.insert("192.168.0.0/23".parse()?);
251    /// set.insert("192.168.0.0/24".parse()?);
252    /// set.insert("192.168.2.0/23".parse()?);
253    /// set.insert("192.168.2.0/24".parse()?);
254    /// set.insert("c0a8::/24".parse()?);
255    /// set.remove_children(&"192.168.0.0/23".parse()?);
256    /// assert!(!set.contains(&"192.168.0.0/23".parse()?));
257    /// assert!(!set.contains(&"192.168.0.0/24".parse()?));
258    /// assert!(set.contains(&"192.168.2.0/23".parse()?));
259    /// assert!(set.contains(&"192.168.2.0/24".parse()?));
260    /// assert!(set.contains(&"c0a8::/24".parse()?));
261    /// # Ok(())
262    /// # }
263    /// # #[cfg(not(feature = "ipnet"))]
264    /// # fn main() {}
265    /// ```
266    pub fn remove_children(&mut self, prefix: &P) {
267        fork_ref!(self, prefix, remove_children)
268    }
269
270    /// Clear the set but keep the allocated memory.
271    ///
272    /// ```
273    /// # use prefix_trie::joint::*;
274    /// # #[cfg(feature = "ipnet")]
275    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
276    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
277    /// set.insert("192.168.0.0/24".parse()?);
278    /// set.insert("192.168.1.0/24".parse()?);
279    /// set.insert("2001::1:0:0/96".parse()?);
280    /// set.clear();
281    /// assert!(!set.contains(&"192.168.0.0/24".parse()?));
282    /// assert!(!set.contains(&"192.168.1.0/24".parse()?));
283    /// assert!(!set.contains(&"2001::1:0:0/96".parse()?));
284    /// # Ok(())
285    /// # }
286    /// # #[cfg(not(feature = "ipnet"))]
287    /// # fn main() {}
288    /// ```
289    pub fn clear(&mut self) {
290        self.t1.clear();
291        self.t2.clear();
292    }
293
294    /// Iterate over all prefixes in the set. It iterates over the first, and then over the second
295    /// set.
296    ///
297    /// ```
298    /// # use prefix_trie::joint::*;
299    /// # #[cfg(feature = "ipnet")]
300    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
301    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
302    /// set.insert("192.168.1.0/24".parse()?);
303    /// set.insert("192.168.0.0/24".parse()?);
304    /// set.insert("2001::1:0:0/96".parse()?);
305    /// assert_eq!(
306    ///     set.iter().collect::<Vec<_>>(),
307    ///     vec![
308    ///         "192.168.0.0/24".parse()?,
309    ///         "192.168.1.0/24".parse()?,
310    ///         "2001::1:0:0/96".parse()?
311    ///     ],
312    /// );
313    /// # Ok(())
314    /// # }
315    /// # #[cfg(not(feature = "ipnet"))]
316    /// # fn main() {}
317    /// ```
318    pub fn iter(&self) -> Iter<'_, P> {
319        self.into_iter()
320    }
321
322    /// Keep only the elements in the map that satisfy the given condition `f`.
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("192.168.2.0/25".parse()?);
333    /// set.insert("2001::/24".parse()?);
334    /// set.insert("2001::/25".parse()?);
335    /// set.retain(|p| p.prefix_len() == 24);
336    /// assert!(set.contains(&"192.168.0.0/24".parse()?));
337    /// assert!(set.contains(&"192.168.1.0/24".parse()?));
338    /// assert!(set.contains(&"192.168.2.0/24".parse()?));
339    /// assert!(!set.contains(&"192.168.2.0/25".parse()?));
340    /// assert!(set.contains(&"2001::/24".parse()?));
341    /// assert!(!set.contains(&"2001::/25".parse()?));
342    /// # Ok(())
343    /// # }
344    /// # #[cfg(not(feature = "ipnet"))]
345    /// # fn main() {}
346    /// ```
347    pub fn retain<F>(&mut self, mut f: F)
348    where
349        F: FnMut(P) -> bool,
350    {
351        self.t1.retain(|p| f(P::from_p1(p)));
352        self.t2.retain(|p| f(P::from_p2(p)));
353    }
354
355    /// Get an iterator over the node itself and all children. All elements returned have a prefix
356    /// that is contained within `prefix` itself (or are the same). The iterator yields elements in
357    /// lexicographic order.
358    ///
359    /// **Info**: Use the [`crate::trieview::TrieView`] abstraction that provides more flexibility.
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/22".parse()?);
367    /// set.insert("192.168.0.0/23".parse()?);
368    /// set.insert("192.168.2.0/23".parse()?);
369    /// set.insert("192.168.0.0/24".parse()?);
370    /// set.insert("192.168.2.0/24".parse()?);
371    /// assert_eq!(
372    ///     set.children(&"192.168.0.0/23".parse()?).collect::<Vec<_>>(),
373    ///     vec![
374    ///         "192.168.0.0/23".parse()?,
375    ///         "192.168.0.0/24".parse()?,
376    ///     ]
377    /// );
378    /// # Ok(())
379    /// # }
380    /// # #[cfg(not(feature = "ipnet"))]
381    /// # fn main() {}
382    /// ```
383    pub fn children<'a>(&'a self, prefix: &P) -> Iter<'a, P> {
384        Iter(match prefix.p1_or_p2_ref() {
385            Left(p1) => super::map::Iter {
386                i1: Some(self.t1.0.children(p1)),
387                i2: None,
388            },
389            Right(p2) => super::map::Iter {
390                i1: None,
391                i2: Some(self.t2.0.children(p2)),
392            },
393        })
394    }
395
396    /// Iterate over all prefixes in the set that covers the given `prefix` (including `prefix`
397    /// itself if that is present in the set). The returned iterator yields `&'a P`.
398    ///
399    /// The iterator will always yield elements ordered by their prefix length, i.e., their depth in
400    /// the tree.
401    ///
402    /// ```
403    /// # use prefix_trie::joint::*;
404    /// # #[cfg(feature = "ipnet")]
405    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
406    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
407    /// let p0 = "10.0.0.0/8".parse()?;
408    /// let p1 = "10.1.0.0/16".parse()?;
409    /// let p2 = "10.1.1.0/24".parse()?;
410    /// set.insert(p0);
411    /// set.insert(p1);
412    /// set.insert(p2);
413    /// set.insert("10.1.2.0/24".parse()?); // disjoint prefixes are not covered
414    /// set.insert("10.1.1.0/25".parse()?); // more specific prefixes are not covered
415    /// set.insert("11.0.0.0/8".parse()?);  // Branch points that don't contain values are skipped
416    /// assert_eq!(set.cover(&p2).collect::<Vec<_>>(), vec![p0, p1, p2]);
417    /// # Ok(())
418    /// # }
419    /// # #[cfg(not(feature = "ipnet"))]
420    /// # fn main() {}
421    /// ```
422    pub fn cover<'a, 'p>(&'a self, prefix: &'p P) -> CoverKeys<'a, 'p, P, ()> {
423        CoverKeys(match prefix.p1_or_p2_ref() {
424            Left(p1) => super::map::Cover::P1(self.t1.0.cover(p1)),
425            Right(p2) => super::map::Cover::P2(self.t2.0.cover(p2)),
426        })
427    }
428
429    /// Iterate over the union of two joint prefix sets. This is roughly equivalent to calling
430    /// `self.t1.view().union(&other.t1).chain(self.t2.view().union(&other.t2))`.
431    ///
432    /// If a prefix is present in both trees, the iterator will yield both elements. Otherwise, the
433    /// iterator will yield the element of one map together with the longest prefix match in
434    /// the other map. Elements are of type `P`.
435    ///
436    /// ```
437    /// # use prefix_trie::joint::*;
438    /// # use prefix_trie::joint::map::UnionItem;
439    /// # #[cfg(feature = "ipnet")]
440    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
441    ///
442    /// # #[cfg(feature = "ipnet")]
443    /// # {
444    /// let mut set_a: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
445    ///     net!("2001::1:0:0/96"),
446    ///     net!("192.168.0.0/22"),
447    ///     net!("192.168.0.0/24"),
448    /// ]);
449    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
450    ///     net!("192.168.0.0/22"),
451    ///     net!("192.168.0.0/23"),
452    /// ]);
453    /// assert_eq!(
454    ///     set_a.union(&set_b).collect::<Vec<_>>(),
455    ///     vec![
456    ///         net!("192.168.0.0/22"),
457    ///         net!("192.168.0.0/23"),
458    ///         net!("192.168.0.0/24"),
459    ///         net!("2001::1:0:0/96"),
460    ///     ]
461    /// );
462    /// # }
463    /// ```
464    pub fn union<'a>(&'a self, other: &'a JointPrefixSet<P>) -> Union<'a, P> {
465        Union(super::map::Union {
466            i1: Some(self.t1.view().union(&other.t1)),
467            i2: Some(self.t2.view().union(&other.t2)),
468        })
469    }
470
471    /// Iterate over the intersection of two joint prefix sets. This is roughly equivalent to
472    /// calling `self.t1.view().intersection(&other.t1).chain(self.t2.view().intersection(&other.t2))`.
473    ///
474    /// ```
475    /// # use prefix_trie::joint::*;
476    /// # #[cfg(feature = "ipnet")]
477    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
478    ///
479    /// # #[cfg(feature = "ipnet")]
480    /// # {
481    /// let mut set_a: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
482    ///     net!("192.168.0.0/20"),
483    ///     net!("192.168.0.0/22"),
484    ///     net!("192.168.0.0/24"),
485    ///     net!("192.168.2.0/23"),
486    ///     net!("2001::1:0:0/96"),
487    ///     net!("2001::1:0:0/97"),
488    /// ]);
489    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
490    ///     net!("192.168.0.0/20"),
491    ///     net!("192.168.0.0/22"),
492    ///     net!("192.168.0.0/23"),
493    ///     net!("192.168.0.0/24"),
494    ///     net!("192.168.2.0/24"),
495    ///     net!("2001::1:0:0/96"),
496    ///     net!("2001::0:0:0/97"),
497    /// ]);
498    /// assert_eq!(
499    ///     set_a.intersection(&set_b).collect::<Vec<_>>(),
500    ///     vec![
501    ///         net!("192.168.0.0/20"),
502    ///         net!("192.168.0.0/22"),
503    ///         net!("192.168.0.0/24"),
504    ///         net!("2001::1:0:0/96"),
505    ///     ]
506    /// );
507    /// # }
508    /// ```
509    pub fn intersection<'a>(&'a self, other: &'a JointPrefixSet<P>) -> Intersection<'a, P> {
510        Intersection(super::map::Intersection {
511            i1: Some(self.t1.view().intersection(&other.t1)),
512            i2: Some(self.t2.view().intersection(&other.t2)),
513        })
514    }
515
516    /// Iterate over the all elements in `self` that are not present in `other`. Each item will
517    /// return a reference to the prefix and value in `self`, as well as the longest prefix match of
518    /// `other`.
519    ///
520    /// ```
521    /// # use prefix_trie::joint::*;
522    /// # #[cfg(feature = "ipnet")]
523    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
524    ///
525    /// # #[cfg(feature = "ipnet")]
526    /// # {
527    /// let mut set_a: 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/24"),
531    ///     net!("192.168.2.0/23"),
532    ///     net!("2001::1:0:0/96"),
533    ///     net!("2001::1:0:0/97"),
534    /// ]);
535    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
536    ///     net!("192.168.0.0/20"),
537    ///     net!("192.168.0.0/22"),
538    ///     net!("192.168.0.0/23"),
539    ///     net!("192.168.2.0/24"),
540    ///     net!("2001::1:0:0/96"),
541    /// ]);
542    /// assert_eq!(
543    ///     set_a.difference(&set_b).collect::<Vec<_>>(),
544    ///     vec![
545    ///         (net!("192.168.0.0/24"), Some(net!("192.168.0.0/23"))),
546    ///         (net!("192.168.2.0/23"), Some(net!("192.168.0.0/22"))),
547    ///         (net!("2001::1:0:0/97"), Some(net!("2001::1:0:0/96"))),
548    ///     ]
549    /// );
550    /// # }
551    /// ```
552    pub fn difference<'a>(&'a self, other: &'a JointPrefixSet<P>) -> Difference<'a, P> {
553        Difference(super::map::Difference {
554            i1: Some(self.t1.view().difference(&other.t1)),
555            i2: Some(self.t2.view().difference(&other.t2)),
556        })
557    }
558
559    /// Iterate over the all elements in `self` that are not covered by `other`.
560    ///
561    /// ```
562    /// # use prefix_trie::joint::*;
563    /// # #[cfg(feature = "ipnet")]
564    /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::IpNet>().unwrap()}; }
565    ///
566    /// # #[cfg(feature = "ipnet")]
567    /// # {
568    /// let mut set_a: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
569    ///     net!("192.168.0.0/20"),
570    ///     net!("192.168.0.0/22"),
571    ///     net!("192.168.0.0/24"),
572    ///     net!("192.168.2.0/23"),
573    ///     net!("2001::0:0:0/95"),
574    ///     net!("2001::1:0:0/96"),
575    ///     net!("2001::1:0:0/97"),
576    /// ]);
577    /// let mut set_b: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::from_iter([
578    ///     net!("192.168.0.0/21"),
579    ///     net!("192.168.0.0/22"),
580    ///     net!("192.168.0.0/23"),
581    ///     net!("192.168.2.0/24"),
582    ///     net!("2001::1:0:0/96"),
583    /// ]);
584    /// assert_eq!(
585    ///     set_a.covering_difference(&set_b).collect::<Vec<_>>(),
586    ///     vec![net!("192.168.0.0/20"), net!("2001::0:0:0/95")]
587    /// );
588    /// # }
589    /// ```
590    pub fn covering_difference<'a>(
591        &'a self,
592        other: &'a JointPrefixSet<P>,
593    ) -> CoveringDifference<'a, P> {
594        CoveringDifference(super::map::CoveringDifference {
595            i1: Some(self.t1.view().covering_difference(&other.t1)),
596            i2: Some(self.t2.view().covering_difference(&other.t2)),
597        })
598    }
599}
600
601impl<P: JointPrefix> Default for JointPrefixSet<P> {
602    fn default() -> Self {
603        Self::new()
604    }
605}
606
607impl<P> PartialEq for JointPrefixSet<P>
608where
609    P: JointPrefix + PartialEq,
610{
611    /// Compare two prefix sets to contain the same prefixes. This also compares the host-part of
612    /// the prefix:
613    ///
614    /// ```
615    /// # use prefix_trie::joint::*;
616    /// # #[cfg(feature = "ipnet")]
617    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
618    /// let mut set1: JointPrefixSet<ipnet::IpNet> = ["10.0.0.0/8".parse()?].into_iter().collect();
619    /// let mut set2: JointPrefixSet<ipnet::IpNet> = ["10.0.0.1/8".parse()?].into_iter().collect();
620    /// assert_ne!(set1, set2);
621    /// # Ok(())
622    /// # }
623    /// # #[cfg(not(feature = "ipnet"))]
624    /// # fn main() {}
625    /// ```
626    fn eq(&self, other: &Self) -> bool {
627        self.iter().zip(other.iter()).all(|(a, b)| a == b)
628    }
629}
630
631impl<P> Eq for JointPrefixSet<P> where P: JointPrefix + Eq {}
632
633/// An iterator over all entries of a [`JointPrefixSet`] in lexicographic order.
634pub struct Iter<'a, P: JointPrefix>(super::map::Iter<'a, P, ()>);
635
636impl<P: JointPrefix> Default for Iter<'_, P> {
637    /// The default iterator is empty.
638    ///
639    /// ```
640    /// use prefix_trie::joint;
641    /// # #[cfg(feature = "ipnet")]
642    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
643    /// assert_eq!(joint::set::Iter::<ipnet::IpNet>::default().count(), 0);
644    /// # Ok(())
645    /// # }
646    /// # #[cfg(not(feature = "ipnet"))]
647    /// # fn main() {}
648    /// ```
649    fn default() -> Self {
650        Self(Default::default())
651    }
652}
653
654impl<P: JointPrefix> Clone for Iter<'_, P> {
655    /// You can clone an iterator, which maintains its state.
656    ///
657    /// ```
658    /// # use prefix_trie::joint::*;
659    /// # #[cfg(feature = "ipnet")]
660    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
661    /// let mut set: JointPrefixSet<ipnet::IpNet> = JointPrefixSet::new();
662    /// set.insert("2001::1:0:0/96".parse()?);
663    /// set.insert("192.168.0.0/22".parse()?);
664    /// set.insert("192.168.0.0/23".parse()?);
665    /// let mut iter = set.iter();
666    ///
667    /// assert_eq!(iter.next(), Some("192.168.0.0/22".parse()?));
668    ///
669    /// let clone = iter.clone();
670    /// assert_eq!(
671    ///     iter.collect::<Vec<_>>(),
672    ///     vec!["192.168.0.0/23".parse()?, "2001::1:0:0/96".parse()?]
673    /// );
674    /// assert_eq!(
675    ///     clone.collect::<Vec<_>>(),
676    ///     vec!["192.168.0.0/23".parse()?, "2001::1:0:0/96".parse()?]
677    /// );
678    /// # Ok(())
679    /// # }
680    /// # #[cfg(not(feature = "ipnet"))]
681    /// # fn main() {}
682    /// ```
683    fn clone(&self) -> Self {
684        Self(self.0.clone())
685    }
686}
687
688impl<P: JointPrefix> Iterator for Iter<'_, P> {
689    type Item = P;
690
691    fn next(&mut self) -> Option<Self::Item> {
692        self.0.next().map(|(p, _)| p)
693    }
694}
695
696#[derive(Clone)]
697/// A consuming iterator over all entries of a [`JointPrefixSet`] in lexicographic order.
698pub struct IntoIter<P: JointPrefix>(super::map::IntoIter<P, ()>);
699
700impl<P: JointPrefix> Iterator for IntoIter<P> {
701    type Item = P;
702
703    fn next(&mut self) -> Option<Self::Item> {
704        self.0.next().map(|(p, _)| p)
705    }
706}
707
708impl<P: JointPrefix> IntoIterator for JointPrefixSet<P> {
709    type Item = P;
710
711    type IntoIter = IntoIter<P>;
712
713    fn into_iter(self) -> Self::IntoIter {
714        IntoIter(super::map::IntoIter {
715            i1: Some(self.t1.0.into_iter()),
716            i2: Some(self.t2.0.into_iter()),
717        })
718    }
719}
720
721impl<'a, P: JointPrefix> IntoIterator for &'a JointPrefixSet<P> {
722    type Item = P;
723
724    type IntoIter = Iter<'a, P>;
725
726    fn into_iter(self) -> Self::IntoIter {
727        Iter(super::map::Iter {
728            i1: Some(self.t1.0.iter()),
729            i2: Some(self.t2.0.iter()),
730        })
731    }
732}
733
734impl<P: JointPrefix> FromIterator<P> for JointPrefixSet<P> {
735    fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> Self {
736        let mut set = Self::new();
737        for p in iter {
738            set.insert(p);
739        }
740        set
741    }
742}
743
744/// An iterator over the union of two [`JointPrefixSet`]s. The iterator yields first prefixes of
745/// `P1`, followed by those of `P2`.
746pub struct Union<'a, P: JointPrefix>(super::map::Union<'a, P, (), ()>);
747
748impl<P: JointPrefix> Iterator for Union<'_, P> {
749    type Item = P;
750
751    fn next(&mut self) -> Option<Self::Item> {
752        self.0.next().map(|x| x.into_prefix())
753    }
754}
755
756/// An iterator over the intersection of two [`JointPrefixSet`]s. The iterator yields first prefixes of
757/// `P1`, followed by those of `P2`.
758pub struct Intersection<'a, P: JointPrefix>(super::map::Intersection<'a, P, (), ()>);
759
760impl<P: JointPrefix> Iterator for Intersection<'_, P> {
761    type Item = P;
762
763    fn next(&mut self) -> Option<Self::Item> {
764        self.0.next().map(|(p, _, _)| p)
765    }
766}
767
768/// An iterator over the difference of two [`JointPrefixSet`]s. The iterator yields prefixes that
769/// are in `self`, but ont in `other`. The iterator also yields the longest prefix match in `other`
770/// (if it exists). The iterator yields first prefixes of `P1`, followed by those of `P2`.
771pub struct Difference<'a, P: JointPrefix>(super::map::Difference<'a, P, (), ()>);
772
773impl<P: JointPrefix> Iterator for Difference<'_, P> {
774    type Item = (P, Option<P>);
775
776    fn next(&mut self) -> Option<Self::Item> {
777        self.0.next().map(|x| (x.prefix, x.right.map(|(p, _)| p)))
778    }
779}
780
781/// An iterator over the covering difference of two [`JointPrefixSet`]s. The iterator yields
782/// prefixes that are in `self`, but not covered by any prefix in `other`. The iterator yields first
783/// prefixes of `P1`, followed by those of `P2`.
784pub struct CoveringDifference<'a, P: JointPrefix>(super::map::CoveringDifference<'a, P, (), ()>);
785
786impl<P: JointPrefix> Iterator for CoveringDifference<'_, P> {
787    type Item = P;
788
789    fn next(&mut self) -> Option<Self::Item> {
790        self.0.next().map(|(p, _)| p)
791    }
792}