prefix_trie/trieview/mod.rs
1//! A [`TrieView`] (or a [`TrieViewMut`]) is a pointer to a specific element in a PrefixTrie, representing the sub-tree
2//! rooted at that node.
3//!
4//! This module allows you to perform Set operations (union, intersection, difference) on
5//! [`PrefixMap`]s and [`PrefixSet`]s, optionally of only a trie-view.
6
7#[cfg(test)]
8#[cfg(feature = "ipnet")]
9mod test;
10
11mod difference;
12mod intersection;
13mod union;
14pub use difference::{
15 CoveringDifference, CoveringDifferenceMut, Difference, DifferenceItem, DifferenceMut,
16 DifferenceMutItem,
17};
18pub use intersection::{Intersection, IntersectionMut};
19pub use union::{Union, UnionItem, UnionMut};
20
21use crate::{
22 inner::{Direction, DirectionForInsert, Node, Table},
23 map::{Iter, IterMut, Keys, Values, ValuesMut},
24 to_right, Prefix, PrefixMap, PrefixSet,
25};
26
27/// A trait for creating a [`TrieView`] of `self`.
28pub trait AsView: Sized {
29 /// The prefix type of the returned view
30 type P: Prefix;
31 /// The value type of the returned view
32 type T;
33
34 /// Get a TrieView rooted at the origin (referencing the entire trie).
35 fn view(&self) -> TrieView<'_, Self::P, Self::T>;
36
37 /// Get a TrieView rooted at the given `prefix`. If that `prefix` is not part of the trie, `None`
38 /// is returned. Calling this function is identical to `self.view().find(prefix)`.
39 fn view_at(&self, prefix: Self::P) -> Option<TrieView<'_, Self::P, Self::T>> {
40 self.view().find(prefix)
41 }
42}
43
44impl<'a, P: Prefix + Clone, T> AsView for TrieView<'a, P, T> {
45 type P = P;
46 type T = T;
47
48 fn view(&self) -> TrieView<'a, P, T> {
49 self.clone()
50 }
51}
52
53impl<'a, P: Prefix + Clone, T> AsView for &TrieView<'a, P, T> {
54 type P = P;
55 type T = T;
56
57 fn view(&self) -> TrieView<'a, P, T> {
58 (*self).clone()
59 }
60}
61
62impl<P: Prefix + Clone, T> AsView for TrieViewMut<'_, P, T> {
63 type P = P;
64 type T = T;
65
66 fn view(&self) -> TrieView<'_, P, T> {
67 TrieView {
68 table: self.table,
69 loc: self.loc.clone(),
70 }
71 }
72}
73
74impl<P: Prefix, T> AsView for PrefixMap<P, T> {
75 type P = P;
76 type T = T;
77
78 fn view(&self) -> TrieView<'_, P, T> {
79 TrieView {
80 table: &self.table,
81 loc: ViewLoc::Node(0),
82 }
83 }
84}
85
86impl<P: Prefix> AsView for PrefixSet<P> {
87 type P = P;
88 type T = ();
89
90 fn view(&self) -> TrieView<'_, P, ()> {
91 TrieView {
92 table: &self.0.table,
93 loc: ViewLoc::Node(0),
94 }
95 }
96}
97
98/// A subtree of a prefix-trie rooted at a specific node.
99///
100/// The view can point to one of three possible things:
101/// - A node in the tree that is actually present in the map,
102/// - A branching node that does not exist in the map, but is needed for the tree structure (or that
103/// was deleted using the function `remove_keep_tree`)
104/// - A virtual node that does not exist as a node in the tree. This is only the case if you call
105/// [`TrieView::find`] or [`AsView::view_at`] with a node that is not present in the tree, but
106/// that contains elements present in the tree. Virtual nodes are treated as if they are actually
107/// present in the tree as branching nodes.
108pub struct TrieView<'a, P, T> {
109 table: &'a Table<P, T>,
110 loc: ViewLoc<P>,
111}
112
113#[derive(Clone, Copy)]
114enum ViewLoc<P> {
115 Node(usize),
116 Virtual(P, usize),
117}
118
119impl<P> ViewLoc<P> {
120 fn idx(&self) -> usize {
121 match self {
122 ViewLoc::Node(i) | ViewLoc::Virtual(_, i) => *i,
123 }
124 }
125}
126
127impl<P: Copy, T> Copy for TrieView<'_, P, T> {}
128
129impl<P: Clone, T> Clone for TrieView<'_, P, T> {
130 fn clone(&self) -> Self {
131 Self {
132 table: self.table,
133 loc: self.loc.clone(),
134 }
135 }
136}
137
138impl<P: std::fmt::Debug, T: std::fmt::Debug> std::fmt::Debug for TrieView<'_, P, T> {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 f.debug_tuple("View").field(self.prefix()).finish()
141 }
142}
143
144impl<P, L, Rhs> PartialEq<Rhs> for TrieView<'_, P, L>
145where
146 P: Prefix + PartialEq,
147 L: PartialEq<Rhs::T>,
148 Rhs: crate::AsView<P = P>,
149{
150 fn eq(&self, other: &Rhs) -> bool {
151 self.iter()
152 .zip(other.view().iter())
153 .all(|((lp, lt), (rp, rt))| lt == rt && lp == rp)
154 }
155}
156
157impl<P, T> Eq for TrieView<'_, P, T>
158where
159 P: Prefix + Eq + Clone,
160 T: Eq,
161{
162}
163
164impl<'a, P, T> TrieView<'a, P, T>
165where
166 P: Prefix,
167{
168 /// Find `prefix`, returning a new view that points to the first node that is contained
169 /// within that prefix (or `prefix` itself). Only the current view is searched. If `prefix`
170 /// is not present in the current view referenced by `self` (including any sub-prefix of
171 /// `prefix`), the function returns `None`.
172 ///
173 /// ```
174 /// # use prefix_trie::*;
175 /// # #[cfg(feature = "ipnet")]
176 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
177 ///
178 /// # #[cfg(feature = "ipnet")]
179 /// # {
180 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
181 /// (net!("192.168.0.0/20"), 1),
182 /// (net!("192.168.0.0/22"), 2),
183 /// (net!("192.168.0.0/24"), 3),
184 /// (net!("192.168.2.0/23"), 4),
185 /// (net!("192.168.4.0/22"), 5),
186 /// ]);
187 /// let sub = map.view();
188 /// assert_eq!(
189 /// sub.find(net!("192.168.0.0/21")).unwrap().keys().collect::<Vec<_>>(),
190 /// vec![
191 /// &net!("192.168.0.0/22"),
192 /// &net!("192.168.0.0/24"),
193 /// &net!("192.168.2.0/23"),
194 /// &net!("192.168.4.0/22"),
195 /// ]
196 /// );
197 /// assert_eq!(
198 /// sub.find(net!("192.168.0.0/22")).unwrap().keys().collect::<Vec<_>>(),
199 /// vec![
200 /// &net!("192.168.0.0/22"),
201 /// &net!("192.168.0.0/24"),
202 /// &net!("192.168.2.0/23"),
203 /// ]
204 /// );
205 /// # }
206 /// ```
207 pub fn find(&self, prefix: P) -> Option<TrieView<'a, P, T>> {
208 let mut idx = self.loc.idx();
209 loop {
210 match self.table.get_direction_for_insert(idx, &prefix) {
211 DirectionForInsert::Enter { next, .. } => {
212 idx = next;
213 }
214 DirectionForInsert::Reached => {
215 return Some(Self {
216 table: self.table,
217 loc: ViewLoc::Node(idx),
218 })
219 }
220 DirectionForInsert::NewChild { right, .. } => {
221 // view at a virtual node between idx and the right child of idx.
222 return Some(Self {
223 table: self.table,
224 loc: ViewLoc::Virtual(prefix, self.table.get_child(idx, right).unwrap()),
225 });
226 }
227 DirectionForInsert::NewLeaf { .. } | DirectionForInsert::NewBranch { .. } => {
228 return None
229 }
230 }
231 }
232 }
233
234 /// Find `prefix`, returning a new view that points to that node. Only the current view is
235 /// searched. If this prefix is not present in the view pointed to by `self`, the function
236 /// returns `None`.
237 ///
238 /// ```
239 /// # use prefix_trie::*;
240 /// # #[cfg(feature = "ipnet")]
241 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
242 ///
243 /// # #[cfg(feature = "ipnet")]
244 /// # {
245 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
246 /// (net!("192.168.0.0/20"), 1),
247 /// (net!("192.168.0.0/22"), 2),
248 /// (net!("192.168.0.0/24"), 3),
249 /// (net!("192.168.2.0/23"), 4),
250 /// (net!("192.168.4.0/22"), 5),
251 /// ]);
252 /// let sub = map.view();
253 /// assert!(sub.find_exact(&net!("192.168.0.0/21")).is_none());
254 /// assert_eq!(
255 /// sub.find_exact(&net!("192.168.0.0/22")).unwrap().keys().collect::<Vec<_>>(),
256 /// vec![
257 /// &net!("192.168.0.0/22"),
258 /// &net!("192.168.0.0/24"),
259 /// &net!("192.168.2.0/23"),
260 /// ]
261 /// );
262 ///
263 /// // If the prefix does not exist, the function returns `None`:
264 /// assert_eq!(map.view().find_exact(&net!("10.0.0.0/8")), None);
265 /// # }
266 /// ```
267 pub fn find_exact(&self, prefix: &P) -> Option<TrieView<'a, P, T>> {
268 let mut idx = self.loc.idx();
269 loop {
270 match self.table.get_direction(idx, prefix) {
271 Direction::Reached => {
272 return self.table[idx].value.is_some().then_some(Self {
273 table: self.table,
274 loc: ViewLoc::Node(idx),
275 })
276 }
277 Direction::Enter { next, .. } => idx = next,
278 Direction::Missing => return None,
279 }
280 }
281 }
282
283 /// Find the longest match of `prefix`, returning a new view that points to that node. Only
284 /// the given view is searched. If the prefix is not present in the view pointed to by
285 /// `self`, the function returns `None`.
286 ///
287 /// Only views to nodes that are present in the map are returned, not to branching nodes.
288 ///
289 /// ```
290 /// # use prefix_trie::*;
291 /// # #[cfg(feature = "ipnet")]
292 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
293 ///
294 /// # #[cfg(feature = "ipnet")]
295 /// # {
296 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
297 /// (net!("192.168.0.0/20"), 1),
298 /// (net!("192.168.0.0/22"), 2),
299 /// (net!("192.168.0.0/24"), 3),
300 /// (net!("192.168.2.0/23"), 4),
301 /// (net!("192.168.4.0/22"), 5),
302 /// ]);
303 /// let sub = map.view();
304 /// assert_eq!(
305 /// sub.find_lpm(&net!("192.168.0.0/21")).unwrap().keys().collect::<Vec<_>>(),
306 /// vec![
307 /// &net!("192.168.0.0/20"),
308 /// &net!("192.168.0.0/22"),
309 /// &net!("192.168.0.0/24"),
310 /// &net!("192.168.2.0/23"),
311 /// &net!("192.168.4.0/22"),
312 /// ]
313 /// );
314 /// assert_eq!(
315 /// sub.find_lpm(&net!("192.168.0.0/22")).unwrap().keys().collect::<Vec<_>>(),
316 /// vec![
317 /// &net!("192.168.0.0/22"),
318 /// &net!("192.168.0.0/24"),
319 /// &net!("192.168.2.0/23"),
320 /// ]
321 /// );
322 /// # }
323 /// ```
324 pub fn find_lpm(&self, prefix: &P) -> Option<TrieView<'a, P, T>> {
325 let mut idx = self.loc.idx();
326 let mut best_match = None;
327 loop {
328 if self.table[idx].value.is_some() {
329 best_match = Some(idx);
330 }
331 match self.table.get_direction(idx, prefix) {
332 Direction::Enter { next, .. } => idx = next,
333 _ => {
334 return best_match.map(|idx| Self {
335 table: self.table,
336 loc: ViewLoc::Node(idx),
337 })
338 }
339 }
340 }
341 }
342
343 /// Get the left branch at the current view. The right branch contains all prefix that are
344 /// contained within `self.prefix()`, and for which the next bit is set to 0.
345 ///
346 /// ```
347 /// # use prefix_trie::*;
348 /// # #[cfg(feature = "ipnet")]
349 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
350 ///
351 /// # #[cfg(feature = "ipnet")]
352 /// # {
353 /// let map: PrefixSet<ipnet::Ipv4Net> = PrefixSet::from_iter([
354 /// net!("1.0.0.0/8"),
355 /// net!("1.0.0.0/16"),
356 /// net!("1.0.128.0/17"),
357 /// net!("1.1.0.0/16"),
358 /// ]);
359 ///
360 /// let view = map.view_at(net!("1.0.0.0/8")).unwrap();
361 /// assert_eq!(view.prefix(), &net!("1.0.0.0/8"));
362 ///
363 /// let view = view.left().unwrap();
364 /// assert_eq!(view.prefix(), &net!("1.0.0.0/15"));
365 ///
366 /// let view = view.left().unwrap();
367 /// assert_eq!(view.prefix(), &net!("1.0.0.0/16"));
368 ///
369 /// assert!(view.left().is_none());
370 /// # }
371 /// ```
372 pub fn left(&self) -> Option<Self> {
373 match &self.loc {
374 ViewLoc::Node(idx) => Some(Self {
375 table: self.table,
376 loc: ViewLoc::Node(self.table[*idx].left?),
377 }),
378 ViewLoc::Virtual(p, idx) => {
379 // first, check if the node is on the left of the virtual one.
380 if !to_right(p, &self.table[*idx].prefix) {
381 Some(Self {
382 table: self.table,
383 loc: ViewLoc::Node(*idx),
384 })
385 } else {
386 None
387 }
388 }
389 }
390 }
391
392 /// Get the right branch at the current view. The right branch contains all prefix that are
393 /// contained within `self.prefix()`, and for which the next bit is set to 1.
394 ///
395 /// ```
396 /// # use prefix_trie::*;
397 /// # #[cfg(feature = "ipnet")]
398 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
399 ///
400 /// # #[cfg(feature = "ipnet")]
401 /// # {
402 /// let map: PrefixSet<ipnet::Ipv4Net> = PrefixSet::from_iter([
403 /// net!("1.0.0.0/8"),
404 /// net!("1.0.0.0/16"),
405 /// net!("1.1.0.0/16"),
406 /// net!("1.1.0.0/24"),
407 /// ]);
408 ///
409 /// let view = map.view_at(net!("1.0.0.0/8")).unwrap();
410 /// assert_eq!(view.prefix(), &net!("1.0.0.0/8"));
411 ///
412 /// assert!(view.right().is_none());
413 /// let view = view.left().unwrap();
414 /// assert_eq!(view.prefix(), &net!("1.0.0.0/15"));
415 ///
416 /// let view = view.right().unwrap();
417 /// assert_eq!(view.prefix(), &net!("1.1.0.0/16"));
418 ///
419 /// assert!(view.right().is_none());
420 /// # }
421 /// ```
422 pub fn right(&self) -> Option<Self> {
423 match &self.loc {
424 ViewLoc::Node(idx) => Some(Self {
425 table: self.table,
426 loc: ViewLoc::Node(self.table[*idx].right?),
427 }),
428 ViewLoc::Virtual(p, idx) => {
429 // first, check if the node is on the right of the virtual one.
430 if to_right(p, &self.table[*idx].prefix) {
431 Some(Self {
432 table: self.table,
433 loc: ViewLoc::Node(*idx),
434 })
435 } else {
436 None
437 }
438 }
439 }
440 }
441}
442
443impl<'a, P, T> TrieView<'a, P, T> {
444 /// Iterate over all elements in the given view (including the element itself), in
445 /// lexicographic order.
446 ///
447 /// ```
448 /// # use prefix_trie::*;
449 /// # #[cfg(feature = "ipnet")]
450 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
451 ///
452 /// # #[cfg(feature = "ipnet")]
453 /// # {
454 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
455 /// (net!("192.168.0.0/20"), 1),
456 /// (net!("192.168.0.0/22"), 2),
457 /// (net!("192.168.0.0/24"), 3),
458 /// (net!("192.168.2.0/23"), 4),
459 /// ]);
460 /// let sub = map.view_at(net!("192.168.0.0/22")).unwrap();
461 /// assert_eq!(
462 /// sub.iter().collect::<Vec<_>>(),
463 /// vec![
464 /// (&net!("192.168.0.0/22"), &2),
465 /// (&net!("192.168.0.0/24"), &3),
466 /// (&net!("192.168.2.0/23"), &4),
467 /// ]
468 /// );
469 /// # }
470 /// ```
471 pub fn iter(&self) -> Iter<'a, P, T> {
472 Iter::new(self.table, vec![self.loc.idx()])
473 }
474
475 /// Iterate over all keys in the given view (including the element itself), in lexicographic
476 /// order.
477 ///
478 /// ```
479 /// # use prefix_trie::*;
480 /// # #[cfg(feature = "ipnet")]
481 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
482 ///
483 /// # #[cfg(feature = "ipnet")]
484 /// # {
485 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
486 /// (net!("192.168.0.0/20"), 1),
487 /// (net!("192.168.0.0/22"), 2),
488 /// (net!("192.168.0.0/24"), 3),
489 /// (net!("192.168.2.0/23"), 4),
490 /// ]);
491 /// let sub = map.view_at(net!("192.168.0.0/22")).unwrap();
492 /// assert_eq!(
493 /// sub.keys().collect::<Vec<_>>(),
494 /// vec![&net!("192.168.0.0/22"), &net!("192.168.0.0/24"), &net!("192.168.2.0/23")]
495 /// );
496 /// # }
497 /// ```
498 pub fn keys(&self) -> Keys<'a, P, T> {
499 Keys { inner: self.iter() }
500 }
501
502 /// Iterate over all values in the given view (including the element itself), in lexicographic
503 /// order.
504 ///
505 /// ```
506 /// # use prefix_trie::*;
507 /// # #[cfg(feature = "ipnet")]
508 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
509 ///
510 /// # #[cfg(feature = "ipnet")]
511 /// # {
512 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
513 /// (net!("192.168.0.0/20"), 1),
514 /// (net!("192.168.0.0/22"), 2),
515 /// (net!("192.168.0.0/24"), 3),
516 /// (net!("192.168.2.0/23"), 4),
517 /// ]);
518 /// let sub = map.view_at(net!("192.168.0.0/22")).unwrap();
519 /// assert_eq!(sub.values().collect::<Vec<_>>(), vec![&2, &3, &4]);
520 /// # }
521 /// ```
522 pub fn values(&self) -> Values<'a, P, T> {
523 Values { inner: self.iter() }
524 }
525
526 /// Get a reference to the prefix that is currently pointed at. This prefix might not exist
527 /// explicitly in the map/set, but may be used as a branching node (or when you call
528 /// `remove_keep_tree`).
529 ///
530 /// ```
531 /// # use prefix_trie::*;
532 /// # #[cfg(feature = "ipnet")]
533 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
534 ///
535 /// # #[cfg(feature = "ipnet")]
536 /// # {
537 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
538 /// (net!("192.168.0.0/20"), 1),
539 /// (net!("192.168.0.0/22"), 2),
540 /// ]);
541 ///
542 /// assert_eq!(map.view_at(net!("192.168.0.0/20")).unwrap().prefix(), &net!("192.168.0.0/20"));
543 /// assert_eq!(map.view_at(net!("192.168.0.0/21")).unwrap().prefix(), &net!("192.168.0.0/21"));
544 /// assert_eq!(map.view_at(net!("192.168.0.0/22")).unwrap().prefix(), &net!("192.168.0.0/22"));
545 /// # }
546 /// ```
547 pub fn prefix(&self) -> &P {
548 match &self.loc {
549 ViewLoc::Node(idx) => &self.table[*idx].prefix,
550 ViewLoc::Virtual(p, _) => p,
551 }
552 }
553
554 /// Get a reference to the value at the root of the current view. This function may return
555 /// `None` if `self` is pointing at a branching node.
556 ///
557 /// ```
558 /// # use prefix_trie::*;
559 /// # #[cfg(feature = "ipnet")]
560 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
561 ///
562 /// # #[cfg(feature = "ipnet")]
563 /// # {
564 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
565 /// (net!("192.168.0.0/20"), 1),
566 /// (net!("192.168.0.0/22"), 2),
567 /// ]);
568 ///
569 /// assert_eq!(map.view_at(net!("192.168.0.0/20")).unwrap().value(), Some(&1));
570 /// assert_eq!(map.view_at(net!("192.168.0.0/21")).unwrap().value(), None);
571 /// assert_eq!(map.view_at(net!("192.168.0.0/22")).unwrap().value(), Some(&2));
572 /// # }
573 /// ```
574 pub fn value(&self) -> Option<&'a T> {
575 match &self.loc {
576 ViewLoc::Node(idx) => self.table[*idx].value.as_ref(),
577 ViewLoc::Virtual(_, _) => None,
578 }
579 }
580
581 /// Get a reference to both the prefix and the value. This function may return `None` if either
582 /// `self` is pointing at a branching node.
583 ///
584 /// ```
585 /// # use prefix_trie::*;
586 /// # #[cfg(feature = "ipnet")]
587 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
588 ///
589 /// # #[cfg(feature = "ipnet")]
590 /// # {
591 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
592 /// (net!("192.168.0.0/20"), 1),
593 /// (net!("192.168.0.0/22"), 2),
594 /// ]);
595 ///
596 /// assert_eq!(
597 /// map.view_at(net!("192.168.0.0/20")).unwrap().prefix_value(),
598 /// Some((&net!("192.168.0.0/20"), &1))
599 /// );
600 /// assert_eq!(map.view_at(net!("192.168.0.0/21")).unwrap().prefix_value(), None);
601 /// # }
602 /// ```
603 pub fn prefix_value(&self) -> Option<(&'a P, &'a T)> {
604 match &self.loc {
605 ViewLoc::Node(idx) => self.table[*idx].prefix_value(),
606 ViewLoc::Virtual(_, _) => None,
607 }
608 }
609}
610
611impl<'a, P, T> IntoIterator for TrieView<'a, P, T> {
612 type Item = (&'a P, &'a T);
613 type IntoIter = Iter<'a, P, T>;
614
615 fn into_iter(self) -> Self::IntoIter {
616 self.iter()
617 }
618}
619
620/// A trait for creating a [`TrieViewMut`] of `self`.
621pub trait AsViewMut<'a, P: Prefix, T>: Sized {
622 /// Get a mutable view rooted at the origin (referencing the entire trie).
623 fn view_mut(self) -> TrieViewMut<'a, P, T>;
624
625 /// Get a mutable view rooted at the given `prefix`. If that `prefix` is not part of the trie, `None`
626 /// is returned. Calling this function is identical to `self.view().find(prefix)`.
627 fn view_mut_at(self, prefix: P) -> Option<TrieViewMut<'a, P, T>> {
628 self.view_mut().find(prefix).ok()
629 }
630}
631
632impl<'a, P: Prefix, T> AsViewMut<'a, P, T> for TrieViewMut<'a, P, T> {
633 fn view_mut(self) -> TrieViewMut<'a, P, T> {
634 self
635 }
636}
637
638impl<'a, P: Prefix, T> AsViewMut<'a, P, T> for &'a mut PrefixMap<P, T> {
639 fn view_mut(self) -> TrieViewMut<'a, P, T> {
640 // Safety: We borrow the prefixmap mutably here. Thus, this is the only mutable reference,
641 // and we can create such a view to the root (referencing the entire tree mutably).
642 unsafe { TrieViewMut::new(&self.table, ViewLoc::Node(0)) }
643 }
644}
645
646impl<'a, P: Prefix> AsViewMut<'a, P, ()> for &'a mut PrefixSet<P> {
647 fn view_mut(self) -> TrieViewMut<'a, P, ()> {
648 self.0.view_mut()
649 }
650}
651
652/// A mutable view of a prefix-trie rooted at a specific node.
653///
654/// **Note**: You can get a `TrieView` from `TrieViewMut` by calling [`AsView::view`]. This will
655/// create a view that has an immutable reference to the mutable view. This allows you to temprarily
656/// borrow the subtrie immutably (to perform set operations). Once all references are dropped, you
657/// can still use the mutable reference.
658///
659/// ```
660/// # use prefix_trie::*;
661/// # #[cfg(feature = "ipnet")]
662/// # macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
663/// # #[cfg(feature = "ipnet")]
664/// # {
665/// # let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
666/// # (net!("192.168.0.0/20"), 1),
667/// # (net!("192.168.0.0/22"), 2),
668/// # (net!("192.168.0.0/24"), 3),
669/// # (net!("192.168.2.0/23"), 4),
670/// # ]);
671/// # let other: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
672/// # (net!("192.168.0.0/22"), 10),
673/// # (net!("192.168.0.0/23"), 20),
674/// # (net!("192.168.2.0/24"), 30),
675/// # ]);
676/// let mut view: TrieViewMut<_, _> = // ...;
677/// # map.view_mut();
678/// // find the first element that is in the view and in another map.
679/// if let Some((p, _, _)) = view.view().union(&other).find_map(|u| u.both()) {
680/// // remove that element from the map.
681/// let p = p.clone();
682/// view.find(p).unwrap().remove();
683/// }
684/// # }
685/// ```
686///
687/// The view can point to one of three possible things:
688/// - A node in the tree that is actually present in the map,
689/// - A branching node that does not exist in the map, but is needed for the tree structure (or that
690/// was deleted using the function `remove_keep_tree`)
691/// - A virtual node that does not exist as a node in the tree. This is only the case if you call
692/// [`TrieViewMut::find`] or [`AsViewMut::view_mut_at`] with a node that is not present in the
693/// tree, but that contains elements present in the tree. Virtual nodes are treated as if they are
694/// actually present in the tree as branching.
695pub struct TrieViewMut<'a, P, T> {
696 table: &'a Table<P, T>,
697 loc: ViewLoc<P>,
698}
699
700impl<'a, P, T> TrieViewMut<'a, P, T> {
701 /// # Safety
702 /// - First, ensure that `'a` is tied to a mutable reference `&'a Table<P, T>`.
703 /// - Second, you must guarantee that, if multiple `TrieViewMut` exist, all of them point to
704 /// nodes that are located on separate sub-trees. You must guarantee that no `TrieViewMut` is
705 /// contained within another `TrieViewMut` or `TrieView`. Also, you must guarantee that no
706 /// `TrieView` is contained within a `TrieViewMut`.
707 unsafe fn new(table: &'a Table<P, T>, loc: ViewLoc<P>) -> Self {
708 Self { table, loc }
709 }
710}
711
712impl<P: std::fmt::Debug, T: std::fmt::Debug> std::fmt::Debug for TrieViewMut<'_, P, T> {
713 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
714 f.debug_tuple("ViewMut").field(self.prefix()).finish()
715 }
716}
717
718impl<P, L, Rhs> PartialEq<Rhs> for TrieViewMut<'_, P, L>
719where
720 P: Prefix + PartialEq + Clone,
721 L: PartialEq<Rhs::T>,
722 Rhs: crate::AsView<P = P>,
723{
724 fn eq(&self, other: &Rhs) -> bool {
725 self.view()
726 .iter()
727 .zip(other.view().iter())
728 .all(|((lp, lt), (rp, rt))| lt == rt && lp == rp)
729 }
730}
731
732impl<P, T> Eq for TrieViewMut<'_, P, T>
733where
734 P: Prefix + Eq + Clone,
735 T: Eq,
736{
737}
738
739impl<P, T> TrieViewMut<'_, P, T>
740where
741 P: Prefix,
742{
743 /// Find `prefix`, returning a new view that points to the first node that is contained
744 /// within that prefix (or `prefix` itself). Only the current view is searched. If `prefix`
745 /// is not present in the current view referenced by `self` (including any sub-prefix of
746 /// `prefix`), the function returns the previous view as `Err(self)`.
747 ///
748 /// ```
749 /// # use prefix_trie::*;
750 /// # #[cfg(feature = "ipnet")]
751 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
752 ///
753 /// # #[cfg(feature = "ipnet")]
754 /// # {
755 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
756 /// (net!("192.168.0.0/20"), 1),
757 /// (net!("192.168.0.0/22"), 2),
758 /// (net!("192.168.0.0/24"), 3),
759 /// (net!("192.168.2.0/23"), 4),
760 /// (net!("192.168.4.0/22"), 5),
761 /// ]);
762 /// map.view_mut().find(net!("192.168.0.0/21")).unwrap().values_mut().for_each(|x| *x += 10);
763 /// assert_eq!(
764 /// map.into_iter().collect::<Vec<_>>(),
765 /// vec![
766 /// (net!("192.168.0.0/20"), 1),
767 /// (net!("192.168.0.0/22"), 12),
768 /// (net!("192.168.0.0/24"), 13),
769 /// (net!("192.168.2.0/23"), 14),
770 /// (net!("192.168.4.0/22"), 15),
771 /// ]
772 /// );
773 /// # }
774 /// ```
775 pub fn find(self, prefix: P) -> Result<Self, Self> {
776 // Safety: We own the entire sub-tree, including `idx` (which was reached from
777 // `self.idx`). Here, we return a new TrieViewMut pointing to that node (which
778 // is still not covered by any other view), while dropping `self`.
779
780 let mut idx = self.loc.idx();
781 loop {
782 match self.table.get_direction_for_insert(idx, &prefix) {
783 DirectionForInsert::Enter { next, .. } => {
784 idx = next;
785 }
786 DirectionForInsert::Reached => {
787 let new_loc = ViewLoc::Node(idx);
788 return unsafe { Ok(Self::new(self.table, new_loc)) };
789 }
790 DirectionForInsert::NewChild { right, .. } => {
791 // view at a virtual node between idx and the right child of idx.
792 let new_loc =
793 ViewLoc::Virtual(prefix, self.table.get_child(idx, right).unwrap());
794 return unsafe { Ok(Self::new(self.table, new_loc)) };
795 }
796 DirectionForInsert::NewLeaf { .. } | DirectionForInsert::NewBranch { .. } => {
797 return Err(self)
798 }
799 }
800 }
801 }
802
803 /// Find `prefix`, returning a new view that points to that node. Only the current view is
804 /// searched. If this prefix is not present in the view pointed to by `self`, the function
805 /// returns the previous view as `Err(self)`.
806 ///
807 /// ```
808 /// # use prefix_trie::*;
809 /// # #[cfg(feature = "ipnet")]
810 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
811 ///
812 /// # #[cfg(feature = "ipnet")]
813 /// # {
814 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
815 /// (net!("192.168.0.0/20"), 1),
816 /// (net!("192.168.0.0/22"), 2),
817 /// (net!("192.168.0.0/24"), 3),
818 /// (net!("192.168.2.0/23"), 4),
819 /// (net!("192.168.4.0/22"), 5),
820 /// ]);
821 /// assert!(map.view_mut().find_exact(&net!("192.168.0.0/21")).is_err());
822 /// map.view_mut().find_exact(&net!("192.168.0.0/22")).unwrap().values_mut().for_each(|x| *x += 10);
823 /// assert_eq!(
824 /// map.into_iter().collect::<Vec<_>>(),
825 /// vec![
826 /// (net!("192.168.0.0/20"), 1),
827 /// (net!("192.168.0.0/22"), 12),
828 /// (net!("192.168.0.0/24"), 13),
829 /// (net!("192.168.2.0/23"), 14),
830 /// (net!("192.168.4.0/22"), 5),
831 /// ]
832 /// );
833 /// # }
834 /// ```
835 ///
836 /// If the node does not exist, then the function returns the original view:
837 ///
838 /// ```
839 /// # use prefix_trie::*;
840 /// # #[cfg(feature = "ipnet")]
841 /// # macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
842 /// # #[cfg(feature = "ipnet")]
843 /// # {
844 /// let mut map: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::from_iter([(net!("192.168.0.0/20"), 1)]);
845 /// let view_mut = map.view_mut();
846 /// let view = view_mut.find_exact(&net!("10.0.0.0/8")).unwrap_err();
847 /// assert_eq!(view.view().iter().collect::<Vec<_>>(), vec![(&net!("192.168.0.0/20"), &1)]);
848 /// # }
849 /// ```
850 pub fn find_exact(self, prefix: &P) -> Result<Self, Self> {
851 let mut idx = self.loc.idx();
852 loop {
853 match self.table.get_direction(idx, prefix) {
854 Direction::Reached => {
855 return if self.table[idx].value.is_some() {
856 // Safety: We own the entire sub-tree, including `idx` (which was reached
857 // from `self.idx`). Here, we return a new TrieViewMut pointing to that node
858 // (which is still not covered by any other view), while dropping `self`.
859 unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx))) }
860 } else {
861 Err(self)
862 };
863 }
864 Direction::Enter { next, .. } => idx = next,
865 Direction::Missing => return Err(self),
866 }
867 }
868 }
869
870 /// Find the longest match of `prefix`, returning a new view that points to that node. Only
871 /// the given view is searched. If the prefix is not present in the view pointed to by
872 /// `self`, the function returns the previous view as `Err(self)`.
873 ///
874 /// Only views to nodes that are present in the map are returned, not to branching nodes.
875 ///
876 /// ```
877 /// # use prefix_trie::*;
878 /// # #[cfg(feature = "ipnet")]
879 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
880 ///
881 /// # #[cfg(feature = "ipnet")]
882 /// # {
883 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
884 /// (net!("192.168.0.0/20"), 1),
885 /// (net!("192.168.0.0/22"), 2),
886 /// (net!("192.168.0.0/24"), 3),
887 /// (net!("192.168.2.0/23"), 4),
888 /// (net!("192.168.4.0/22"), 5),
889 /// ]);
890 /// map.view_mut().find_lpm(&net!("192.168.0.0/22")).unwrap().values_mut().for_each(|x| *x += 10);
891 /// map.view_mut().find_lpm(&net!("192.168.0.0/23")).unwrap().values_mut().for_each(|x| *x += 100);
892 /// assert_eq!(
893 /// map.into_iter().collect::<Vec<_>>(),
894 /// vec![
895 /// (net!("192.168.0.0/20"), 1),
896 /// (net!("192.168.0.0/22"), 112),
897 /// (net!("192.168.0.0/24"), 113),
898 /// (net!("192.168.2.0/23"), 114),
899 /// (net!("192.168.4.0/22"), 5),
900 /// ]
901 /// );
902 /// # }
903 /// ```
904 ///
905 /// If the node does not exist, then the function returns the original view:
906 ///
907 /// ```
908 /// # use prefix_trie::*;
909 /// # #[cfg(feature = "ipnet")]
910 /// # macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
911 /// # #[cfg(feature = "ipnet")]
912 /// # {
913 /// let mut map: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::from_iter([(net!("192.168.0.0/20"), 1)]);
914 /// let view_mut = map.view_mut();
915 /// let view = view_mut.find_lpm(&net!("10.0.0.0/8")).unwrap_err();
916 /// assert_eq!(view.view().iter().collect::<Vec<_>>(), vec![(&net!("192.168.0.0/20"), &1)]);
917 /// # }
918 /// ```
919 pub fn find_lpm(self, prefix: &P) -> Result<Self, Self> {
920 let mut idx = self.loc.idx();
921 let mut best_match = None;
922 loop {
923 if self.table[idx].value.is_some() {
924 best_match = Some(idx);
925 }
926 match self.table.get_direction(idx, prefix) {
927 Direction::Enter { next, .. } => idx = next,
928 _ => {
929 return if let Some(idx) = best_match {
930 // Safety: We own the entire sub-tree, including `idx` (which was reached
931 // from `self.idx`). Here, we return a new TrieViewMut pointing to that node
932 // (which is still not covered by any other view), while dropping `self`.
933 unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx))) }
934 } else {
935 Err(self)
936 };
937 }
938 }
939 }
940 }
941
942 /// Get the left branch at the current view. The right branch contains all prefix that are
943 /// contained within `self.prefix()`, and for which the next bit is set to 0. If the node has no
944 /// children to the left, the function will return the previous view as `Err(self)`.
945 ///
946 /// ```
947 /// # use prefix_trie::*;
948 /// # #[cfg(feature = "ipnet")]
949 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
950 ///
951 /// # #[cfg(feature = "ipnet")]
952 /// # {
953 /// let mut map: PrefixSet<ipnet::Ipv4Net> = PrefixSet::from_iter([
954 /// net!("1.0.0.0/8"),
955 /// net!("1.0.0.0/16"),
956 /// net!("1.0.128.0/17"),
957 /// net!("1.1.0.0/16"),
958 /// ]);
959 ///
960 /// let view = map.view_mut_at(net!("1.0.0.0/8")).unwrap();
961 /// assert_eq!(view.prefix(), &net!("1.0.0.0/8"));
962 ///
963 /// let view = view.left().unwrap();
964 /// assert_eq!(view.prefix(), &net!("1.0.0.0/15"));
965 ///
966 /// let view = view.left().unwrap();
967 /// assert_eq!(view.prefix(), &net!("1.0.0.0/16"));
968 ///
969 /// assert!(view.left().is_err());
970 /// # }
971 /// ```
972 pub fn left(self) -> Result<Self, Self> {
973 // Safety: We assume `self` was created while satisfying the safety conditions from
974 // `TrieViewMut::new`. Thus, `self` is the only TrieView referencing that root. Here, we
975 // construct a new `TrieViewMut` of the left child while destroying `self`, and thus,
976 // the safety conditions remain satisfied.
977
978 let left_idx = match &self.loc {
979 ViewLoc::Node(idx) => self.table[*idx].left,
980 ViewLoc::Virtual(p, idx) => {
981 // first, check if the node is on the left of the virtual one.
982 if !to_right(p, &self.table[*idx].prefix) {
983 Some(*idx)
984 } else {
985 None
986 }
987 }
988 };
989
990 if let Some(idx) = left_idx {
991 unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx))) }
992 } else {
993 Err(self)
994 }
995 }
996
997 /// Get the right branch at the current view. The right branch contains all prefix that are
998 /// contained within `self.prefix()`, and for which the next bit is set to 1. If the node has no
999 /// children to the right, the function will return the previous view as `Err(self)`.
1000 ///
1001 /// ```
1002 /// # use prefix_trie::*;
1003 /// # #[cfg(feature = "ipnet")]
1004 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1005 ///
1006 /// # #[cfg(feature = "ipnet")]
1007 /// # {
1008 /// let mut map: PrefixSet<ipnet::Ipv4Net> = PrefixSet::from_iter([
1009 /// net!("1.0.0.0/8"),
1010 /// net!("1.0.0.0/16"),
1011 /// net!("1.1.0.0/16"),
1012 /// net!("1.1.0.0/24"),
1013 /// ]);
1014 ///
1015 /// let view = map.view_mut_at(net!("1.0.0.0/8")).unwrap();
1016 /// assert_eq!(view.prefix(), &net!("1.0.0.0/8"));
1017 ///
1018 /// let view = view.right().unwrap_err(); // there is no view on the right.
1019 /// assert_eq!(view.prefix(), &net!("1.0.0.0/8"));
1020 ///
1021 /// let view = view.left().unwrap();
1022 /// assert_eq!(view.prefix(), &net!("1.0.0.0/15"));
1023 ///
1024 /// let view = view.right().unwrap();
1025 /// assert_eq!(view.prefix(), &net!("1.1.0.0/16"));
1026 ///
1027 /// assert!(view.right().is_err());
1028 /// # }
1029 /// ```
1030 pub fn right(self) -> Result<Self, Self> {
1031 // Safety: We assume `self` was created while satisfying the safety conditions from
1032 // `TrieViewMut::new`. Thus, `self` is the only TrieView referencing that root. Here, we
1033 // construct a new `TrieViewMut` of the right child while destroying `self`, and thus,
1034 // the safety conditions remain satisfied.
1035
1036 let right_idx = match &self.loc {
1037 ViewLoc::Node(idx) => self.table[*idx].right,
1038 ViewLoc::Virtual(p, idx) => {
1039 // first, check if the node is on the right of the virtual one.
1040 if to_right(p, &self.table[*idx].prefix) {
1041 Some(*idx)
1042 } else {
1043 None
1044 }
1045 }
1046 };
1047
1048 if let Some(idx) = right_idx {
1049 unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx))) }
1050 } else {
1051 Err(self)
1052 }
1053 }
1054
1055 /// Returns `True` whether `self` has children to the left.
1056 ///
1057 /// ```
1058 /// # use prefix_trie::*;
1059 /// # #[cfg(feature = "ipnet")]
1060 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1061 ///
1062 /// # #[cfg(feature = "ipnet")]
1063 /// # {
1064 /// let mut map: PrefixSet<ipnet::Ipv4Net> = PrefixSet::from_iter([
1065 /// net!("1.0.0.0/8"),
1066 /// net!("1.0.0.0/9"),
1067 /// ]);
1068 ///
1069 /// assert!(map.view_mut_at(net!("1.0.0.0/8")).unwrap().has_left());
1070 /// assert!(!map.view_mut_at(net!("1.0.0.0/9")).unwrap().has_left());
1071 /// # }
1072 /// ```
1073 pub fn has_left(&self) -> bool {
1074 match &self.loc {
1075 ViewLoc::Node(idx) => self.table[*idx].left.is_some(),
1076 ViewLoc::Virtual(p, idx) => {
1077 // first, check if the node is on the right of the virtual one.
1078 !to_right(p, &self.table[*idx].prefix)
1079 }
1080 }
1081 }
1082
1083 /// Returns `True` whether `self` has children to the right.
1084 ///
1085 /// ```
1086 /// # use prefix_trie::*;
1087 /// # #[cfg(feature = "ipnet")]
1088 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1089 ///
1090 /// # #[cfg(feature = "ipnet")]
1091 /// # {
1092 /// let mut map: PrefixSet<ipnet::Ipv4Net> = PrefixSet::from_iter([
1093 /// net!("1.0.0.0/8"),
1094 /// net!("1.128.0.0/9"),
1095 /// ]);
1096 ///
1097 /// assert!(map.view_mut_at(net!("1.0.0.0/8")).unwrap().has_right());
1098 /// assert!(!map.view_mut_at(net!("1.128.0.0/9")).unwrap().has_right());
1099 /// # }
1100 /// ```
1101 pub fn has_right(&self) -> bool {
1102 match &self.loc {
1103 ViewLoc::Node(idx) => self.table[*idx].right.is_some(),
1104 ViewLoc::Virtual(p, idx) => {
1105 // first, check if the node is on the right of the virtual one.
1106 to_right(p, &self.table[*idx].prefix)
1107 }
1108 }
1109 }
1110
1111 /// Split `self` into two views, one pointing to the left and one pointing to the right child.
1112 ///
1113 /// ```
1114 /// # use prefix_trie::*;
1115 /// # #[cfg(feature = "ipnet")]
1116 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1117 ///
1118 /// # #[cfg(feature = "ipnet")]
1119 /// # {
1120 /// let mut map: PrefixMap<ipnet::Ipv4Net, &'static str> = PrefixMap::from_iter([
1121 /// (net!("1.0.0.0/8"), "a"),
1122 /// (net!("1.0.0.0/9"), "b"),
1123 /// (net!("1.128.0.0/9"), "c"),
1124 /// (net!("1.128.0.0/10"), "d"),
1125 /// ]);
1126 ///
1127 /// let view_at_a = map.view_mut_at(net!("1.0.0.0/8")).unwrap();
1128 /// assert_eq!(view_at_a.value(), Some(&"a"));
1129 ///
1130 /// let (Some(view_at_b), Some(view_at_c)) = view_at_a.split() else { unreachable!() };
1131 /// assert_eq!(view_at_b.value(), Some(&"b"));
1132 /// assert_eq!(view_at_c.value(), Some(&"c"));
1133 ///
1134 /// let (Some(view_at_d), None) = view_at_c.split() else { unreachable!() };
1135 /// assert_eq!(view_at_d.value(), Some(&"d"));
1136 /// # }
1137 /// ```
1138 pub fn split(self) -> (Option<Self>, Option<Self>) {
1139 let (left, right) = match &self.loc {
1140 ViewLoc::Node(idx) => (self.table[*idx].left, self.table[*idx].right),
1141 ViewLoc::Virtual(p, idx) => {
1142 // check if the node is on the right or the left of the virtual one.
1143 if to_right(p, &self.table[*idx].prefix) {
1144 (None, Some(*idx))
1145 } else {
1146 (Some(*idx), None)
1147 }
1148 }
1149 };
1150
1151 // Safety: We assume `self` was created while satisfying the safety conditions from
1152 // `TrieViewMut::new`. Thus, `self` is the only TrieView referencing that root. Here, we
1153 // construct two new `TrieViewMut`s, one on the left and one on the right. Thus, they are
1154 // siblings and don't overlap. Further, we destroy `self`, ensuring that the safety
1155 // guarantees remain satisfied.
1156 unsafe {
1157 (
1158 left.map(|idx| Self::new(self.table, ViewLoc::Node(idx))),
1159 right.map(|idx| Self::new(self.table, ViewLoc::Node(idx))),
1160 )
1161 }
1162 }
1163}
1164
1165impl<P, T> TrieViewMut<'_, P, T> {
1166 /// Iterate over all elements in the given view (including the element itself), in
1167 /// lexicographic order, with a mutable reference to the value.
1168 ///
1169 /// ```
1170 /// # use prefix_trie::*;
1171 /// # #[cfg(feature = "ipnet")]
1172 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1173 ///
1174 /// # #[cfg(feature = "ipnet")]
1175 /// # {
1176 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1177 /// (net!("1.0.0.0/8"), 1),
1178 /// (net!("1.0.0.0/16"), 2),
1179 /// (net!("1.0.1.0/24"), 3),
1180 /// (net!("1.1.0.0/16"), 4),
1181 /// ]);
1182 ///
1183 /// map.view_mut_at(net!("1.0.0.0/16")).unwrap().iter_mut().for_each(|(_, x)| *x *= 10);
1184 /// assert_eq!(
1185 /// map.into_iter().collect::<Vec<_>>(),
1186 /// vec![
1187 /// (net!("1.0.0.0/8"), 1),
1188 /// (net!("1.0.0.0/16"), 20),
1189 /// (net!("1.0.1.0/24"), 30),
1190 /// (net!("1.1.0.0/16"), 4),
1191 /// ]
1192 /// );
1193 /// # }
1194 /// ```
1195 pub fn iter_mut(&mut self) -> IterMut<'_, P, T> {
1196 // Safety: Here, we assume the TrieView was created using the `TrieViewMut::new` function,
1197 // and that the safety conditions from that function were satisfied. These safety conditions
1198 // comply with the safety conditions from `IterMut::new()`. Further, `self` is borrowed
1199 // mutably for the lifetime of the mutable iterator.
1200 unsafe { IterMut::new(self.table, vec![self.loc.idx()]) }
1201 }
1202
1203 /// Iterate over mutable references to all values in the given view (including the element
1204 /// itself), in lexicographic order.
1205 ///
1206 /// ```
1207 /// # use prefix_trie::*;
1208 /// # #[cfg(feature = "ipnet")]
1209 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1210 ///
1211 /// # #[cfg(feature = "ipnet")]
1212 /// # {
1213 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1214 /// (net!("192.168.0.0/20"), 1),
1215 /// (net!("192.168.0.0/22"), 2),
1216 /// (net!("192.168.0.0/24"), 3),
1217 /// (net!("192.168.2.0/23"), 4),
1218 /// ]);
1219 ///
1220 /// map.view_mut_at(net!("192.168.0.0/22")).unwrap().values_mut().for_each(|x| *x *= 10);
1221 /// assert_eq!(
1222 /// map.into_iter().collect::<Vec<_>>(),
1223 /// vec![
1224 /// (net!("192.168.0.0/20"), 1),
1225 /// (net!("192.168.0.0/22"), 20),
1226 /// (net!("192.168.0.0/24"), 30),
1227 /// (net!("192.168.2.0/23"), 40),
1228 /// ]
1229 /// );
1230 /// # }
1231 /// ```
1232 pub fn values_mut(&mut self) -> ValuesMut<'_, P, T> {
1233 ValuesMut {
1234 inner: self.iter_mut(),
1235 }
1236 }
1237
1238 /// Get a reference to the prefix that is currently pointed at. This prefix might not exist
1239 /// explicitly in the map/set. Instead, it might be a branching or a virtual node. In both
1240 /// cases, this function returns the prefix of that node.
1241 ///
1242 /// ```
1243 /// # use prefix_trie::*;
1244 /// # #[cfg(feature = "ipnet")]
1245 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1246 ///
1247 /// # #[cfg(feature = "ipnet")]
1248 /// # {
1249 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1250 /// (net!("1.0.0.0/20"), 1),
1251 /// (net!("1.0.0.0/22"), 2),
1252 /// ]);
1253 ///
1254 /// assert_eq!(map.view_mut_at(net!("1.0.0.0/20")).unwrap().prefix(), &net!("1.0.0.0/20"));
1255 /// assert_eq!(map.view_mut_at(net!("1.0.0.0/21")).unwrap().prefix(), &net!("1.0.0.0/21"));
1256 /// assert_eq!(map.view_mut_at(net!("1.0.0.0/22")).unwrap().prefix(), &net!("1.0.0.0/22"));
1257 /// # }
1258 /// ```
1259 pub fn prefix(&self) -> &P {
1260 match &self.loc {
1261 ViewLoc::Node(idx) => &self.table[*idx].prefix,
1262 ViewLoc::Virtual(p, _) => p,
1263 }
1264 }
1265
1266 /// Get a reference to the value at the root of the current view. This function may return
1267 /// `None` if `self` is pointing at a branching or a virtual node.
1268 ///
1269 /// ```
1270 /// # use prefix_trie::*;
1271 /// # #[cfg(feature = "ipnet")]
1272 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1273 ///
1274 /// # #[cfg(feature = "ipnet")]
1275 /// # {
1276 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1277 /// (net!("1.0.0.0/20"), 1),
1278 /// (net!("1.0.0.0/22"), 2),
1279 /// ]);
1280 ///
1281 /// assert_eq!(map.view_mut_at(net!("1.0.0.0/20")).unwrap().value(), Some(&1));
1282 /// assert_eq!(map.view_mut_at(net!("1.0.0.0/21")).unwrap().value(), None);
1283 /// assert_eq!(map.view_mut_at(net!("1.0.0.0/22")).unwrap().value(), Some(&2));
1284 /// # }
1285 /// ```
1286 pub fn value(&self) -> Option<&T> {
1287 match &self.loc {
1288 ViewLoc::Node(idx) => self.table[*idx].value.as_ref(),
1289 ViewLoc::Virtual(_, _) => None,
1290 }
1291 }
1292
1293 fn node_mut(&mut self) -> Option<&mut Node<P, T>> {
1294 // Safety: In the following, we assume that the safety conditions of `TrieViewMut::new` were
1295 // satisfied. In that case, we know that we are the only ones owning a mutable reference to
1296 // a tree that contains that root node. Therefore, it is safe to take a mutable reference of
1297 // that value.
1298 match &self.loc {
1299 ViewLoc::Node(idx) => unsafe { Some(self.table.get_mut(*idx)) },
1300 ViewLoc::Virtual(_, _) => None,
1301 }
1302 }
1303
1304 /// Get a mutable reference to the value at the root of the current view. This function may
1305 /// return `None` if `self` is pointing at a branching node.
1306 ///
1307 /// ```
1308 /// # use prefix_trie::*;
1309 /// # #[cfg(feature = "ipnet")]
1310 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1311 ///
1312 /// # #[cfg(feature = "ipnet")]
1313 /// # {
1314 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1315 /// (net!("1.0.0.0/20"), 1),
1316 /// (net!("1.0.0.0/22"), 2),
1317 /// ]);
1318 /// *map.view_mut_at(net!("1.0.0.0/22")).unwrap().value_mut().unwrap() *= 10;
1319 /// assert_eq!(Vec::from_iter(map), vec![(net!("1.0.0.0/20"), 1), (net!("1.0.0.0/22"), 20)]);
1320 /// # }
1321 /// ```
1322 pub fn value_mut(&mut self) -> Option<&mut T> {
1323 self.node_mut()?.value.as_mut()
1324 }
1325
1326 /// Get a reference to both the prefix and the value. This function may return `None` if either
1327 /// `self` is pointing at a branching node.
1328 ///
1329 /// ```
1330 /// # use prefix_trie::*;
1331 /// # #[cfg(feature = "ipnet")]
1332 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1333 ///
1334 /// # #[cfg(feature = "ipnet")]
1335 /// # {
1336 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1337 /// (net!("192.168.0.0/20"), 1),
1338 /// (net!("192.168.0.0/22"), 2),
1339 /// ]);
1340 ///
1341 /// assert_eq!(
1342 /// map.view_mut_at(net!("192.168.0.0/20")).unwrap().prefix_value(),
1343 /// Some((&net!("192.168.0.0/20"), &1))
1344 /// );
1345 /// assert_eq!(map.view_mut_at(net!("192.168.0.0/21")).unwrap().prefix_value(), None);
1346 /// # }
1347 /// ```
1348 pub fn prefix_value(&self) -> Option<(&P, &T)> {
1349 match &self.loc {
1350 ViewLoc::Node(idx) => self.table[*idx].prefix_value(),
1351 ViewLoc::Virtual(_, _) => None,
1352 }
1353 }
1354
1355 /// Get a reference to both the prefix and the value (the latter is mutable). This function may
1356 /// return `None` if either `self` is pointing at a branching node.
1357 ///
1358 /// ```
1359 /// # use prefix_trie::*;
1360 /// # #[cfg(feature = "ipnet")]
1361 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1362 ///
1363 /// # #[cfg(feature = "ipnet")]
1364 /// # {
1365 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1366 /// (net!("1.0.0.0/20"), 1),
1367 /// (net!("1.0.0.0/22"), 2),
1368 /// ]);
1369 /// *map.view_mut_at(net!("1.0.0.0/22")).unwrap().prefix_value_mut().unwrap().1 *= 10;
1370 /// assert_eq!(Vec::from_iter(map), vec![(net!("1.0.0.0/20"), 1), (net!("1.0.0.0/22"), 20)]);
1371 /// # }
1372 /// ```
1373 pub fn prefix_value_mut(&mut self) -> Option<(&P, &mut T)> {
1374 self.node_mut()?.prefix_value_mut()
1375 }
1376
1377 /// Remove the element at the current position of the view. The tree structure is not modified
1378 /// (similar to calling [`PrefixMap::remove_keep_tree`].)
1379 ///
1380 /// ```
1381 /// # use prefix_trie::*;
1382 /// # #[cfg(feature = "ipnet")]
1383 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1384 ///
1385 /// # #[cfg(feature = "ipnet")]
1386 /// # {
1387 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1388 /// (net!("192.168.0.0/20"), 1),
1389 /// (net!("192.168.0.0/22"), 2),
1390 /// (net!("192.168.0.0/24"), 3),
1391 /// (net!("192.168.2.0/23"), 4),
1392 /// (net!("192.168.4.0/22"), 5),
1393 /// ]);
1394 /// let mut view = map.view_mut_at(net!("192.168.0.0/22")).unwrap();
1395 /// assert_eq!(view.remove(), Some(2));
1396 /// assert_eq!(
1397 /// view.into_iter().collect::<Vec<_>>(),
1398 /// vec![
1399 /// (&net!("192.168.0.0/24"), &mut 3),
1400 /// (&net!("192.168.2.0/23"), &mut 4),
1401 /// ]
1402 /// );
1403 /// assert_eq!(
1404 /// map.into_iter().collect::<Vec<_>>(),
1405 /// vec![
1406 /// (net!("192.168.0.0/20"), 1),
1407 /// (net!("192.168.0.0/24"), 3),
1408 /// (net!("192.168.2.0/23"), 4),
1409 /// (net!("192.168.4.0/22"), 5),
1410 /// ]
1411 /// );
1412 /// # }
1413 /// ```
1414 pub fn remove(&mut self) -> Option<T> {
1415 self.node_mut()?.value.take()
1416 }
1417
1418 /// Set the value of the node currently pointed at. This operation fails if the current view
1419 /// points at a virtual node, returning `Err(value)`. In such a case, you may want to go to the
1420 /// next node (e.g., using [`TrieViewMut::split`]).
1421 ///
1422 /// This operation will only modify the value, and keep the prefix unchanged (in contrast to
1423 /// `PrefixMap::insert`).
1424 ///
1425 /// This is an implementation detail of mutable views. Since you can have multiple different
1426 /// mutable views pointing to different parts in the tree, it is not safe to modify the tree
1427 /// structure itself.
1428 ///
1429 /// ```
1430 /// # use prefix_trie::*;
1431 /// # #[cfg(feature = "ipnet")]
1432 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1433 ///
1434 /// # #[cfg(feature = "ipnet")]
1435 /// # {
1436 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1437 /// (net!("192.168.0.0/20"), 1),
1438 /// (net!("192.168.0.0/22"), 2),
1439 /// (net!("192.168.0.0/24"), 3),
1440 /// (net!("192.168.2.0/23"), 4),
1441 /// (net!("192.168.8.0/22"), 5),
1442 /// ]);
1443 /// let mut view = map.view_mut_at(net!("192.168.0.0/22")).unwrap();
1444 /// assert_eq!(view.set(20), Ok(Some(2)));
1445 /// assert_eq!(
1446 /// view.into_iter().collect::<Vec<_>>(),
1447 /// vec![
1448 /// (&net!("192.168.0.0/22"), &mut 20),
1449 /// (&net!("192.168.0.0/24"), &mut 3),
1450 /// (&net!("192.168.2.0/23"), &mut 4),
1451 /// ]
1452 /// );
1453 /// assert_eq!(
1454 /// map.iter().collect::<Vec<_>>(),
1455 /// vec![
1456 /// (&net!("192.168.0.0/20"), &1),
1457 /// (&net!("192.168.0.0/22"), &20),
1458 /// (&net!("192.168.0.0/24"), &3),
1459 /// (&net!("192.168.2.0/23"), &4),
1460 /// (&net!("192.168.8.0/22"), &5),
1461 /// ]
1462 /// );
1463 /// # }
1464 /// ```
1465 ///
1466 /// Calling `set` on a view that points to a virtual node will fail:
1467 ///
1468 /// ```
1469 /// # use prefix_trie::*;
1470 /// # #[cfg(feature = "ipnet")]
1471 /// macro_rules! net { ($x:literal) => {$x.parse::<ipnet::Ipv4Net>().unwrap()}; }
1472 ///
1473 /// # #[cfg(feature = "ipnet")]
1474 /// # {
1475 /// let mut map: PrefixMap<ipnet::Ipv4Net, usize> = PrefixMap::from_iter([
1476 /// (net!("192.168.0.0/24"), 1),
1477 /// (net!("192.168.2.0/24"), 2),
1478 /// ]);
1479 /// assert_eq!(map.view_mut_at(net!("192.168.0.0/23")).unwrap().set(10), Err(10));
1480 /// # }
1481 pub fn set(&mut self, value: T) -> Result<Option<T>, T> {
1482 match self.node_mut() {
1483 Some(n) => Ok(n.value.replace(value)),
1484 None => Err(value),
1485 }
1486 }
1487}
1488
1489impl<'a, P, T> IntoIterator for TrieViewMut<'a, P, T> {
1490 type Item = (&'a P, &'a mut T);
1491 type IntoIter = IterMut<'a, P, T>;
1492
1493 fn into_iter(self) -> Self::IntoIter {
1494 // Safety: Here, we assume the TrieView was created using the `TrieViewMut::new` function,
1495 // and that the safety conditions from that function were satisfied. These safety conditions
1496 // comply with the safety conditions from `IterMut::new()`.
1497 unsafe { IterMut::new(self.table, vec![self.loc.idx()]) }
1498 }
1499}