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::*;