prefix_trie/
set.rs

1//! PrefixSet, that is implemened as a simple binary tree, based on the [`PrefixMap`].
2
3use crate::{map::CoverKeys, Prefix, PrefixMap};
4
5/// Set of prefixes, organized in a tree. This strucutre gives efficient access to the longest
6/// prefix in the set that contains another prefix.
7///
8/// You can perform union, intersection, and (covering) difference operations by first creating a
9/// view over the map using [`crate::AsView`] or [`crate::AsViewMut`].
10#[derive(Clone)]
11pub struct PrefixSet<P>(pub(crate) PrefixMap<P, ()>);
12
13impl<P: Prefix> PrefixSet<P> {
14    /// Create a new, empty prefixset.
15    pub fn new() -> Self {
16        Self(Default::default())
17    }
18
19    /// Returns the number of elements stored in `self`.
20    #[inline(always)]
21    pub fn len(&self) -> usize {
22        self.0.len()
23    }
24
25    /// Returns `true` if the set contains no elements.
26    #[inline(always)]
27    pub fn is_empty(&self) -> bool {
28        self.0.is_empty()
29    }
30
31    /// Check wether some prefix is present in the set, without using longest prefix match.
32    ///
33    /// ```
34    /// # use prefix_trie::*;
35    /// # #[cfg(feature = "ipnet")]
36    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
37    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
38    /// set.insert("192.168.1.0/24".parse()?);
39    /// assert!(set.contains(&"192.168.1.0/24".parse()?));
40    /// assert!(!set.contains(&"192.168.2.0/24".parse()?));
41    /// assert!(!set.contains(&"192.168.0.0/23".parse()?));
42    /// assert!(!set.contains(&"192.168.1.128/25".parse()?));
43    /// # Ok(())
44    /// # }
45    /// # #[cfg(not(feature = "ipnet"))]
46    /// # fn main() {}
47    /// ```
48    pub fn contains(&self, prefix: &P) -> bool {
49        self.0.contains_key(prefix)
50    }
51
52    /// Get a reference to the stored prefix. This function allows you to retrieve the host part of
53    /// the prefix. The returned prefix will always have the same network address and prefix length.
54    ///
55    /// ```
56    /// # use prefix_trie::*;
57    /// # #[cfg(feature = "ipnet")]
58    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
59    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
60    /// set.insert("192.168.0.254/24".parse()?);
61    /// assert_eq!(set.get(&"192.168.0.0/24".parse()?), Some(&"192.168.0.254/24".parse()?));
62    /// # Ok(())
63    /// # }
64    /// # #[cfg(not(feature = "ipnet"))]
65    /// # fn main() {}
66    /// ```
67    pub fn get<'a>(&'a self, prefix: &P) -> Option<&'a P> {
68        self.0.get_key_value(prefix).map(|(p, _)| p)
69    }
70
71    /// Get the longest prefix in the set that contains the given preifx.
72    ///
73    /// ```
74    /// # use prefix_trie::*;
75    /// # #[cfg(feature = "ipnet")]
76    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
77    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
78    /// set.insert("192.168.1.0/24".parse()?);
79    /// set.insert("192.168.0.0/23".parse()?);
80    /// assert_eq!(set.get_lpm(&"192.168.1.1/32".parse()?), Some(&"192.168.1.0/24".parse()?));
81    /// assert_eq!(set.get_lpm(&"192.168.1.0/24".parse()?), Some(&"192.168.1.0/24".parse()?));
82    /// assert_eq!(set.get_lpm(&"192.168.0.0/24".parse()?), Some(&"192.168.0.0/23".parse()?));
83    /// assert_eq!(set.get_lpm(&"192.168.2.0/24".parse()?), None);
84    /// # Ok(())
85    /// # }
86    /// # #[cfg(not(feature = "ipnet"))]
87    /// # fn main() {}
88    /// ```
89    pub fn get_lpm<'a>(&'a self, prefix: &P) -> Option<&'a P> {
90        self.0.get_lpm(prefix).map(|(p, _)| p)
91    }
92
93    /// Get the shortest prefix in the set that contains the given preifx.
94    ///
95    /// ```
96    /// # use prefix_trie::*;
97    /// # #[cfg(feature = "ipnet")]
98    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
99    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
100    /// set.insert("192.168.1.0/24".parse()?);
101    /// set.insert("192.168.0.0/23".parse()?);
102    /// assert_eq!(set.get_spm(&"192.168.1.1/32".parse()?), Some(&"192.168.0.0/23".parse()?));
103    /// assert_eq!(set.get_spm(&"192.168.1.0/24".parse()?), Some(&"192.168.0.0/23".parse()?));
104    /// assert_eq!(set.get_spm(&"192.168.0.0/23".parse()?), Some(&"192.168.0.0/23".parse()?));
105    /// assert_eq!(set.get_spm(&"192.168.2.0/24".parse()?), None);
106    /// # Ok(())
107    /// # }
108    /// # #[cfg(not(feature = "ipnet"))]
109    /// # fn main() {}
110    /// ```
111    pub fn get_spm<'a>(&'a self, prefix: &P) -> Option<&'a P> {
112        self.0.get_spm_prefix(prefix)
113    }
114
115    /// Adds a value to the set.
116    ///
117    /// Returns whether the value was newly inserted. That is:
118    /// - If the set did not previously contain this value, `true` is returned.
119    /// - If the set already contained this value, `false` is returned.
120    ///
121    /// This operation will always replace the currently stored prefix. This allows you to store
122    /// additional information in the host aprt of the prefix.
123    ///
124    /// ```
125    /// # use prefix_trie::*;
126    /// # #[cfg(feature = "ipnet")]
127    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
128    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
129    /// assert!(set.insert("192.168.0.0/23".parse()?));
130    /// assert!(set.insert("192.168.1.0/24".parse()?));
131    /// assert!(!set.insert("192.168.1.0/24".parse()?));
132    /// # Ok(())
133    /// # }
134    /// # #[cfg(not(feature = "ipnet"))]
135    /// # fn main() {}
136    /// ```
137    pub fn insert(&mut self, prefix: P) -> bool {
138        self.0.insert(prefix, ()).is_none()
139    }
140
141    /// Removes a value from the set. Returns whether the value was present in the set.
142    ///
143    /// ```
144    /// # use prefix_trie::*;
145    /// # #[cfg(feature = "ipnet")]
146    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
147    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
148    /// let prefix = "192.168.1.0/24".parse()?;
149    /// set.insert(prefix);
150    /// assert!(set.contains(&prefix));
151    /// assert!(set.remove(&prefix));
152    /// assert!(!set.contains(&prefix));
153    /// # Ok(())
154    /// # }
155    /// # #[cfg(not(feature = "ipnet"))]
156    /// # fn main() {}
157    /// ```
158    pub fn remove(&mut self, prefix: &P) -> bool {
159        self.0.remove(prefix).is_some()
160    }
161
162    /// Removes a prefix from the set, returning wether the prefix was present or not. In contrast
163    /// to [`Self::remove`], his operation will keep the tree structure as is, but only remove the
164    /// element from it. This allows any future `insert` on the same prefix to be faster. However
165    /// future reads from the tree might be a bit slower because they need to traverse more nodes.
166    ///
167    /// ```
168    /// # use prefix_trie::*;
169    /// # #[cfg(feature = "ipnet")]
170    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
171    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
172    /// let prefix = "192.168.1.0/24".parse()?;
173    /// set.insert(prefix);
174    /// assert!(set.contains(&prefix));
175    /// assert!(set.remove_keep_tree(&prefix));
176    /// assert!(!set.contains(&prefix));
177    ///
178    /// // future inserts of the same key are now faster!
179    /// set.insert(prefix);
180    /// # Ok(())
181    /// # }
182    /// # #[cfg(not(feature = "ipnet"))]
183    /// # fn main() {}
184    /// ```
185    pub fn remove_keep_tree(&mut self, prefix: &P) -> bool {
186        self.0.remove_keep_tree(prefix).is_some()
187    }
188
189    /// Remove all elements that are contained within `prefix`. This will change the tree
190    /// structure. This operation is `O(n)`, as the entries must be freed up one-by-one.
191    ///
192    /// ```
193    /// # use prefix_trie::*;
194    /// # #[cfg(feature = "ipnet")]
195    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
196    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
197    /// set.insert("192.168.0.0/22".parse()?);
198    /// set.insert("192.168.0.0/23".parse()?);
199    /// set.insert("192.168.0.0/24".parse()?);
200    /// set.insert("192.168.2.0/23".parse()?);
201    /// set.insert("192.168.2.0/24".parse()?);
202    /// set.remove_children(&"192.168.0.0/23".parse()?);
203    /// assert!(!set.contains(&"192.168.0.0/23".parse()?));
204    /// assert!(!set.contains(&"192.168.0.0/24".parse()?));
205    /// assert!(set.contains(&"192.168.2.0/23".parse()?));
206    /// assert!(set.contains(&"192.168.2.0/24".parse()?));
207    /// # Ok(())
208    /// # }
209    /// # #[cfg(not(feature = "ipnet"))]
210    /// # fn main() {}
211    /// ```
212    pub fn remove_children(&mut self, prefix: &P) {
213        self.0.remove_children(prefix)
214    }
215
216    /// Clear the set but keep the allocated memory.
217    ///
218    /// ```
219    /// # use prefix_trie::*;
220    /// # #[cfg(feature = "ipnet")]
221    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
222    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
223    /// set.insert("192.168.0.0/24".parse()?);
224    /// set.insert("192.168.1.0/24".parse()?);
225    /// set.clear();
226    /// assert!(!set.contains(&"192.168.0.0/24".parse()?));
227    /// assert!(!set.contains(&"192.168.1.0/24".parse()?));
228    /// # Ok(())
229    /// # }
230    /// # #[cfg(not(feature = "ipnet"))]
231    /// # fn main() {}
232    /// ```
233    pub fn clear(&mut self) {
234        self.0.clear()
235    }
236
237    /// Iterate over all prefixes in the set
238    pub fn iter(&self) -> Iter<'_, P> {
239        self.into_iter()
240    }
241
242    /// Keep only the elements in the map that satisfy the given condition `f`.
243    ///
244    /// ```
245    /// # use prefix_trie::*;
246    /// # #[cfg(feature = "ipnet")]
247    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
248    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
249    /// set.insert("192.168.0.0/24".parse()?);
250    /// set.insert("192.168.1.0/24".parse()?);
251    /// set.insert("192.168.2.0/24".parse()?);
252    /// set.insert("192.168.2.0/25".parse()?);
253    /// set.retain(|p| p.prefix_len() == 24);
254    /// assert!(set.contains(&"192.168.0.0/24".parse()?));
255    /// assert!(set.contains(&"192.168.1.0/24".parse()?));
256    /// assert!(set.contains(&"192.168.2.0/24".parse()?));
257    /// assert!(!set.contains(&"192.168.2.0/25".parse()?));
258    /// # Ok(())
259    /// # }
260    /// # #[cfg(not(feature = "ipnet"))]
261    /// # fn main() {}
262    /// ```
263    pub fn retain<F>(&mut self, mut f: F)
264    where
265        F: FnMut(&P) -> bool,
266    {
267        let _ = self.0._retain(0, None, false, None, false, |p, _| f(p));
268    }
269
270    /// Get an iterator over the node itself and all children. All elements returned have a prefix
271    /// that is contained within `prefix` itself (or are the same). The iterator yields elements in
272    /// lexicographic order.
273    ///
274    /// **Info**: Use the [`crate::trieview::TrieView`] abstraction that provides more flexibility.
275    ///
276    /// ```
277    /// # use prefix_trie::*;
278    /// # #[cfg(feature = "ipnet")]
279    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
280    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
281    /// set.insert("192.168.0.0/22".parse()?);
282    /// set.insert("192.168.0.0/23".parse()?);
283    /// set.insert("192.168.2.0/23".parse()?);
284    /// set.insert("192.168.0.0/24".parse()?);
285    /// set.insert("192.168.2.0/24".parse()?);
286    /// assert_eq!(
287    ///     set.children(&"192.168.0.0/23".parse()?).collect::<Vec<_>>(),
288    ///     vec![
289    ///         &"192.168.0.0/23".parse()?,
290    ///         &"192.168.0.0/24".parse()?,
291    ///     ]
292    /// );
293    /// # Ok(())
294    /// # }
295    /// # #[cfg(not(feature = "ipnet"))]
296    /// # fn main() {}
297    /// ```
298    pub fn children<'a>(&'a self, prefix: &P) -> Iter<'a, P> {
299        Iter(self.0.children(prefix))
300    }
301
302    /// Iterate over all prefixes in the set that covers the given `prefix` (including `prefix`
303    /// itself if that is present in the set). The returned iterator yields `&'a P`.
304    ///
305    /// The iterator will always yield elements ordered by their prefix length, i.e., their depth in
306    /// the tree.
307    ///
308    /// ```
309    /// # use prefix_trie::*;
310    /// # #[cfg(feature = "ipnet")]
311    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
312    /// let mut set: PrefixSet<ipnet::Ipv4Net> = PrefixSet::new();
313    /// let p0 = "10.0.0.0/8".parse()?;
314    /// let p1 = "10.1.0.0/16".parse()?;
315    /// let p2 = "10.1.1.0/24".parse()?;
316    /// set.insert(p0);
317    /// set.insert(p1);
318    /// set.insert(p2);
319    /// set.insert("10.1.2.0/24".parse()?); // disjoint prefixes are not covered
320    /// set.insert("10.1.1.0/25".parse()?); // more specific prefixes are not covered
321    /// set.insert("11.0.0.0/8".parse()?);  // Branch points that don't contain values are skipped
322    /// assert_eq!(set.cover(&p2).collect::<Vec<_>>(), vec![&p0, &p1, &p2]);
323    /// # Ok(())
324    /// # }
325    /// # #[cfg(not(feature = "ipnet"))]
326    /// # fn main() {}
327    /// ```
328    pub fn cover<'a, 'p>(&'a self, prefix: &'p P) -> CoverKeys<'a, 'p, P, ()> {
329        self.0.cover_keys(prefix)
330    }
331}
332
333impl<P: Prefix> Default for PrefixSet<P> {
334    fn default() -> Self {
335        Self::new()
336    }
337}
338
339impl<P> PartialEq for PrefixSet<P>
340where
341    P: Prefix + PartialEq,
342{
343    fn eq(&self, other: &Self) -> bool {
344        self.iter().zip(other.iter()).all(|(a, b)| a == b)
345    }
346}
347
348impl<P> Eq for PrefixSet<P> where P: Prefix + Eq {}
349
350#[derive(Clone, Default)]
351/// An iterator over all entries of a [`PrefixSet`] in lexicographic order.
352pub struct Iter<'a, P>(crate::map::Iter<'a, P, ()>);
353
354impl<'a, P: Prefix> Iterator for Iter<'a, P> {
355    type Item = &'a P;
356
357    fn next(&mut self) -> Option<Self::Item> {
358        self.0.next().map(|(p, _)| p)
359    }
360}
361
362#[derive(Clone)]
363/// A consuming iterator over all entries of a [`PrefixSet`] in lexicographic order.
364pub struct IntoIter<P>(crate::map::IntoIter<P, ()>);
365
366impl<P: Prefix> Iterator for IntoIter<P> {
367    type Item = P;
368
369    fn next(&mut self) -> Option<Self::Item> {
370        self.0.next().map(|(p, _)| p)
371    }
372}
373
374impl<P: Prefix> IntoIterator for PrefixSet<P> {
375    type Item = P;
376
377    type IntoIter = IntoIter<P>;
378
379    fn into_iter(self) -> Self::IntoIter {
380        IntoIter(self.0.into_iter())
381    }
382}
383
384impl<'a, P: Prefix> IntoIterator for &'a PrefixSet<P> {
385    type Item = &'a P;
386
387    type IntoIter = Iter<'a, P>;
388
389    fn into_iter(self) -> Self::IntoIter {
390        Iter(self.0.iter())
391    }
392}
393
394impl<P: Prefix> FromIterator<P> for PrefixSet<P> {
395    fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> Self {
396        let mut set = Self::new();
397        for p in iter {
398            set.insert(p);
399        }
400        set
401    }
402}