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