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