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}