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