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}