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}