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}