prefix_trie/trieview/mod.rs
1//! Composable trie-view trait for [`crate::PrefixMap`].
2//!
3//! # Architecture
4//!
5//! [`TrieView`] is a **trait** implemented by any cursor (mutable or immutable)
6//! into a prefix trie:
7//! - [`TrieRef`]: an immutable cursor yielding `&T`
8//! - [`TrieRefMut`]: a mutable cursor yielding `&mut T`
9//! - Composed views: [`IntersectionView`], [`UnionView`], [`CoveringUnionView`],
10//! [`DifferenceView`], [`CoveringDifferenceView`]
11//!
12//! This design makes set operations **composable**:
13//!
14//! ```
15//! # use prefix_trie::{PrefixMap, PrefixSet, AsView, TrieView};
16//! # use prefix_trie::trieview::union::UnionItem;
17//! # type P = (u32, u8);
18//! let mut target: PrefixMap::<P, _> = [((0, 8), 1), ((0, 16), 2), ((0, 24), 3)].into_iter().collect();
19//! let source: PrefixMap::<P, _> = [((0, 8), 9), ((0, 16), 1)].into_iter().collect();
20//! let ignore: PrefixSet::<P> = [ (0, 10)].into_iter().collect();
21//!
22//! (&mut target)
23//! .view()
24//! .union(&source)
25//! .covering_difference(&ignore)
26//! .values()
27//! .for_each(|x| if let UnionItem::Both(l, r) = x {
28//! *l += *r
29//! });
30//!
31//! assert_eq!(
32//! target.into_iter().collect::<Vec<_>>(),
33//! vec![((0, 8), 10), ((0, 16), 2), ((0, 24), 3)], // only (0, 8) got updated
34//! );
35//! ```
36//!
37//! # Safety contract for `get_data`, `get_child`, and `reposition`
38//!
39//! The three unsafe primitives carry the following contracts:
40//!
41//! - **`get_data`**: each `data_bit` must be passed **at most once** per view instance.
42//! - **`get_child`**: each `child_bit` must be passed **at most once** per view instance.
43//! - For mutable views, values reached through different data bits, values reachable through
44//! different child bits, and values stored in a node versus values reachable through its child
45//! views must be disjoint from each other.
46//! - **`reposition`**: the returned cursor shares the same underlying node as `self`.
47//! For mutable views the caller must ensure the two cursors' effective bitmaps are
48//! disjoint, or that the original is not used for data access after the call.
49//!
50//! All default methods uphold these invariants internally.
51//!
52//! # Clone and mutable views
53//!
54//! The `TrieView` trait does **not** require `Self: Clone`. Mutable views
55//! ([`TrieRefMut`]) intentionally do not implement `Clone` to prevent aliasing
56//! `&mut` references. Methods that need to retain an earlier cursor while descending,
57//! such as [`find_lpm`][TrieView::find_lpm], require `Self: Clone`. Methods that
58//! return an element directly, such as [`find_lpm_value`][TrieView::find_lpm_value],
59//! can work with mutable views because they do not need to return a saved cursor.
60//!
61//! Composed views implement `Clone` only when their sides do. This naturally means clone-backed
62//! methods such as [`find_lpm`][TrieView::find_lpm] are unavailable on composed mutable views,
63//! while consuming methods such as [`find_lpm_value`][TrieView::find_lpm_value] remain usable.
64
65// Structural immutability invariant (for maintainers)
66//
67// The node structure of the underlying trie (node allocations, bitmaps, child pointers) must
68// not change for the entire lifetime of any `TrieView` or `TrieRefMut` borrow.
69//
70// Concretely:
71// - No insertions or deletions that would trigger a tier upgrade/downgrade in the node or cell
72// allocators are permitted while a view is alive.
73// - No structural operations (e.g. `insert`, `remove`, `remove_children`, `retain`) may be
74// called on the underlying `PrefixMap` while a view borrows it.
75//
76// For immutable views (TrieRef) this is automatically enforced by Rust's borrow checker:
77// the view holds `&'a Table<T>`, which prevents any `&mut` access to the map.
78//
79// For mutable views (TrieRefMut) the invariant is maintained by holding `&'a Table<T>` for
80// structural reads while using a raw pointer (`RawPtr<T>`) only for data-value mutations.
81// The raw pointer path accesses only the value slots (the flat `cells` array), never any
82// allocation metadata or bitmaps. As long as no two live `&mut T` references alias the same
83// slot — guaranteed by the acyclic tree structure — these raw-pointer value mutations are sound
84// without requiring `&mut Table<T>`.
85
86pub mod covering_difference;
87pub mod covering_union;
88pub mod difference;
89mod equality;
90pub mod intersection;
91pub(crate) mod iter;
92pub mod trie_ref;
93pub mod trie_ref_mut;
94pub mod union;
95
96pub use covering_difference::CoveringDifferenceView;
97pub use covering_union::{CoveringUnionItem, CoveringUnionView};
98pub use difference::DifferenceView;
99pub use intersection::IntersectionView;
100pub use iter::{ViewIter, ViewKeys, ViewValues};
101pub use trie_ref::TrieRef;
102pub use trie_ref_mut::TrieRefMut;
103pub use union::{UnionItem, UnionView};
104
105use num_traits::{One, PrimInt, Zero};
106
107use crate::{
108 prefix::mask_from_prefix_len,
109 Prefix,
110 {
111 node::{child_bit, data_bit, data_lpm_mask, DATA_BIT_TO_PREFIX},
112 table::K,
113 },
114};
115
116/// An immutable or mutable view into a (possibly composed) prefix trie.
117///
118/// # Required methods
119///
120/// Eight methods that concrete and composed views must implement:
121/// - **Position**: [`Self::depth`], [`Self::key`], [`Self::prefix_len`]
122/// - **Bitmaps**: [`Self::data_bitmap`], [`Self::child_bitmap`]
123/// - **Primitives** (unsafe): [`Self::get_data`], [`Self::get_child`], [`Self::reposition`]
124///
125/// # Default methods
126///
127/// All other methods (`left`/`right`/`find`/`find_lpm`/`iter`/etc.) are
128/// provided as defaults built from the eight required methods.
129#[cfg_attr(docsrs, doc(notable_trait))]
130pub trait TrieView<'a>: Sized {
131 /// The prefix type.
132 type P: Prefix;
133 /// The value type yielded by this view (e.g. `&'a T`, `&'a mut T`, `(&'a L, &'a R)`).
134 type T: 'a;
135
136 /// Depth of the underlying `MultiBitNode`: always a multiple of `K`.
137 fn depth(&self) -> u32;
138
139 /// Accumulated key bits; only the top [`prefix_len`][Self::prefix_len] bits are significant.
140 fn key(&self) -> <Self::P as Prefix>::R;
141
142 /// Binary-tree depth of this view's root position (`depth <= prefix_len < depth + K`).
143 fn prefix_len(&self) -> u32;
144
145 /// Effective data bitmap (node bitmap ANDed with cover mask and any set-op filter).
146 ///
147 /// A set bit at position `b` means there is a value accessible via
148 /// [`get_data(b)`][Self::get_data].
149 fn data_bitmap(&self) -> u32;
150
151 /// Effective child bitmap (node bitmap ANDed with cover mask and any set-op filter).
152 ///
153 /// A set bit at position `b` means there is a non-empty sub-trie reachable via
154 /// [`get_child(b)`][Self::get_child].
155 fn child_bitmap(&self) -> u32;
156
157 /// Return the value at `data_bit`.
158 ///
159 /// # Safety
160 /// Each `data_bit` must be passed to this method **at most once** per view instance.
161 /// For mutable views (`T = &'a mut T`), calling with the same bit twice produces two
162 /// aliasing `&'a mut T` references -> undefined behavior.
163 ///
164 /// # Panics
165 /// May panic or return garbage if `data_bit` is not set in [`data_bitmap`][Self::data_bitmap].
166 unsafe fn get_data(&mut self, data_bit: u32) -> Self::T;
167
168 /// Return a child view at `child_bit`.
169 ///
170 /// The returned view has `depth = self.depth() + K`, `prefix_len = self.depth() + K`,
171 /// and `key = extend_repr(self.key(), self.depth(), child_bit)`.
172 ///
173 /// # Safety
174 /// Each `child_bit` must be passed to this method **at most once** per view instance.
175 /// For mutable views, calling with the same bit twice creates two views with overlapping
176 /// mutable access to the same child node -> undefined behavior. Different bits always
177 /// refer to disjoint child nodes and are safe to combine.
178 ///
179 /// # Panics
180 /// May panic if `child_bit` is not set in [`child_bitmap`][Self::child_bitmap].
181 unsafe fn get_child(&mut self, child_bit: u32) -> Self;
182
183 /// Move the cursor to a different location within the same multibit-node.
184 ///
185 /// The underlying node location (and all data pointers) remain unchanged; only the
186 /// position cursor is updated.
187 ///
188 /// # Safety
189 /// For mutable views, the returned cursor shares the same `raw_ptr` and `node_loc`
190 /// as `self`. The caller must ensure that the returned cursor and `self` are never
191 /// simultaneously used to access overlapping data -> either by ensuring their effective
192 /// bitmaps are disjoint or by not accessing `self`'s data after the call (as in
193 /// `navigate_to` and `step`).
194 unsafe fn reposition(&mut self, key: <Self::P as Prefix>::R, prefix_len: u32);
195
196 // -----------------------------------------------------------------------------
197 // Default implementations
198 // -----------------------------------------------------------------------------
199
200 /// Whether the sub-trie rooted at this view position is non-empty.
201 ///
202 /// A shallow bitmap check: `true` means data or children exist worth exploring.
203 /// `false` means the sub-trie is definitely empty.
204 #[inline]
205 fn is_non_empty(&self) -> bool {
206 self.data_bitmap() != 0 || self.child_bitmap() != 0
207 }
208
209 /// Reconstruct the prefix at this view's root position.
210 ///
211 /// ```
212 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
213 /// # #[cfg(feature = "ipnet")]
214 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
215 ///
216 /// # #[cfg(feature = "ipnet")]
217 /// # {
218 /// let mut map = PrefixMap::new();
219 /// map.insert(net!("192.168.0.0/20"), 1);
220 /// map.insert(net!("192.168.0.0/22"), 2);
221 ///
222 /// let view = map.view().find(&net!("192.168.0.0/21")).unwrap();
223 /// assert_eq!(view.prefix(), net!("192.168.0.0/21"));
224 /// # }
225 /// ```
226 #[inline]
227 fn prefix(&self) -> Self::P {
228 let masked = self.key() & mask_from_prefix_len(self.prefix_len() as u8);
229 Self::P::from_repr_len(masked, self.prefix_len() as u8)
230 }
231
232 /// Return the value stored exactly at this view's root position, if any.
233 ///
234 /// This method consumes the view, which makes it suitable for mutable views.
235 ///
236 /// ```
237 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
238 /// # #[cfg(feature = "ipnet")]
239 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
240 ///
241 /// # #[cfg(feature = "ipnet")]
242 /// # {
243 /// let mut map = PrefixMap::new();
244 /// map.insert(net!("192.168.0.0/20"), 1);
245 /// map.insert(net!("192.168.0.0/22"), 2);
246 ///
247 /// assert_eq!(map.view().find_exact(&net!("192.168.0.0/22")).unwrap().value(), Some(&2));
248 /// assert_eq!(map.view().find(&net!("192.168.0.0/21")).unwrap().value(), None);
249 /// # }
250 /// ```
251 #[inline]
252 fn value(mut self) -> Option<Self::T> {
253 let data_bit = data_bit(self.key(), self.prefix_len());
254 if (self.data_bitmap() >> data_bit) & 1 == 1 {
255 // SAFETY: `value` consumes the view and calls `get_data` for one bit.
256 Some(unsafe { self.get_data(data_bit) })
257 } else {
258 None
259 }
260 }
261
262 /// Return the prefix and value stored exactly at this view's root position, if any.
263 ///
264 /// This method consumes the view, which makes it suitable for mutable views.
265 ///
266 /// ```
267 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
268 /// # #[cfg(feature = "ipnet")]
269 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
270 ///
271 /// # #[cfg(feature = "ipnet")]
272 /// # {
273 /// let mut map = PrefixMap::new();
274 /// map.insert(net!("192.168.0.0/22"), 2);
275 ///
276 /// let view = map.view().find_exact(&net!("192.168.0.0/22")).unwrap();
277 /// assert_eq!(view.prefix_value(), Some((net!("192.168.0.0/22"), &2)));
278 /// # }
279 /// ```
280 #[inline]
281 fn prefix_value(mut self) -> Option<(Self::P, Self::T)> {
282 let data_bit = data_bit(self.key(), self.prefix_len());
283 if (self.data_bitmap() >> data_bit) & 1 == 1 {
284 let prefix = self.prefix();
285 // SAFETY: `prefix_value` consumes the view and calls `get_data` for one bit.
286 Some((prefix, unsafe { self.get_data(data_bit) }))
287 } else {
288 None
289 }
290 }
291
292 /// Return a view into the left (0-bit) child sub-trie, or `None` if empty.
293 ///
294 /// ```
295 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
296 /// # #[cfg(feature = "ipnet")]
297 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
298 ///
299 /// # #[cfg(feature = "ipnet")]
300 /// # {
301 /// let mut map = PrefixMap::new();
302 /// map.insert(net!("10.0.0.0/8"), 1);
303 ///
304 /// let left = map.view().left().unwrap();
305 /// assert_eq!(left.prefix(), net!("0.0.0.0/1"));
306 /// assert_eq!(left.keys().collect::<Vec<_>>(), vec![net!("10.0.0.0/8")]);
307 /// # }
308 /// ```
309 #[inline]
310 fn left(self) -> Option<Self> {
311 self.step(false)
312 }
313
314 /// Return a view into the right (1-bit) child sub-trie, or `None` if empty.
315 ///
316 /// ```
317 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
318 /// # #[cfg(feature = "ipnet")]
319 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
320 ///
321 /// # #[cfg(feature = "ipnet")]
322 /// # {
323 /// let mut map = PrefixMap::new();
324 /// map.insert(net!("128.0.0.0/1"), 1);
325 ///
326 /// let right = map.view().right().unwrap();
327 /// assert_eq!(right.prefix(), net!("128.0.0.0/1"));
328 /// assert_eq!(right.value(), Some(&1));
329 /// # }
330 /// ```
331 #[inline]
332 fn right(self) -> Option<Self> {
333 self.step(true)
334 }
335
336 /// Navigate toward `(target_key, target_len)` from this view's node.
337 ///
338 /// Returns `None` if a required child node does not exist in [`child_bitmap`][Self::child_bitmap].
339 fn navigate_to(mut self, target_key: <Self::P as Prefix>::R, target_len: u32) -> Option<Self> {
340 while target_len >= self.depth() + K {
341 let child_bit = child_bit(self.depth(), target_key);
342 if (self.child_bitmap() >> child_bit) & 1 == 0 {
343 return None;
344 }
345 // SAFETY: follows a single path; each child_bit used exactly once per
346 // view instance before view is replaced by the returned child.
347 self = unsafe { self.get_child(child_bit) };
348 }
349 // SAFETY: view is replaced by the repositioned cursor; the old position is
350 // not used for data access after this point.
351 unsafe { self.reposition(target_key, target_len) }
352 Some(self)
353 }
354
355 /// Navigate to `prefix` and return the view if the sub-trie is non-empty.
356 ///
357 /// ```
358 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
359 /// # #[cfg(feature = "ipnet")]
360 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
361 ///
362 /// # #[cfg(feature = "ipnet")]
363 /// # {
364 /// let mut map = PrefixMap::new();
365 /// map.insert(net!("192.168.0.0/20"), 1);
366 /// map.insert(net!("192.168.0.0/22"), 2);
367 /// map.insert(net!("192.168.0.0/24"), 3);
368 ///
369 /// let sub = map.view().find(&net!("192.168.0.0/21")).unwrap();
370 /// assert_eq!(
371 /// sub.keys().collect::<Vec<_>>(),
372 /// vec![net!("192.168.0.0/22"), net!("192.168.0.0/24")]
373 /// );
374 /// # }
375 /// ```
376 #[inline]
377 fn find(self, prefix: &Self::P) -> Option<Self> {
378 let view = self.navigate_to(prefix.mask(), prefix.prefix_len() as u32)?;
379 if view.is_non_empty() {
380 Some(view)
381 } else {
382 None
383 }
384 }
385
386 /// Navigate to `prefix` and return the view only if a value is stored exactly there.
387 ///
388 /// ```
389 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
390 /// # #[cfg(feature = "ipnet")]
391 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
392 ///
393 /// # #[cfg(feature = "ipnet")]
394 /// # {
395 /// let mut map = PrefixMap::new();
396 /// map.insert(net!("192.168.0.0/20"), 1);
397 /// map.insert(net!("192.168.0.0/22"), 2);
398 ///
399 /// assert!(map.view().find_exact(&net!("192.168.0.0/21")).is_none());
400 /// assert_eq!(
401 /// map.view().find_exact(&net!("192.168.0.0/22")).unwrap().value(),
402 /// Some(&2)
403 /// );
404 /// # }
405 /// ```
406 #[inline]
407 fn find_exact(self, prefix: &Self::P) -> Option<Self> {
408 let view = self.navigate_to(prefix.mask(), prefix.prefix_len() as u32)?;
409 let data_bit = data_bit(view.key(), view.prefix_len());
410 if (view.data_bitmap() >> data_bit) & 1 == 1 {
411 Some(view)
412 } else {
413 None
414 }
415 }
416
417 /// Navigate to `prefix` and return its prefix/value pair if a value is stored exactly there.
418 ///
419 /// This method consumes the view and does not require `Self: Clone`, so it also works with
420 /// mutable views.
421 ///
422 /// ```
423 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
424 /// # #[cfg(feature = "ipnet")]
425 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
426 ///
427 /// # #[cfg(feature = "ipnet")]
428 /// # {
429 /// let mut map = PrefixMap::new();
430 /// map.insert(net!("192.168.0.0/22"), 2);
431 ///
432 /// assert_eq!(
433 /// map.view().find_exact_value(&net!("192.168.0.0/22")),
434 /// Some((net!("192.168.0.0/22"), &2))
435 /// );
436 /// assert_eq!(map.view().find_exact_value(&net!("192.168.0.0/21")), None);
437 /// # }
438 /// ```
439 #[inline]
440 fn find_exact_value(self, prefix: &Self::P) -> Option<(Self::P, Self::T)> {
441 let view = self.navigate_to(prefix.mask(), prefix.prefix_len() as u32)?;
442 view.prefix_value()
443 }
444
445 /// Find the view pointing at the longest prefix match for `prefix`.
446 ///
447 /// This method requires `Self: Clone` because the search must remember the best matching view
448 /// while it continues descending toward more-specific prefixes.
449 ///
450 /// ```
451 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
452 /// # #[cfg(feature = "ipnet")]
453 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
454 ///
455 /// # #[cfg(feature = "ipnet")]
456 /// # {
457 /// let mut map = PrefixMap::new();
458 /// map.insert(net!("192.168.0.0/20"), 1);
459 /// map.insert(net!("192.168.0.0/22"), 2);
460 ///
461 /// let view = map.view().find_lpm(&net!("192.168.0.0/21")).unwrap();
462 /// assert_eq!(view.prefix(), net!("192.168.0.0/20"));
463 /// assert_eq!(view.value(), Some(&1));
464 /// # }
465 /// ```
466 fn find_lpm(mut self, prefix: &Self::P) -> Option<Self>
467 where
468 Self: Clone,
469 {
470 let target_key = prefix.mask();
471 let target_len = prefix.prefix_len() as u32;
472 if !contains_key::<Self::P>(self.key(), self.prefix_len(), target_key, target_len) {
473 return None;
474 }
475 let mut best = None;
476
477 loop {
478 if let Some(data_bit) = lpm_data_bit(&self, target_key, target_len) {
479 let prefix = reconstruct_prefix::<Self::P>(self.depth(), self.key(), data_bit);
480 let mut view = self.clone();
481 // SAFETY: the cloned cursor is moved within its current multibit node.
482 unsafe { view.reposition(prefix.mask(), prefix.prefix_len() as u32) };
483 best = Some(view);
484 }
485
486 if target_len < self.depth() + K {
487 return best;
488 }
489
490 let child_bit = child_bit(self.depth(), target_key);
491 if (self.child_bitmap() >> child_bit) & 1 == 0 {
492 return best;
493 }
494
495 // SAFETY: follows a single path; each child bit is used at most once per view.
496 self = unsafe { self.get_child(child_bit) };
497 }
498 }
499
500 /// Find the longest prefix match for `prefix` and return its prefix/value pair.
501 ///
502 /// This method does not require `Self: Clone`; it can therefore be used with views that yield
503 /// mutable references. It consumes the view and only returns the matched element, not a cursor.
504 ///
505 /// ```
506 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
507 /// # #[cfg(feature = "ipnet")]
508 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
509 ///
510 /// # #[cfg(feature = "ipnet")]
511 /// # {
512 /// let mut map = PrefixMap::new();
513 /// map.insert(net!("192.168.0.0/20"), 1);
514 /// map.insert(net!("192.168.0.0/22"), 2);
515 ///
516 /// let (prefix, value) = (&mut map)
517 /// .view()
518 /// .find_lpm_value(&net!("192.168.0.0/21"))
519 /// .unwrap();
520 ///
521 /// assert_eq!(prefix, net!("192.168.0.0/20"));
522 /// *value += 10;
523 /// assert_eq!(map.get(&net!("192.168.0.0/20")), Some(&11));
524 /// # }
525 /// ```
526 fn find_lpm_value(mut self, prefix: &Self::P) -> Option<(Self::P, Self::T)> {
527 let target_key = prefix.mask();
528 let target_len = prefix.prefix_len() as u32;
529 if !contains_key::<Self::P>(self.key(), self.prefix_len(), target_key, target_len) {
530 return None;
531 }
532 let mut best = None;
533
534 loop {
535 if let Some(data_bit) = lpm_data_bit(&self, target_key, target_len) {
536 let prefix = reconstruct_prefix::<Self::P>(self.depth(), self.key(), data_bit);
537 drop(best.take());
538 // SAFETY: each node on the target path is visited at most once, and we keep only
539 // the most-specific matched value.
540 best = Some((prefix, unsafe { self.get_data(data_bit) }));
541 }
542
543 if target_len < self.depth() + K {
544 return best;
545 }
546
547 let child_bit = child_bit(self.depth(), target_key);
548 if (self.child_bitmap() >> child_bit) & 1 == 0 {
549 return best;
550 }
551
552 // SAFETY: follows a single path; each child bit is used at most once per view.
553 self = unsafe { self.get_child(child_bit) };
554 }
555 }
556
557 /// Return an iterator over all `(prefix, value)` pairs in this sub-trie.
558 ///
559 /// ```
560 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
561 /// # #[cfg(feature = "ipnet")]
562 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
563 ///
564 /// # #[cfg(feature = "ipnet")]
565 /// # {
566 /// let mut map = PrefixMap::new();
567 /// map.insert(net!("192.168.0.0/20"), 1);
568 /// map.insert(net!("192.168.0.0/22"), 2);
569 /// map.insert(net!("192.168.0.0/24"), 3);
570 ///
571 /// let sub = map.view().find(&net!("192.168.0.0/22")).unwrap();
572 /// assert_eq!(
573 /// sub.iter().collect::<Vec<_>>(),
574 /// vec![(net!("192.168.0.0/22"), &2), (net!("192.168.0.0/24"), &3)]
575 /// );
576 /// # }
577 /// ```
578 #[inline]
579 fn iter(self) -> ViewIter<'a, Self> {
580 ViewIter::new(self)
581 }
582
583 /// Return an iterator starting at the given prefix in lexicographic order.
584 ///
585 /// If `inclusive` is `true`, the iterator includes the entry at `prefix` (if present).
586 /// If `inclusive` is `false`, the iterator starts after `prefix`.
587 ///
588 /// If `prefix` is not present, the iterator starts at the first entry that would come
589 /// after `prefix` in lexicographic order, regardless of `inclusive`.
590 ///
591 /// ```
592 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
593 /// # #[cfg(feature = "ipnet")]
594 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
595 ///
596 /// # #[cfg(feature = "ipnet")]
597 /// # {
598 /// let mut map = PrefixMap::new();
599 /// map.insert(net!("10.0.0.0/8"), 1);
600 /// map.insert(net!("10.1.0.0/16"), 2);
601 /// map.insert(net!("10.2.0.0/16"), 3);
602 /// map.insert(net!("10.3.0.0/16"), 4);
603 ///
604 /// let page: Vec<_> = map.view().iter_from(&net!("10.1.0.0/16"), false).take(2).collect();
605 /// assert_eq!(page, vec![(net!("10.2.0.0/16"), &3), (net!("10.3.0.0/16"), &4)]);
606 /// # }
607 /// ```
608 #[inline]
609 fn iter_from(self, prefix: &Self::P, inclusive: bool) -> ViewIter<'a, Self> {
610 ViewIter::new_from(self, prefix, inclusive)
611 }
612
613 /// Return an iterator over all prefixes in this sub-trie.
614 ///
615 /// ```
616 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
617 /// # #[cfg(feature = "ipnet")]
618 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
619 ///
620 /// # #[cfg(feature = "ipnet")]
621 /// # {
622 /// let mut map = PrefixMap::new();
623 /// map.insert(net!("192.168.0.0/20"), 1);
624 /// map.insert(net!("192.168.0.0/22"), 2);
625 /// map.insert(net!("192.168.0.0/24"), 3);
626 ///
627 /// let sub = map.view().find(&net!("192.168.0.0/22")).unwrap();
628 /// assert_eq!(
629 /// sub.keys().collect::<Vec<_>>(),
630 /// vec![net!("192.168.0.0/22"), net!("192.168.0.0/24")]
631 /// );
632 /// # }
633 /// ```
634 #[inline]
635 fn keys(self) -> ViewKeys<'a, Self> {
636 ViewKeys::new(self)
637 }
638
639 /// Return an iterator over all values in this sub-trie.
640 ///
641 /// ```
642 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
643 /// # #[cfg(feature = "ipnet")]
644 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
645 ///
646 /// # #[cfg(feature = "ipnet")]
647 /// # {
648 /// let mut map = PrefixMap::new();
649 /// map.insert(net!("192.168.0.0/20"), 1);
650 /// map.insert(net!("192.168.0.0/22"), 2);
651 /// map.insert(net!("192.168.0.0/24"), 3);
652 ///
653 /// let sub = map.view().find(&net!("192.168.0.0/22")).unwrap();
654 /// assert_eq!(sub.values().copied().collect::<Vec<_>>(), vec![2, 3]);
655 /// # }
656 /// ```
657 #[inline]
658 fn values(self) -> ViewValues<'a, Self> {
659 ViewValues::new(self)
660 }
661
662 /// Return the intersection of `self` and `other` as a view, or `None` if disjoint.
663 ///
664 /// The returned [`IntersectionView`] iterates over every prefix present in **both**
665 /// sub-tries, yielding `(prefix, (left_value, right_value))` in lexicographic order.
666 ///
667 /// ```
668 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
669 /// # #[cfg(feature = "ipnet")]
670 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
671 ///
672 /// # #[cfg(feature = "ipnet")]
673 /// # {
674 /// let mut left = PrefixMap::new();
675 /// left.insert(net!("10.0.0.0/8"), 1);
676 /// left.insert(net!("10.1.0.0/16"), 2);
677 ///
678 /// let mut right = PrefixMap::new();
679 /// right.insert(net!("10.1.0.0/16"), 20);
680 /// right.insert(net!("10.1.1.0/24"), 30);
681 ///
682 /// let got: Vec<_> = left
683 /// .view()
684 /// .intersection(&right)
685 /// .unwrap()
686 /// .iter()
687 /// .map(|(prefix, (left, right))| (prefix, *left, *right))
688 /// .collect();
689 ///
690 /// assert_eq!(got, vec![(net!("10.1.0.0/16"), 2, 20)]);
691 /// # }
692 /// ```
693 #[inline]
694 fn intersection<R>(self, other: R) -> Option<IntersectionView<'a, Self, R::View>>
695 where
696 R: AsView<'a, P = Self::P>,
697 {
698 IntersectionView::new(self, other.view())
699 }
700
701 /// Return the union of `self` and `other` as a view.
702 ///
703 /// The returned [`UnionView`] iterates over every prefix present in **either** sub-trie,
704 /// yielding `(prefix, UnionItem)` in lexicographic order.
705 ///
706 /// ```
707 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
708 /// # use prefix_trie::trieview::union::UnionItem;
709 /// # #[cfg(feature = "ipnet")]
710 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
711 ///
712 /// # #[cfg(feature = "ipnet")]
713 /// # {
714 /// let mut left = PrefixMap::new();
715 /// left.insert(net!("10.0.0.0/8"), 1);
716 /// left.insert(net!("10.1.0.0/16"), 2);
717 ///
718 /// let mut right = PrefixMap::new();
719 /// right.insert(net!("10.1.0.0/16"), 20);
720 /// right.insert(net!("10.1.1.0/24"), 30);
721 ///
722 /// let got: Vec<_> = left
723 /// .view()
724 /// .union(&right)
725 /// .iter()
726 /// .map(|(prefix, item)| match item {
727 /// UnionItem::Left(left) => (prefix, Some(*left), None),
728 /// UnionItem::Right(right) => (prefix, None, Some(*right)),
729 /// UnionItem::Both(left, right) => (prefix, Some(*left), Some(*right)),
730 /// })
731 /// .collect();
732 ///
733 /// assert_eq!(
734 /// got,
735 /// vec![
736 /// (net!("10.0.0.0/8"), Some(1), None),
737 /// (net!("10.1.0.0/16"), Some(2), Some(20)),
738 /// (net!("10.1.1.0/24"), None, Some(30)),
739 /// ]
740 /// );
741 /// # }
742 /// ```
743 #[inline]
744 fn union<R>(self, other: R) -> UnionView<'a, Self, R::View>
745 where
746 R: AsView<'a, P = Self::P>,
747 {
748 UnionView::new(self, other.view())
749 }
750
751 /// Return the covering union of `self` and `other` as a view.
752 ///
753 /// The returned [`CoveringUnionView`] iterates over every prefix present in either sub-trie.
754 /// For prefixes present on only one side, the yielded item includes the longest prefix match
755 /// from the opposite side when one exists inside that opposite view.
756 ///
757 /// ```
758 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
759 /// # use prefix_trie::trieview::CoveringUnionItem;
760 /// # #[cfg(feature = "ipnet")]
761 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
762 ///
763 /// # #[cfg(feature = "ipnet")]
764 /// # {
765 /// let mut left = PrefixMap::new();
766 /// left.insert(net!("10.1.0.0/16"), 2);
767 ///
768 /// let mut right = PrefixMap::new();
769 /// right.insert(net!("10.0.0.0/8"), 10);
770 ///
771 /// let (_, item) = left
772 /// .view()
773 /// .covering_union(&right)
774 /// .iter()
775 /// .find(|(prefix, _)| prefix == &net!("10.1.0.0/16"))
776 /// .unwrap();
777 ///
778 /// match item {
779 /// CoveringUnionItem::Left {
780 /// left,
781 /// right_lpm: Some((right_prefix, right)),
782 /// } => {
783 /// assert_eq!(*left, 2);
784 /// assert_eq!(right_prefix, net!("10.0.0.0/8"));
785 /// assert_eq!(*right, 10);
786 /// }
787 /// _ => panic!("expected a left-only prefix covered by the right side"),
788 /// }
789 /// # }
790 /// ```
791 #[inline]
792 fn covering_union<R>(self, other: R) -> CoveringUnionView<'a, Self, R::View>
793 where
794 Self: Clone,
795 R: AsView<'a, P = Self::P>,
796 R::View: Clone,
797 {
798 CoveringUnionView::new(self, other.view())
799 }
800
801 /// Return the difference of `self` minus `other` as a view.
802 ///
803 /// The returned [`DifferenceView`] iterates over every prefix present in `self` but
804 /// **not** in `other`, yielding values from `self` in lexicographic order.
805 ///
806 /// ```
807 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
808 /// # #[cfg(feature = "ipnet")]
809 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
810 ///
811 /// # #[cfg(feature = "ipnet")]
812 /// # {
813 /// let mut left = PrefixMap::new();
814 /// left.insert(net!("10.0.0.0/8"), 1);
815 /// left.insert(net!("10.1.0.0/16"), 2);
816 /// left.insert(net!("10.1.1.0/24"), 3);
817 ///
818 /// let mut right = PrefixMap::new();
819 /// right.insert(net!("10.1.0.0/16"), 20);
820 ///
821 /// let got: Vec<_> = left
822 /// .view()
823 /// .difference(&right)
824 /// .iter()
825 /// .map(|(prefix, value)| (prefix, *value))
826 /// .collect();
827 ///
828 /// assert_eq!(got, vec![(net!("10.0.0.0/8"), 1), (net!("10.1.1.0/24"), 3)]);
829 /// # }
830 /// ```
831 #[inline]
832 fn difference<R>(self, other: R) -> DifferenceView<'a, Self, R::View>
833 where
834 R: AsView<'a, P = Self::P>,
835 {
836 DifferenceView::new(self, other.view())
837 }
838
839 /// Check whether `self` and `other` contain exactly the same set of prefixes,
840 /// ignoring values.
841 ///
842 /// This uses a bitmap-based structural comparison (no prefix reconstruction)
843 /// and short-circuits as soon as a difference is found.
844 ///
845 /// ```
846 /// # use prefix_trie::{PrefixMap, PrefixSet, AsView, TrieView};
847 /// # type P = (u32, u8);
848 /// let a: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 2)].into_iter().collect();
849 /// let b: PrefixMap<P, _> = [((0, 8), 9), ((0, 16), 9)].into_iter().collect();
850 /// let c: PrefixMap<P, _> = [((0, 8), 1)].into_iter().collect();
851 ///
852 /// assert!(a.view().eq_keys(&b)); // same keys, different values
853 /// assert!(!a.view().eq_keys(&c)); // different key sets
854 /// ```
855 fn eq_keys<R: AsView<'a, P = Self::P>>(self, other: R) -> bool {
856 equality::eq_keys_recursive(self, other.view())
857 }
858
859 /// Check whether `self` and `other` contain the same prefixes with equal values,
860 /// using `cmp` to compare each value pair.
861 ///
862 /// Iterates both views in lexicographic order, verifying that prefixes match
863 /// and `cmp` returns `true` for every value pair, and that both views have the
864 /// same number of entries.
865 ///
866 /// ```
867 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
868 /// # type P = (u32, u8);
869 /// let a: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 2)].into_iter().collect();
870 /// let b: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 2)].into_iter().collect();
871 /// let c: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 9)].into_iter().collect();
872 ///
873 /// assert!(a.view().eq_by(&b, |a, b| a == b));
874 /// assert!(!a.view().eq_by(&c, |a, b| a == b));
875 /// ```
876 fn eq_by<R, F>(self, other: R, mut cmp: F) -> bool
877 where
878 Self::P: PartialEq,
879 R: AsView<'a, P = Self::P>,
880 F: FnMut(Self::T, <<R as AsView<'a>>::View as TrieView<'a>>::T) -> bool,
881 {
882 let mut left = self.iter();
883 let mut right = other.view().iter();
884 loop {
885 match (left.next(), right.next()) {
886 (None, None) => return true,
887 (Some((lp, lv)), Some((rp, rv))) if lp == rp => {
888 if !cmp(lv, rv) {
889 return false;
890 }
891 }
892 _ => return false,
893 }
894 }
895 }
896
897 /// Return the covering difference of `self` minus `other` as a view.
898 ///
899 /// Iterates over every prefix `P_l` in `self` for which no covering prefix `P_r`
900 /// exists in `other` (`P_r.len ≤ P_l.len` and `P_r` matches `P_l`'s leading bits).
901 ///
902 /// ```
903 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
904 /// # #[cfg(feature = "ipnet")]
905 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
906 ///
907 /// # #[cfg(feature = "ipnet")]
908 /// # {
909 /// let mut left = PrefixMap::new();
910 /// left.insert(net!("10.0.0.0/8"), 1);
911 /// left.insert(net!("10.1.0.0/16"), 2);
912 /// left.insert(net!("10.1.1.0/24"), 3);
913 ///
914 /// let mut right = PrefixMap::new();
915 /// right.insert(net!("10.1.0.0/16"), 20);
916 ///
917 /// let got: Vec<_> = left
918 /// .view()
919 /// .covering_difference(&right)
920 /// .iter()
921 /// .map(|(prefix, value)| (prefix, *value))
922 /// .collect();
923 ///
924 /// assert_eq!(got, vec![(net!("10.0.0.0/8"), 1)]);
925 /// # }
926 /// ```
927 #[inline]
928 fn covering_difference<R>(self, other: R) -> CoveringDifferenceView<'a, Self, R::View>
929 where
930 R: AsView<'a, P = Self::P>,
931 {
932 CoveringDifferenceView::new(self, other.view())
933 }
934
935 // -----------------------------------------------------------------------------
936 // Private helper
937 // -----------------------------------------------------------------------------
938
939 /// Step one binary level deeper, going left (0-bit) or right (1-bit).
940 fn step(mut self, go_right: bool) -> Option<Self> {
941 let num_bits = <Self::P as Prefix>::R::zero().count_zeros();
942 // Cannot descend past the key width.
943 if self.prefix_len() >= num_bits {
944 return None;
945 }
946 let new_prefix_len = self.prefix_len() + 1;
947 let new_key = if go_right {
948 let bit_pos = num_bits - self.prefix_len() - 1;
949 self.key() | <Self::P as Prefix>::R::one().unsigned_shl(bit_pos)
950 } else {
951 self.key()
952 };
953
954 if new_prefix_len < self.depth() + K {
955 // Intra-node: narrow the position cursor within the same node.
956 // SAFETY: self is not used for data access after this; only `view` is used.
957 unsafe { self.reposition(new_key, new_prefix_len) };
958 if self.is_non_empty() {
959 Some(self)
960 } else {
961 None
962 }
963 } else {
964 // Cross into a child node (new_prefix_len == depth + K).
965 let child_bit = child_bit(self.depth(), new_key);
966 if (self.child_bitmap() >> child_bit) & 1 == 0 {
967 return None;
968 }
969 // SAFETY: step is called for one direction at a time; child_bit is used once.
970 Some(unsafe { self.get_child(child_bit) })
971 }
972 }
973}
974
975fn contains_key<P: Prefix>(
976 root_key: P::R,
977 root_len: u32,
978 target_key: P::R,
979 target_len: u32,
980) -> bool {
981 if root_len > target_len {
982 return false;
983 }
984 let mask = mask_from_prefix_len(root_len as u8);
985 root_key & mask == target_key & mask
986}
987
988fn lpm_data_bit<'a, V: TrieView<'a>>(
989 view: &V,
990 target_key: <V::P as Prefix>::R,
991 target_len: u32,
992) -> Option<u32> {
993 let data_bits = view.data_bitmap() & data_lpm_mask(view.depth(), target_key, target_len);
994 if data_bits == 0 {
995 None
996 } else {
997 Some(u32::BITS - 1 - data_bits.leading_zeros())
998 }
999}
1000
1001/// Reconstruct the prefix at `data_bit` within the node starting at `depth`.
1002pub(crate) fn reconstruct_prefix<P: Prefix>(depth: u32, key: P::R, data_bit: u32) -> P {
1003 let (offset, level) = DATA_BIT_TO_PREFIX[data_bit as usize];
1004 let prefix_len = depth + level as u32;
1005 let root = key & mask_from_prefix_len(depth as u8);
1006 let offset_r = <P::R as num_traits::cast::NumCast>::from(offset).unwrap();
1007 let offset_bits = K - 1;
1008 let total_width = P::num_bits();
1009 let shifted = if total_width > depth + offset_bits {
1010 offset_r << (total_width - (depth + offset_bits)) as usize
1011 } else {
1012 offset_r >> (depth + offset_bits - total_width) as usize
1013 };
1014 P::from_repr_len(root | shifted, prefix_len as u8)
1015}
1016
1017/// Trait that is implemented on structures that can be turned into a view.
1018pub trait AsView<'a> {
1019 /// The prefix type.
1020 type P: Prefix;
1021 /// The concrete view type returned by [`view`][AsView::view].
1022 type View: TrieView<'a, P = Self::P>;
1023
1024 /// Get a view rooted at the origin (the entire trie).
1025 fn view(self) -> Self::View;
1026
1027 /// Get a view rooted at `prefix`, or `None` if the sub-trie is empty.
1028 fn view_at(self, prefix: &Self::P) -> Option<Self::View>
1029 where
1030 Self: Sized,
1031 {
1032 self.view().find(prefix)
1033 }
1034}