prefix_trie/map/mod.rs
1//! Implementation of the Prefix Map.
2
3use crate::{
4 inner::{Direction, DirectionForInsert, Node, Table},
5 Prefix,
6};
7
8mod entry;
9mod iter;
10
11pub use entry::*;
12pub use iter::*;
13
14/// Prefix map implemented as a prefix tree.
15///
16/// You can perform union, intersection, and (covering) difference operations by first creating a
17/// view over the map using [`crate::AsView`] or [`crate::AsViewMut`].
18#[derive(Clone)]
19pub struct PrefixMap<P, T> {
20 pub(crate) table: Table<P, T>,
21 free: Vec<usize>,
22 count: usize,
23}
24
25impl<P, T> Default for PrefixMap<P, T>
26where
27 P: Prefix,
28{
29 fn default() -> Self {
30 Self {
31 table: Default::default(),
32 free: Vec::new(),
33 count: 0,
34 }
35 }
36}
37
38impl<P, T> PrefixMap<P, T>
39where
40 P: Prefix,
41{
42 /// Create an empty prefix map.
43 pub fn new() -> Self {
44 Self::default()
45 }
46
47 /// Returns the number of elements stored in `self`.
48 #[inline(always)]
49 pub fn len(&self) -> usize {
50 self.count
51 }
52
53 /// Returns `true` if the map contains no elements.
54 #[inline(always)]
55 pub fn is_empty(&self) -> bool {
56 self.count == 0
57 }
58
59 /// Get the value of an element by matching exactly on the prefix.
60 ///
61 /// ```
62 /// # use prefix_trie::*;
63 /// # #[cfg(feature = "ipnet")]
64 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
65 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
66 /// pm.insert("192.168.1.0/24".parse()?, 1);
67 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
68 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), None);
69 /// assert_eq!(pm.get(&"192.168.0.0/23".parse()?), None);
70 /// assert_eq!(pm.get(&"192.168.1.128/25".parse()?), None);
71 /// # Ok(())
72 /// # }
73 /// # #[cfg(not(feature = "ipnet"))]
74 /// # fn main() {}
75 /// ```
76 pub fn get<'a>(&'a self, prefix: &P) -> Option<&'a T> {
77 let mut idx = 0;
78 loop {
79 match self.table.get_direction(idx, prefix) {
80 Direction::Reached => return self.table[idx].value.as_ref(),
81 Direction::Enter { next, .. } => idx = next,
82 Direction::Missing => return None,
83 }
84 }
85 }
86
87 /// Get a mutable reference to a value of an element by matching exactly on the prefix.
88 ///
89 /// ```
90 /// # use prefix_trie::*;
91 /// # #[cfg(feature = "ipnet")]
92 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
93 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
94 /// let prefix = "192.168.1.0/24".parse()?;
95 /// pm.insert(prefix, 1);
96 /// assert_eq!(pm.get(&prefix), Some(&1));
97 /// *pm.get_mut(&prefix).unwrap() += 1;
98 /// assert_eq!(pm.get(&prefix), Some(&2));
99 /// # Ok(())
100 /// # }
101 /// # #[cfg(not(feature = "ipnet"))]
102 /// # fn main() {}
103 /// ```
104 pub fn get_mut<'a>(&'a mut self, prefix: &P) -> Option<&'a mut T> {
105 let mut idx = 0;
106 loop {
107 match self.table.get_direction(idx, prefix) {
108 Direction::Reached => return self.table[idx].value.as_mut(),
109 Direction::Enter { next, .. } => idx = next,
110 Direction::Missing => return None,
111 }
112 }
113 }
114
115 /// Get the value of an element by matching exactly on the prefix. Notice, that the returned
116 /// prefix may differ from the one provided in the host-part of the address.
117 ///
118 /// ```
119 /// # use prefix_trie::*;
120 /// # #[cfg(feature = "ipnet")]
121 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
122 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
123 /// let prefix = "192.168.1.0/24".parse()?;
124 /// pm.insert(prefix, 1);
125 /// assert_eq!(pm.get_key_value(&prefix), Some((&prefix, &1)));
126 /// # Ok(())
127 /// # }
128 /// # #[cfg(not(feature = "ipnet"))]
129 /// # fn main() {}
130 /// ```
131 pub fn get_key_value<'a>(&'a self, prefix: &P) -> Option<(&'a P, &'a T)> {
132 let mut idx = 0;
133 loop {
134 match self.table.get_direction(idx, prefix) {
135 Direction::Reached => return self.table[idx].prefix_value(),
136 Direction::Enter { next, .. } => idx = next,
137 Direction::Missing => return None,
138 }
139 }
140 }
141
142 /// Get a value of an element by using longest prefix matching
143 ///
144 /// ```
145 /// # use prefix_trie::*;
146 /// # #[cfg(feature = "ipnet")]
147 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
148 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
149 /// pm.insert("192.168.1.0/24".parse()?, 1);
150 /// pm.insert("192.168.0.0/23".parse()?, 2);
151 /// assert_eq!(pm.get_lpm(&"192.168.1.1/32".parse()?), Some((&"192.168.1.0/24".parse()?, &1)));
152 /// assert_eq!(pm.get_lpm(&"192.168.1.0/24".parse()?), Some((&"192.168.1.0/24".parse()?, &1)));
153 /// assert_eq!(pm.get_lpm(&"192.168.0.0/24".parse()?), Some((&"192.168.0.0/23".parse()?, &2)));
154 /// assert_eq!(pm.get_lpm(&"192.168.2.0/24".parse()?), None);
155 /// # Ok(())
156 /// # }
157 /// # #[cfg(not(feature = "ipnet"))]
158 /// # fn main() {}
159 /// ```
160 pub fn get_lpm<'a>(&'a self, prefix: &P) -> Option<(&'a P, &'a T)> {
161 let mut idx = 0;
162 let mut best_match: Option<(&P, &T)> = None;
163 loop {
164 best_match = self.table[idx].prefix_value().or(best_match);
165 match self.table.get_direction(idx, prefix) {
166 Direction::Enter { next, .. } => idx = next,
167 _ => return best_match,
168 }
169 }
170 }
171
172 /// Get a mutable reference to a value of an element by using longest prefix matching
173 ///
174 /// ```
175 /// # use prefix_trie::*;
176 /// # #[cfg(feature = "ipnet")]
177 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
178 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
179 /// pm.insert("192.168.1.0/24".parse()?, 1);
180 /// pm.insert("192.168.0.0/23".parse()?, 2);
181 /// assert_eq!(pm.get_lpm(&"192.168.1.1/32".parse()?), Some((&"192.168.1.0/24".parse()?, &1)));
182 /// *pm.get_lpm_mut(&"192.168.1.64/26".parse()?).unwrap().1 += 1;
183 /// assert_eq!(pm.get_lpm(&"192.168.1.1/32".parse()?), Some((&"192.168.1.0/24".parse()?, &2)));
184 /// # Ok(())
185 /// # }
186 /// # #[cfg(not(feature = "ipnet"))]
187 /// # fn main() {}
188 /// ```
189 pub fn get_lpm_mut<'a>(&'a mut self, prefix: &P) -> Option<(&'a P, &'a mut T)> {
190 let mut idx = 0;
191 let mut best_match: Option<usize> = None;
192 loop {
193 best_match = if self.table[idx].value.is_some() {
194 Some(idx)
195 } else {
196 best_match
197 };
198 match self.table.get_direction(idx, prefix) {
199 Direction::Enter { next, .. } => idx = next,
200 _ => break,
201 }
202 }
203 if let Some(idx) = best_match {
204 self.table[idx].prefix_value_mut()
205 } else {
206 None
207 }
208 }
209
210 /// Check if a key is present in the datastructure.
211 ///
212 /// ```
213 /// # use prefix_trie::*;
214 /// # #[cfg(feature = "ipnet")]
215 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
216 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
217 /// pm.insert("192.168.1.0/24".parse()?, 1);
218 /// assert!(pm.contains_key(&"192.168.1.0/24".parse()?));
219 /// assert!(!pm.contains_key(&"192.168.2.0/24".parse()?));
220 /// assert!(!pm.contains_key(&"192.168.0.0/23".parse()?));
221 /// assert!(!pm.contains_key(&"192.168.1.128/25".parse()?));
222 /// # Ok(())
223 /// # }
224 /// # #[cfg(not(feature = "ipnet"))]
225 /// # fn main() {}
226 /// ```
227 pub fn contains_key(&self, prefix: &P) -> bool {
228 let mut idx = 0;
229 loop {
230 match self.table.get_direction(idx, prefix) {
231 Direction::Reached => return self.table[idx].value.is_some(),
232 Direction::Enter { next, .. } => idx = next,
233 Direction::Missing => return false,
234 }
235 }
236 }
237
238 /// Get the longest prefix in the datastructure that matches the given `prefix`.
239 ///
240 /// ```
241 /// # use prefix_trie::*;
242 /// # #[cfg(feature = "ipnet")]
243 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
244 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
245 /// pm.insert("192.168.1.0/24".parse()?, 1);
246 /// pm.insert("192.168.0.0/23".parse()?, 2);
247 /// assert_eq!(pm.get_lpm_prefix(&"192.168.1.1/32".parse()?), Some(&"192.168.1.0/24".parse()?));
248 /// assert_eq!(pm.get_lpm_prefix(&"192.168.1.0/24".parse()?), Some(&"192.168.1.0/24".parse()?));
249 /// assert_eq!(pm.get_lpm_prefix(&"192.168.0.0/24".parse()?), Some(&"192.168.0.0/23".parse()?));
250 /// assert_eq!(pm.get_lpm_prefix(&"192.168.2.0/24".parse()?), None);
251 /// # Ok(())
252 /// # }
253 /// # #[cfg(not(feature = "ipnet"))]
254 /// # fn main() {}
255 /// ```
256 pub fn get_lpm_prefix<'a>(&'a self, prefix: &P) -> Option<&'a P> {
257 let mut idx = 0;
258 let mut best_match: Option<&P> = None;
259 loop {
260 best_match = self.table[idx]
261 .prefix_value()
262 .map(|(p, _)| p)
263 .or(best_match);
264 match self.table.get_direction(idx, prefix) {
265 Direction::Enter { next, .. } => idx = next,
266 _ => return best_match,
267 }
268 }
269 }
270
271 /// Get a value of an element by using shortest prefix matching.
272 ///
273 /// ```
274 /// # use prefix_trie::*;
275 /// # #[cfg(feature = "ipnet")]
276 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
277 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
278 /// pm.insert("192.168.1.0/24".parse()?, 1);
279 /// pm.insert("192.168.0.0/23".parse()?, 2);
280 /// assert_eq!(pm.get_spm(&"192.168.1.1/32".parse()?), Some((&"192.168.0.0/23".parse()?, &2)));
281 /// assert_eq!(pm.get_spm(&"192.168.1.0/24".parse()?), Some((&"192.168.0.0/23".parse()?, &2)));
282 /// assert_eq!(pm.get_spm(&"192.168.0.0/23".parse()?), Some((&"192.168.0.0/23".parse()?, &2)));
283 /// assert_eq!(pm.get_spm(&"192.168.2.0/24".parse()?), None);
284 /// # Ok(())
285 /// # }
286 /// # #[cfg(not(feature = "ipnet"))]
287 /// # fn main() {}
288 pub fn get_spm<'a>(&'a self, prefix: &P) -> Option<(&'a P, &'a T)> {
289 // Handle the special case, where the root is populated
290 if let Some(x) = self.table[0].prefix_value() {
291 return Some(x);
292 }
293 let mut idx = 0;
294 loop {
295 match self.table.get_direction(idx, prefix) {
296 Direction::Reached => return self.table[idx].prefix_value(),
297 Direction::Enter { next, .. } => {
298 // Go until the first node with a value
299 match self.table[next].prefix_value() {
300 Some(x) => return Some(x),
301 None => idx = next,
302 }
303 }
304 Direction::Missing => return None,
305 }
306 }
307 }
308
309 /// Get the shortest prefix in the datastructure that contains the given `prefix`.
310 ///
311 /// ```
312 /// # use prefix_trie::*;
313 /// # #[cfg(feature = "ipnet")]
314 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
315 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
316 /// pm.insert("192.168.1.1/24".parse()?, 1);
317 /// pm.insert("192.168.0.0/23".parse()?, 2);
318 /// assert_eq!(pm.get_spm_prefix(&"192.168.1.1/32".parse()?), Some(&"192.168.0.0/23".parse()?));
319 /// assert_eq!(pm.get_spm_prefix(&"192.168.1.0/24".parse()?), Some(&"192.168.0.0/23".parse()?));
320 /// assert_eq!(pm.get_spm_prefix(&"192.168.0.0/23".parse()?), Some(&"192.168.0.0/23".parse()?));
321 /// assert_eq!(pm.get_spm_prefix(&"192.168.2.0/24".parse()?), None);
322 /// # Ok(())
323 /// # }
324 /// # #[cfg(not(feature = "ipnet"))]
325 /// # fn main() {}
326 pub fn get_spm_prefix<'a>(&'a self, prefix: &P) -> Option<&'a P> {
327 self.get_spm(prefix).map(|(p, _)| p)
328 }
329
330 /// Insert a new item into the prefix-map. This function may return any value that existed
331 /// before.
332 ///
333 /// In case the node already exists in the tree, its prefix will be replaced by the provided
334 /// argument. This allows you to store additional information in the host part of the prefix.
335 ///
336 /// ```
337 /// # use prefix_trie::*;
338 /// # #[cfg(feature = "ipnet")]
339 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
340 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
341 /// assert_eq!(pm.insert("192.168.0.0/23".parse()?, 1), None);
342 /// assert_eq!(pm.insert("192.168.1.0/24".parse()?, 2), None);
343 /// assert_eq!(pm.insert("192.168.1.0/24".parse()?, 3), Some(2));
344 /// # Ok(())
345 /// # }
346 /// # #[cfg(not(feature = "ipnet"))]
347 /// # fn main() {}
348 /// ```
349 pub fn insert(&mut self, prefix: P, value: T) -> Option<T> {
350 let mut idx = 0;
351 loop {
352 match self.table.get_direction_for_insert(idx, &prefix) {
353 DirectionForInsert::Enter { next, .. } => idx = next,
354 DirectionForInsert::Reached => {
355 let mut inc = 0;
356 let node = &mut self.table[idx];
357 // replace the prefix
358 node.prefix = prefix;
359 let old_value = node.value.take();
360 if old_value.is_none() {
361 inc = 1;
362 }
363 node.value = Some(value);
364 self.count += inc;
365 return old_value;
366 }
367 DirectionForInsert::NewLeaf { right } => {
368 let new = self.new_node(prefix, Some(value));
369 self.table.set_child(idx, new, right);
370 return None;
371 }
372 DirectionForInsert::NewChild { right, child_right } => {
373 let new = self.new_node(prefix, Some(value));
374 let child = self.table.set_child(idx, new, right).unwrap();
375 self.table.set_child(new, child, child_right);
376 return None;
377 }
378 DirectionForInsert::NewBranch {
379 branch_prefix,
380 right,
381 prefix_right,
382 } => {
383 let branch = self.new_node(branch_prefix, None);
384 let new = self.new_node(prefix, Some(value));
385 let child = self.table.set_child(idx, branch, right).unwrap();
386 self.table.set_child(branch, new, prefix_right);
387 self.table.set_child(branch, child, !prefix_right);
388 return None;
389 }
390 }
391 }
392 }
393
394 /// Gets the given key’s corresponding entry in the map for in-place manipulation. In case you
395 /// eventually insert an element into the map, this operation will also replace the prefix in
396 /// the node with the existing one. That is if you store additional information in the host part
397 /// of the address (the one that is masked out).
398 ///
399 /// ```
400 /// # use prefix_trie::*;
401 /// # #[cfg(feature = "ipnet")]
402 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
403 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
404 /// pm.insert("192.168.0.0/23".parse()?, vec![1]);
405 /// pm.entry("192.168.0.0/23".parse()?).or_default().push(2);
406 /// pm.entry("192.168.0.0/24".parse()?).or_default().push(3);
407 /// assert_eq!(pm.get(&"192.168.0.0/23".parse()?), Some(&vec![1, 2]));
408 /// assert_eq!(pm.get(&"192.168.0.0/24".parse()?), Some(&vec![3]));
409 /// # Ok(())
410 /// # }
411 /// # #[cfg(not(feature = "ipnet"))]
412 /// # fn main() {}
413 /// ```
414 pub fn entry(&mut self, prefix: P) -> Entry<'_, P, T> {
415 let mut idx = 0;
416 loop {
417 match self.table.get_direction_for_insert(idx, &prefix) {
418 DirectionForInsert::Enter { next, .. } => idx = next,
419 DirectionForInsert::Reached if self.table[idx].value.is_some() => {
420 return Entry::Occupied(OccupiedEntry {
421 node: &mut self.table[idx],
422 prefix,
423 })
424 }
425 direction => {
426 return Entry::Vacant(VacantEntry {
427 map: self,
428 prefix,
429 idx,
430 direction,
431 })
432 }
433 }
434 }
435 }
436
437 /// Removes a key from the map, returning the value at the key if the key was previously in the
438 /// map. In contrast to [`Self::remove_keep_tree`], this operation will modify the tree
439 /// structure. As a result, this operation takes longer than `remove_keep_tree`, as does
440 /// inserting the same element again. However, future reads may be faster as less nodes need to
441 /// be traversed. Further, it reduces the memory footprint to its minimum.
442 ///
443 /// ```
444 /// # use prefix_trie::*;
445 /// # #[cfg(feature = "ipnet")]
446 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
447 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
448 /// let prefix = "192.168.1.0/24".parse()?;
449 /// pm.insert(prefix, 1);
450 /// assert_eq!(pm.get(&prefix), Some(&1));
451 /// assert_eq!(pm.remove(&prefix), Some(1));
452 /// assert_eq!(pm.get(&prefix), None);
453 /// # Ok(())
454 /// # }
455 /// # #[cfg(not(feature = "ipnet"))]
456 /// # fn main() {}
457 /// ```
458 pub fn remove(&mut self, prefix: &P) -> Option<T> {
459 let mut idx = 0;
460 let mut grandparent = None;
461 let mut grandparent_right = false;
462 let mut parent = None;
463 let mut parent_right = false;
464 // first, search for the element
465 loop {
466 match self.table.get_direction(idx, prefix) {
467 Direction::Reached => break,
468 Direction::Enter { next, right } => {
469 grandparent_right = parent_right;
470 parent_right = right;
471 grandparent = parent;
472 parent = Some(idx);
473 idx = next;
474 }
475 Direction::Missing => return None,
476 }
477 }
478 self._remove_node(idx, parent, parent_right, grandparent, grandparent_right)
479 .0
480 }
481
482 /// Removes a key from the map, returning the value at the key if the key was previously in the
483 /// map. In contrast to [`Self::remove`], his operation will keep the tree structure as is, but
484 /// only remove the element from it. This allows any future `insert` on the same prefix to be
485 /// faster. However future reads from the tree might be a bit slower because they need to
486 /// traverse more nodes.
487 ///
488 /// ```
489 /// # use prefix_trie::*;
490 /// # #[cfg(feature = "ipnet")]
491 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
492 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
493 /// let prefix = "192.168.1.0/24".parse()?;
494 /// pm.insert(prefix, 1);
495 /// assert_eq!(pm.get(&prefix), Some(&1));
496 /// assert_eq!(pm.remove_keep_tree(&prefix), Some(1));
497 /// assert_eq!(pm.get(&prefix), None);
498 ///
499 /// // future inserts of the same key are now faster!
500 /// pm.insert(prefix, 1);
501 /// # Ok(())
502 /// # }
503 /// # #[cfg(not(feature = "ipnet"))]
504 /// # fn main() {}
505 /// ```
506 pub fn remove_keep_tree(&mut self, prefix: &P) -> Option<T> {
507 let mut idx = 0;
508 let value = loop {
509 match self.table.get_direction(idx, prefix) {
510 Direction::Reached => break self.table[idx].value.take(),
511 Direction::Enter { next, .. } => idx = next,
512 Direction::Missing => break None,
513 }
514 };
515
516 // decrease the count if the value is something
517 if value.is_some() {
518 self.count -= 1;
519 }
520
521 value
522 }
523
524 /// Remove all entries that are contained within `prefix`. This will change the tree
525 /// structure. This operation is `O(n)`, as the entries must be freed up one-by-one.
526 ///
527 /// ```
528 /// # use prefix_trie::*;
529 /// # #[cfg(feature = "ipnet")]
530 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
531 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
532 /// pm.insert("192.168.0.0/22".parse()?, 1);
533 /// pm.insert("192.168.0.0/23".parse()?, 2);
534 /// pm.insert("192.168.0.0/24".parse()?, 3);
535 /// pm.insert("192.168.2.0/23".parse()?, 4);
536 /// pm.insert("192.168.2.0/24".parse()?, 5);
537 /// pm.remove_children(&"192.168.0.0/23".parse()?);
538 /// assert_eq!(pm.get(&"192.168.0.0/23".parse()?), None);
539 /// assert_eq!(pm.get(&"192.168.0.0/24".parse()?), None);
540 /// assert_eq!(pm.get(&"192.168.2.0/23".parse()?), Some(&4));
541 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&5));
542 /// # Ok(())
543 /// # }
544 /// # #[cfg(not(feature = "ipnet"))]
545 /// # fn main() {}
546 /// ```
547 pub fn remove_children(&mut self, prefix: &P) {
548 if prefix.prefix_len() == 0 {
549 return self.clear();
550 }
551 let mut parent_right = false;
552 let mut parent = 0;
553 let mut idx = 0;
554 loop {
555 match self.table.get_direction_for_insert(idx, prefix) {
556 DirectionForInsert::Reached => {
557 return self._do_remove_children(parent, parent_right)
558 }
559 DirectionForInsert::Enter { next, right } => {
560 parent_right = right;
561 parent = idx;
562 idx = next
563 }
564 DirectionForInsert::NewLeaf { .. } | DirectionForInsert::NewBranch { .. } => return,
565 DirectionForInsert::NewChild { right, .. } => {
566 return self._do_remove_children(idx, right)
567 }
568 }
569 }
570 }
571
572 /// Clear the map but keep the allocated memory.
573 ///
574 /// ```
575 /// # use prefix_trie::*;
576 /// # #[cfg(feature = "ipnet")]
577 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
578 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
579 /// pm.insert("192.168.0.0/24".parse()?, 1);
580 /// pm.insert("192.168.1.0/24".parse()?, 2);
581 /// pm.clear();
582 /// assert_eq!(pm.get(&"192.168.0.0/24".parse()?), None);
583 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), None);
584 /// # Ok(())
585 /// # }
586 /// # #[cfg(not(feature = "ipnet"))]
587 /// # fn main() {}
588 /// ```
589 pub fn clear(&mut self) {
590 self.table.as_mut().clear();
591 self.free.clear();
592 self.table.as_mut().push(Node {
593 prefix: P::zero(),
594 value: None,
595 left: None,
596 right: None,
597 });
598 self.count = 0;
599 }
600
601 /// Keep only the elements in the map that satisfy the given condition `f`.
602 ///
603 /// ```
604 /// # use prefix_trie::*;
605 /// # #[cfg(feature = "ipnet")]
606 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
607 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
608 /// pm.insert("192.168.0.0/24".parse()?, 1);
609 /// pm.insert("192.168.1.0/24".parse()?, 2);
610 /// pm.insert("192.168.2.0/24".parse()?, 3);
611 /// pm.insert("192.168.2.0/25".parse()?, 4);
612 /// pm.retain(|_, t| *t % 2 == 0);
613 /// assert_eq!(pm.get(&"192.168.0.0/24".parse()?), None);
614 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&2));
615 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), None);
616 /// assert_eq!(pm.get(&"192.168.2.0/25".parse()?), Some(&4));
617 /// # Ok(())
618 /// # }
619 /// # #[cfg(not(feature = "ipnet"))]
620 /// # fn main() {}
621 /// ```
622 pub fn retain<F>(&mut self, f: F)
623 where
624 F: FnMut(&P, &T) -> bool,
625 {
626 self._retain(0, None, false, None, false, f);
627 }
628
629 /// Iterate over all entries in the map that covers the given `prefix` (including `prefix`
630 /// itself if that is present in the map). The returned iterator yields `(&'a P, &'a T)`.
631 ///
632 /// The iterator will always yield elements ordered by their prefix length, i.e., their depth in
633 /// the tree.
634 ///
635 /// ```
636 /// # use prefix_trie::*;
637 /// # #[cfg(feature = "ipnet")]
638 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
639 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
640 /// let p0 = "10.0.0.0/8".parse()?;
641 /// let p1 = "10.1.0.0/16".parse()?;
642 /// let p2 = "10.1.1.0/24".parse()?;
643 /// pm.insert(p0, 0);
644 /// pm.insert(p1, 1);
645 /// pm.insert(p2, 2);
646 /// pm.insert("10.1.2.0/24".parse()?, 3); // disjoint prefixes are not covered
647 /// pm.insert("10.1.1.0/25".parse()?, 4); // more specific prefixes are not covered
648 /// pm.insert("11.0.0.0/8".parse()?, 5); // Branch points that don't contain values are skipped
649 /// assert_eq!(
650 /// pm.cover(&p2).collect::<Vec<_>>(),
651 /// vec![(&p0, &0), (&p1, &1), (&p2, &2)]
652 /// );
653 /// # Ok(())
654 /// # }
655 /// # #[cfg(not(feature = "ipnet"))]
656 /// # fn main() {}
657 /// ```
658 ///
659 /// This function also yields the root note *if* it is part of the map:
660 ///
661 /// ```
662 /// # use prefix_trie::*;
663 /// # #[cfg(feature = "ipnet")]
664 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
665 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
666 /// let root = "0.0.0.0/0".parse()?;
667 /// pm.insert(root, 0);
668 /// assert_eq!(pm.cover(&"10.0.0.0/8".parse()?).collect::<Vec<_>>(), vec![(&root, &0)]);
669 /// # Ok(())
670 /// # }
671 /// # #[cfg(not(feature = "ipnet"))]
672 /// # fn main() {}
673 /// ```
674 pub fn cover<'a, 'p>(&'a self, prefix: &'p P) -> Cover<'a, 'p, P, T> {
675 Cover {
676 table: &self.table,
677 idx: None,
678 prefix,
679 }
680 }
681
682 /// Iterate over all keys (prefixes) in the map that covers the given `prefix` (including
683 /// `prefix` itself if that is present in the map). The returned iterator yields `&'a P`.
684 ///
685 /// The iterator will always yield elements ordered by their prefix length, i.e., their depth in
686 /// the tree.
687 ///
688 /// ```
689 /// # use prefix_trie::*;
690 /// # #[cfg(feature = "ipnet")]
691 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
692 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
693 /// let p0 = "10.0.0.0/8".parse()?;
694 /// let p1 = "10.1.0.0/16".parse()?;
695 /// let p2 = "10.1.1.0/24".parse()?;
696 /// pm.insert(p0, 0);
697 /// pm.insert(p1, 1);
698 /// pm.insert(p2, 2);
699 /// pm.insert("10.1.2.0/24".parse()?, 3); // disjoint prefixes are not covered
700 /// pm.insert("10.1.1.0/25".parse()?, 4); // more specific prefixes are not covered
701 /// pm.insert("11.0.0.0/8".parse()?, 5); // Branch points that don't contain values are skipped
702 /// assert_eq!(pm.cover_keys(&p2).collect::<Vec<_>>(), vec![&p0, &p1, &p2]);
703 /// # Ok(())
704 /// # }
705 /// # #[cfg(not(feature = "ipnet"))]
706 /// # fn main() {}
707 /// ```
708 pub fn cover_keys<'a, 'p>(&'a self, prefix: &'p P) -> CoverKeys<'a, 'p, P, T> {
709 CoverKeys(Cover {
710 table: &self.table,
711 idx: None,
712 prefix,
713 })
714 }
715
716 /// Iterate over all values in the map that covers the given `prefix` (including `prefix`
717 /// itself if that is present in the map). The returned iterator yields `&'a T`.
718 ///
719 /// The iterator will always yield elements ordered by their prefix length, i.e., their depth in
720 /// the tree.
721 ///
722 /// ```
723 /// # use prefix_trie::*;
724 /// # #[cfg(feature = "ipnet")]
725 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
726 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
727 /// let p0 = "10.0.0.0/8".parse()?;
728 /// let p1 = "10.1.0.0/16".parse()?;
729 /// let p2 = "10.1.1.0/24".parse()?;
730 /// pm.insert(p0, 0);
731 /// pm.insert(p1, 1);
732 /// pm.insert(p2, 2);
733 /// pm.insert("10.1.2.0/24".parse()?, 3); // disjoint prefixes are not covered
734 /// pm.insert("10.1.1.0/25".parse()?, 4); // more specific prefixes are not covered
735 /// pm.insert("11.0.0.0/8".parse()?, 5); // Branch points that don't contain values are skipped
736 /// assert_eq!(pm.cover_values(&p2).collect::<Vec<_>>(), vec![&0, &1, &2]);
737 /// # Ok(())
738 /// # }
739 /// # #[cfg(not(feature = "ipnet"))]
740 /// # fn main() {}
741 /// ```
742 pub fn cover_values<'a, 'p>(&'a self, prefix: &'p P) -> CoverValues<'a, 'p, P, T> {
743 CoverValues(Cover {
744 table: &self.table,
745 idx: None,
746 prefix,
747 })
748 }
749}
750
751/// Private function implementations
752impl<P, T> PrefixMap<P, T>
753where
754 P: Prefix,
755{
756 /// remove all elements from that point onwards.
757 fn _do_remove_children(&mut self, idx: usize, right: bool) {
758 let mut to_free = vec![self.table.get_child(idx, right).unwrap()];
759 self.table.clear_child(idx, right);
760 while let Some(idx) = to_free.pop() {
761 let mut dec = 0;
762 let node = &mut self.table[idx];
763 let value = node.value.take();
764 // decrease the count if `value` is something
765 if value.is_some() {
766 dec = 1;
767 }
768 if let Some(left) = node.left.take() {
769 to_free.push(left)
770 }
771 if let Some(right) = node.right.take() {
772 to_free.push(right)
773 }
774 self.free.push(idx);
775 self.count -= dec;
776 }
777 }
778
779 /// insert a new node into the table and return its index. This function also increments the
780 /// count by 1, but only if `value` is `Some`.
781 #[inline(always)]
782 fn new_node(&mut self, prefix: P, value: Option<T>) -> usize {
783 if value.is_some() {
784 self.count += 1;
785 }
786 if let Some(idx) = self.free.pop() {
787 let node = &mut self.table[idx];
788 node.prefix = prefix;
789 node.value = value;
790 node.left = None;
791 node.right = None;
792 idx
793 } else {
794 let table = self.table.as_mut();
795 let idx = table.len();
796 table.push(Node {
797 prefix,
798 value,
799 left: None,
800 right: None,
801 });
802 idx
803 }
804 }
805
806 /// Remove a child from the tree. If the parent was removed, return `true` as a second return parameter
807 fn _remove_node(
808 &mut self,
809 idx: usize,
810 par: Option<usize>,
811 par_right: bool,
812 grp: Option<usize>,
813 grp_right: bool,
814 ) -> (Option<T>, bool) {
815 // if we reach this point, then `idx` is the element to remove, `parent` is its parent,
816 // and `parent_right` stores the direction of `idx` at `parent`.
817 let node = &mut self.table[idx];
818 let value = node.value.take();
819 let has_left = node.left.is_some();
820 let has_right = node.right.is_some();
821
822 // decrease the number of elements if value is something
823 if value.is_some() {
824 self.count -= 1;
825 }
826
827 if has_left && has_right {
828 // if the node has both left and right set, then it must remain in the tree.
829 } else if !(has_left || has_right) {
830 if let Some(par) = par {
831 // if the node is a leaf, simply remove it.
832 self.table.clear_child(par, par_right);
833 self.free.push(idx);
834 // now, if the parent has no value, also remove the parent and replace it with the
835 // current node. but only do that if the grandparent is something.
836 if let Some(grp) = grp {
837 if self.table[par].value.is_none() {
838 if let Some(sibling) = self.table.get_child(par, !par_right) {
839 self.table.set_child(grp, sibling, grp_right);
840 return (value, true);
841 } else {
842 self.table.clear_child(grp, grp_right);
843 }
844 }
845 }
846 }
847 } else {
848 // one child remains. simply connect that child directly to the parent if the parent is Something.
849 if let Some(par) = par {
850 let child_right = has_right;
851 let child = self.table.clear_child(idx, child_right).unwrap();
852 self.table.set_child(par, child, par_right);
853 self.free.push(idx);
854 }
855 }
856 (value, false)
857 }
858
859 /// recursive retain implementation
860 pub(crate) fn _retain<F>(
861 &mut self,
862 idx: usize,
863 par: Option<usize>,
864 par_right: bool,
865 grp: Option<usize>,
866 grp_right: bool,
867 mut f: F,
868 ) -> (F, bool)
869 where
870 F: FnMut(&P, &T) -> bool,
871 {
872 // first, do the recursion
873 let mut idx_removed = false;
874 let mut par_removed = false;
875 if let Some(left) = self.table[idx].left {
876 (f, idx_removed) = self._retain(left, Some(idx), false, par, par_right, f);
877 }
878 if let Some(right) = self.table[idx].right {
879 if idx_removed {
880 (f, par_removed) = self._retain(right, par, par_right, grp, grp_right, f);
881 } else {
882 (f, _) = self._retain(right, Some(idx), true, par, par_right, f);
883 }
884 }
885 // then, check if we need to delete the node
886 if let Some(val) = self.table[idx].value.as_ref() {
887 if !f(&self.table[idx].prefix, val) {
888 // deletion is necessary.
889 let (_, par_del) = self._remove_node(idx, par, par_right, grp, grp_right);
890 par_removed = par_del;
891 }
892 }
893 (f, par_removed)
894 }
895}
896
897impl<P, T> PartialEq for PrefixMap<P, T>
898where
899 P: Prefix + PartialEq,
900 T: PartialEq,
901{
902 fn eq(&self, other: &Self) -> bool {
903 self.iter().zip(other.iter()).all(|(a, b)| a == b)
904 }
905}
906
907impl<P, T> Eq for PrefixMap<P, T>
908where
909 P: Prefix + Eq,
910 T: Eq,
911{
912}