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