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;
90mod filter;
91pub mod intersection;
92pub(crate) mod iter;
93mod map;
94pub mod trie_ref;
95pub mod trie_ref_mut;
96pub mod union;
97
98pub use covering_difference::CoveringDifferenceView;
99pub use covering_union::{CoveringUnionItem, CoveringUnionView};
100pub use difference::DifferenceView;
101pub use filter::FilterView;
102pub use intersection::IntersectionView;
103pub use iter::{ViewIter, ViewKeys, ViewValues};
104pub use map::{ClonedView, CopiedView, MapView};
105pub use trie_ref::TrieRef;
106pub use trie_ref_mut::TrieRefMut;
107pub use union::{UnionItem, UnionView};
108
109use num_traits::{One, PrimInt, Zero};
110
111use crate::{
112 prefix::mask_from_prefix_len,
113 Prefix,
114 {
115 node::{child_bit, data_bit, data_lpm_mask, DATA_BIT_TO_PREFIX},
116 table::K,
117 },
118};
119
120/// An immutable or mutable view into a (possibly composed) prefix trie.
121///
122/// # Required methods
123///
124/// Eight methods that concrete and composed views must implement:
125/// - **Position**: [`Self::depth`], [`Self::key`], [`Self::prefix_len`]
126/// - **Bitmaps**: [`Self::data_bitmap`], [`Self::child_bitmap`]
127/// - **Primitives** (unsafe): [`Self::get_data`], [`Self::get_child`], [`Self::reposition`]
128///
129/// # Default methods
130///
131/// All other methods (`left`/`right`/`find`/`find_lpm`/`iter`/etc.) are
132/// provided as defaults built from the eight required methods.
133#[cfg_attr(docsrs, doc(notable_trait))]
134pub trait TrieView<'a>: Sized {
135 /// The prefix type.
136 type P: Prefix;
137 /// The value type yielded by this view (e.g. `&'a T`, `&'a mut T`, `(&'a L, &'a R)`).
138 type T: 'a;
139
140 /// Depth of the underlying `MultiBitNode`: always a multiple of `K`.
141 fn depth(&self) -> u32;
142
143 /// Accumulated key bits; only the top [`prefix_len`][Self::prefix_len] bits are significant.
144 fn key(&self) -> <Self::P as Prefix>::R;
145
146 /// Binary-tree depth of this view's root position (`depth <= prefix_len < depth + K`).
147 fn prefix_len(&self) -> u32;
148
149 /// Effective data bitmap (node bitmap ANDed with cover mask and any set-op filter).
150 ///
151 /// A set bit at position `b` means there is a value accessible via
152 /// [`get_data(b)`][Self::get_data].
153 fn data_bitmap(&self) -> u32;
154
155 /// Effective child bitmap (node bitmap ANDed with cover mask and any set-op filter).
156 ///
157 /// A set bit at position `b` means there is a non-empty sub-trie reachable via
158 /// [`get_child(b)`][Self::get_child].
159 fn child_bitmap(&self) -> u32;
160
161 /// Return the value at `data_bit`.
162 ///
163 /// # Safety
164 /// `data_bit` must be set in [`data_bitmap`][Self::data_bitmap], and must be passed to this
165 /// method **at most once** per view instance.
166 /// For mutable views (`T = &'a mut T`), calling with the same bit twice produces two
167 /// aliasing `&'a mut T` references -> undefined behavior. Some implementations (e.g. those
168 /// caching values behind `MaybeUninit`) rely on `data_bit` being set in `data_bitmap` for
169 /// soundness, not merely for a well-defined result.
170 unsafe fn get_data(&mut self, data_bit: u32) -> Self::T;
171
172 /// Return a child view at `child_bit`.
173 ///
174 /// The returned view has `depth = self.depth() + K`, `prefix_len = self.depth() + K`,
175 /// and `key = extend_repr(self.key(), self.depth(), child_bit)`.
176 ///
177 /// # Safety
178 /// Each `child_bit` must be passed to this method **at most once** per view instance.
179 /// For mutable views, calling with the same bit twice creates two views with overlapping
180 /// mutable access to the same child node -> undefined behavior. Different bits always
181 /// refer to disjoint child nodes and are safe to combine.
182 ///
183 /// # Panics
184 /// May panic if `child_bit` is not set in [`child_bitmap`][Self::child_bitmap].
185 unsafe fn get_child(&mut self, child_bit: u32) -> Self;
186
187 /// Move the cursor to a different location within the same multibit-node.
188 ///
189 /// The underlying node location (and all data pointers) remain unchanged; only the
190 /// position cursor is updated.
191 ///
192 /// # Safety
193 /// For mutable views, the returned cursor shares the same `raw_ptr` and `node_loc`
194 /// as `self`. The caller must ensure that the returned cursor and `self` are never
195 /// simultaneously used to access overlapping data -> either by ensuring their effective
196 /// bitmaps are disjoint or by not accessing `self`'s data after the call (as in
197 /// `navigate_to` and `step`).
198 unsafe fn reposition(&mut self, key: <Self::P as Prefix>::R, prefix_len: u32);
199
200 // -----------------------------------------------------------------------------
201 // Default implementations
202 // -----------------------------------------------------------------------------
203
204 /// Whether the sub-trie rooted at this view position is non-empty.
205 ///
206 /// A shallow bitmap check: `true` means data or children exist worth exploring.
207 /// `false` means the sub-trie is definitely empty.
208 ///
209 /// **Note**: Composed views may over-approximate their bitmaps. For example,
210 /// [`DifferenceView`] and [`CoveringDifferenceView`] always expose all of the left side's
211 /// children, since some of their subtrees may be absent from the right side. For such views,
212 /// `true` may be returned even though iterating the view yields no entries. `false` is
213 /// always exact. To check emptiness exactly, iterate:
214 /// `view.iter().next().is_none()`. Note that [`iter`][Self::iter] takes the view by value;
215 /// clone it first if you still need it afterwards.
216 ///
217 /// ```
218 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
219 /// # #[cfg(feature = "ipnet")]
220 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
221 ///
222 /// # #[cfg(feature = "ipnet")]
223 /// # {
224 /// let mut map = PrefixMap::new();
225 /// map.insert(net!("10.0.0.0/8"), 1);
226 /// assert!(map.view().is_non_empty());
227 ///
228 /// let empty: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
229 /// assert!(!empty.view().is_non_empty());
230 ///
231 /// // Over-approximation: `right` removes `left`'s only entry entirely, but `DifferenceView`
232 /// // still exposes left's child pointer toward it, so `is_non_empty` says `true` even though
233 /// // iterating the difference yields nothing.
234 /// let mut left = PrefixMap::new();
235 /// left.insert(net!("10.1.0.0/16"), 1);
236 /// let mut right = PrefixMap::new();
237 /// right.insert(net!("10.1.0.0/16"), 1);
238 ///
239 /// let diff = left.view().difference(&right);
240 /// assert!(diff.is_non_empty());
241 /// assert!(diff.iter().next().is_none());
242 /// # }
243 /// ```
244 #[inline]
245 fn is_non_empty(&self) -> bool {
246 self.data_bitmap() != 0 || self.child_bitmap() != 0
247 }
248
249 /// Reconstruct the prefix at this view's root position.
250 ///
251 /// ```
252 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
253 /// # #[cfg(feature = "ipnet")]
254 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
255 ///
256 /// # #[cfg(feature = "ipnet")]
257 /// # {
258 /// let mut map = PrefixMap::new();
259 /// map.insert(net!("192.168.0.0/20"), 1);
260 /// map.insert(net!("192.168.0.0/22"), 2);
261 ///
262 /// let view = map.view().find(&net!("192.168.0.0/21")).unwrap();
263 /// assert_eq!(view.prefix(), net!("192.168.0.0/21"));
264 /// # }
265 /// ```
266 #[inline]
267 fn prefix(&self) -> Self::P {
268 let masked = self.key() & mask_from_prefix_len(self.prefix_len() as u8);
269 Self::P::from_repr_len(masked, self.prefix_len() as u8)
270 }
271
272 /// Return the value stored exactly at this view's root position, if any.
273 ///
274 /// This method consumes the view, which makes it suitable for mutable views.
275 ///
276 /// ```
277 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
278 /// # #[cfg(feature = "ipnet")]
279 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
280 ///
281 /// # #[cfg(feature = "ipnet")]
282 /// # {
283 /// let mut map = PrefixMap::new();
284 /// map.insert(net!("192.168.0.0/20"), 1);
285 /// map.insert(net!("192.168.0.0/22"), 2);
286 ///
287 /// assert_eq!(map.view().find_exact(&net!("192.168.0.0/22")).unwrap().value(), Some(&2));
288 /// assert_eq!(map.view().find(&net!("192.168.0.0/21")).unwrap().value(), None);
289 /// # }
290 /// ```
291 #[inline]
292 fn value(mut self) -> Option<Self::T> {
293 let data_bit = data_bit(self.key(), self.prefix_len());
294 if (self.data_bitmap() >> data_bit) & 1 == 1 {
295 // SAFETY: `value` consumes the view and calls `get_data` for one bit.
296 Some(unsafe { self.get_data(data_bit) })
297 } else {
298 None
299 }
300 }
301
302 /// Return the prefix and value stored exactly at this view's root position, if any.
303 ///
304 /// This method consumes the view, which makes it suitable for mutable views.
305 ///
306 /// ```
307 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
308 /// # #[cfg(feature = "ipnet")]
309 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
310 ///
311 /// # #[cfg(feature = "ipnet")]
312 /// # {
313 /// let mut map = PrefixMap::new();
314 /// map.insert(net!("192.168.0.0/22"), 2);
315 ///
316 /// let view = map.view().find_exact(&net!("192.168.0.0/22")).unwrap();
317 /// assert_eq!(view.prefix_value(), Some((net!("192.168.0.0/22"), &2)));
318 /// # }
319 /// ```
320 #[inline]
321 fn prefix_value(mut self) -> Option<(Self::P, Self::T)> {
322 let data_bit = data_bit(self.key(), self.prefix_len());
323 if (self.data_bitmap() >> data_bit) & 1 == 1 {
324 let prefix = self.prefix();
325 // SAFETY: `prefix_value` consumes the view and calls `get_data` for one bit.
326 Some((prefix, unsafe { self.get_data(data_bit) }))
327 } else {
328 None
329 }
330 }
331
332 /// Return a view into the left (0-bit) child sub-trie, or `None` if empty.
333 ///
334 /// ```
335 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
336 /// # #[cfg(feature = "ipnet")]
337 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
338 ///
339 /// # #[cfg(feature = "ipnet")]
340 /// # {
341 /// let mut map = PrefixMap::new();
342 /// map.insert(net!("10.0.0.0/8"), 1);
343 ///
344 /// let left = map.view().left().unwrap();
345 /// assert_eq!(left.prefix(), net!("0.0.0.0/1"));
346 /// assert_eq!(left.keys().collect::<Vec<_>>(), vec![net!("10.0.0.0/8")]);
347 /// # }
348 /// ```
349 #[inline]
350 fn left(self) -> Option<Self> {
351 step(self, false)
352 }
353
354 /// Return a view into the right (1-bit) child sub-trie, or `None` if empty.
355 ///
356 /// ```
357 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
358 /// # #[cfg(feature = "ipnet")]
359 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
360 ///
361 /// # #[cfg(feature = "ipnet")]
362 /// # {
363 /// let mut map = PrefixMap::new();
364 /// map.insert(net!("128.0.0.0/1"), 1);
365 ///
366 /// let right = map.view().right().unwrap();
367 /// assert_eq!(right.prefix(), net!("128.0.0.0/1"));
368 /// assert_eq!(right.value(), Some(&1));
369 /// # }
370 /// ```
371 #[inline]
372 fn right(self) -> Option<Self> {
373 step(self, true)
374 }
375
376 /// Navigate to `prefix` and return the view if the sub-trie is non-empty.
377 ///
378 /// The emptiness check may over-approximate on composed views (see
379 /// [`is_non_empty`][Self::is_non_empty]): the returned view may yield no entries when
380 /// iterated. `None`, however, always means that the view contains nothing at or below
381 /// `prefix`. To check exactly whether the sub-trie contains an entry, iterate the returned
382 /// view: `view.iter().next().is_none()`. Note that [`iter`][Self::iter] takes the view by
383 /// value; clone it first if you still need it afterwards.
384 ///
385 /// ```
386 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
387 /// # #[cfg(feature = "ipnet")]
388 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
389 ///
390 /// # #[cfg(feature = "ipnet")]
391 /// # {
392 /// let mut map = PrefixMap::new();
393 /// map.insert(net!("192.168.0.0/20"), 1);
394 /// map.insert(net!("192.168.0.0/22"), 2);
395 /// map.insert(net!("192.168.0.0/24"), 3);
396 ///
397 /// let sub = map.view().find(&net!("192.168.0.0/21")).unwrap();
398 /// assert_eq!(
399 /// sub.keys().collect::<Vec<_>>(),
400 /// vec![net!("192.168.0.0/22"), net!("192.168.0.0/24")]
401 /// );
402 /// # }
403 /// ```
404 #[inline]
405 fn find(self, prefix: &Self::P) -> Option<Self> {
406 let view = navigate_to(self, prefix.mask(), prefix.prefix_len() as u32)?;
407 if view.is_non_empty() {
408 Some(view)
409 } else {
410 None
411 }
412 }
413
414 /// Navigate to `prefix` and return the view only if a value is stored exactly there.
415 ///
416 /// ```
417 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
418 /// # #[cfg(feature = "ipnet")]
419 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
420 ///
421 /// # #[cfg(feature = "ipnet")]
422 /// # {
423 /// let mut map = PrefixMap::new();
424 /// map.insert(net!("192.168.0.0/20"), 1);
425 /// map.insert(net!("192.168.0.0/22"), 2);
426 ///
427 /// assert!(map.view().find_exact(&net!("192.168.0.0/21")).is_none());
428 /// assert_eq!(
429 /// map.view().find_exact(&net!("192.168.0.0/22")).unwrap().value(),
430 /// Some(&2)
431 /// );
432 /// # }
433 /// ```
434 #[inline]
435 fn find_exact(self, prefix: &Self::P) -> Option<Self> {
436 let view = navigate_to(self, prefix.mask(), prefix.prefix_len() as u32)?;
437 let data_bit = data_bit(view.key(), view.prefix_len());
438 if (view.data_bitmap() >> data_bit) & 1 == 1 {
439 Some(view)
440 } else {
441 None
442 }
443 }
444
445 /// Navigate to `prefix` and return its prefix/value pair if a value is stored exactly there.
446 ///
447 /// This method consumes the view and does not require `Self: Clone`, so it also works with
448 /// mutable views.
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/22"), 2);
459 ///
460 /// assert_eq!(
461 /// map.view().find_exact_value(&net!("192.168.0.0/22")),
462 /// Some((net!("192.168.0.0/22"), &2))
463 /// );
464 /// assert_eq!(map.view().find_exact_value(&net!("192.168.0.0/21")), None);
465 /// # }
466 /// ```
467 #[inline]
468 fn find_exact_value(self, prefix: &Self::P) -> Option<(Self::P, Self::T)> {
469 let view = navigate_to(self, prefix.mask(), prefix.prefix_len() as u32)?;
470 view.prefix_value()
471 }
472
473 /// Find the view pointing at the longest prefix match for `prefix`.
474 ///
475 /// This method requires `Self: Clone` because the search must remember the best matching view
476 /// while it continues descending toward more-specific prefixes.
477 ///
478 /// ```
479 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
480 /// # #[cfg(feature = "ipnet")]
481 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
482 ///
483 /// # #[cfg(feature = "ipnet")]
484 /// # {
485 /// let mut map = PrefixMap::new();
486 /// map.insert(net!("192.168.0.0/20"), 1);
487 /// map.insert(net!("192.168.0.0/22"), 2);
488 ///
489 /// let view = map.view().find_lpm(&net!("192.168.0.0/21")).unwrap();
490 /// assert_eq!(view.prefix(), net!("192.168.0.0/20"));
491 /// assert_eq!(view.value(), Some(&1));
492 /// # }
493 /// ```
494 fn find_lpm(mut self, prefix: &Self::P) -> Option<Self>
495 where
496 Self: Clone,
497 {
498 let target_key = prefix.mask();
499 let target_len = prefix.prefix_len() as u32;
500 if !contains_key::<Self::P>(self.key(), self.prefix_len(), target_key, target_len) {
501 return None;
502 }
503 let mut best = None;
504
505 loop {
506 if let Some(data_bit) = lpm_data_bit(&self, target_key, target_len) {
507 let prefix = reconstruct_prefix::<Self::P>(self.depth(), self.key(), data_bit);
508 let mut view = self.clone();
509 // SAFETY: the cloned cursor is moved within its current multibit node.
510 unsafe { view.reposition(prefix.mask(), prefix.prefix_len() as u32) };
511 best = Some(view);
512 }
513
514 if target_len < self.depth() + K {
515 return best;
516 }
517
518 let child_bit = child_bit(self.depth(), target_key);
519 if (self.child_bitmap() >> child_bit) & 1 == 0 {
520 return best;
521 }
522
523 // SAFETY: follows a single path; each child bit is used at most once per view.
524 self = unsafe { self.get_child(child_bit) };
525 }
526 }
527
528 /// Find the longest prefix match for `prefix` and return its prefix/value pair.
529 ///
530 /// This method does not require `Self: Clone`; it can therefore be used with views that yield
531 /// mutable references. It consumes the view and only returns the matched element, not a cursor.
532 ///
533 /// ```
534 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
535 /// # #[cfg(feature = "ipnet")]
536 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
537 ///
538 /// # #[cfg(feature = "ipnet")]
539 /// # {
540 /// let mut map = PrefixMap::new();
541 /// map.insert(net!("192.168.0.0/20"), 1);
542 /// map.insert(net!("192.168.0.0/22"), 2);
543 ///
544 /// let (prefix, value) = (&mut map)
545 /// .view()
546 /// .find_lpm_value(&net!("192.168.0.0/21"))
547 /// .unwrap();
548 ///
549 /// assert_eq!(prefix, net!("192.168.0.0/20"));
550 /// *value += 10;
551 /// assert_eq!(map.get(&net!("192.168.0.0/20")), Some(&11));
552 /// # }
553 /// ```
554 fn find_lpm_value(mut self, prefix: &Self::P) -> Option<(Self::P, Self::T)> {
555 let target_key = prefix.mask();
556 let target_len = prefix.prefix_len() as u32;
557 if !contains_key::<Self::P>(self.key(), self.prefix_len(), target_key, target_len) {
558 return None;
559 }
560 let mut best = None;
561
562 loop {
563 if let Some(data_bit) = lpm_data_bit(&self, target_key, target_len) {
564 let prefix = reconstruct_prefix::<Self::P>(self.depth(), self.key(), data_bit);
565 drop(best.take());
566 // SAFETY: each node on the target path is visited at most once, and we keep only
567 // the most-specific matched value.
568 best = Some((prefix, unsafe { self.get_data(data_bit) }));
569 }
570
571 if target_len < self.depth() + K {
572 return best;
573 }
574
575 let child_bit = child_bit(self.depth(), target_key);
576 if (self.child_bitmap() >> child_bit) & 1 == 0 {
577 return best;
578 }
579
580 // SAFETY: follows a single path; each child bit is used at most once per view.
581 self = unsafe { self.get_child(child_bit) };
582 }
583 }
584
585 /// Return an iterator over all `(prefix, value)` pairs in this sub-trie.
586 ///
587 /// ```
588 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
589 /// # #[cfg(feature = "ipnet")]
590 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
591 ///
592 /// # #[cfg(feature = "ipnet")]
593 /// # {
594 /// let mut map = PrefixMap::new();
595 /// map.insert(net!("192.168.0.0/20"), 1);
596 /// map.insert(net!("192.168.0.0/22"), 2);
597 /// map.insert(net!("192.168.0.0/24"), 3);
598 ///
599 /// let sub = map.view().find(&net!("192.168.0.0/22")).unwrap();
600 /// assert_eq!(
601 /// sub.iter().collect::<Vec<_>>(),
602 /// vec![(net!("192.168.0.0/22"), &2), (net!("192.168.0.0/24"), &3)]
603 /// );
604 /// # }
605 /// ```
606 #[inline]
607 fn iter(self) -> ViewIter<'a, Self> {
608 ViewIter::new(self)
609 }
610
611 /// Iterate over all entries in this sub-trie starting at `prefix`, in lexicographic order.
612 ///
613 /// This enables stateless, cursor-based pagination: pass the last-seen prefix to resume.
614 ///
615 /// - If `inclusive` is `true`, the iterator includes the entry at `prefix` (if present).
616 /// - If `inclusive` is `false`, the iterator starts after `prefix`. Entries more specific than
617 /// `prefix` (its children) are still yielded.
618 ///
619 /// If `prefix` is not present, the iterator starts at the first entry that would come after
620 /// `prefix` in lexicographic order, regardless of `inclusive`.
621 ///
622 /// ```
623 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
624 /// # #[cfg(feature = "ipnet")]
625 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
626 ///
627 /// # #[cfg(feature = "ipnet")]
628 /// # {
629 /// let mut map = PrefixMap::new();
630 /// map.insert(net!("10.0.0.0/8"), 1);
631 /// map.insert(net!("10.1.0.0/16"), 2);
632 /// map.insert(net!("10.2.0.0/16"), 3);
633 /// map.insert(net!("10.3.0.0/16"), 4);
634 ///
635 /// let page: Vec<_> = map.view().iter_from(&net!("10.1.0.0/16"), false).take(2).collect();
636 /// assert_eq!(page, vec![(net!("10.2.0.0/16"), &3), (net!("10.3.0.0/16"), &4)]);
637 /// # }
638 /// ```
639 #[inline]
640 fn iter_from(self, prefix: &Self::P, inclusive: bool) -> ViewIter<'a, Self> {
641 ViewIter::new_from(self, prefix, inclusive)
642 }
643
644 /// Return an iterator over all prefixes in this sub-trie.
645 ///
646 /// ```
647 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
648 /// # #[cfg(feature = "ipnet")]
649 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
650 ///
651 /// # #[cfg(feature = "ipnet")]
652 /// # {
653 /// let mut map = PrefixMap::new();
654 /// map.insert(net!("192.168.0.0/20"), 1);
655 /// map.insert(net!("192.168.0.0/22"), 2);
656 /// map.insert(net!("192.168.0.0/24"), 3);
657 ///
658 /// let sub = map.view().find(&net!("192.168.0.0/22")).unwrap();
659 /// assert_eq!(
660 /// sub.keys().collect::<Vec<_>>(),
661 /// vec![net!("192.168.0.0/22"), net!("192.168.0.0/24")]
662 /// );
663 /// # }
664 /// ```
665 #[inline]
666 fn keys(self) -> ViewKeys<'a, Self> {
667 ViewKeys::new(self)
668 }
669
670 /// Return an iterator over all values in this sub-trie.
671 ///
672 /// ```
673 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
674 /// # #[cfg(feature = "ipnet")]
675 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
676 ///
677 /// # #[cfg(feature = "ipnet")]
678 /// # {
679 /// let mut map = PrefixMap::new();
680 /// map.insert(net!("192.168.0.0/20"), 1);
681 /// map.insert(net!("192.168.0.0/22"), 2);
682 /// map.insert(net!("192.168.0.0/24"), 3);
683 ///
684 /// let sub = map.view().find(&net!("192.168.0.0/22")).unwrap();
685 /// assert_eq!(sub.values().copied().collect::<Vec<_>>(), vec![2, 3]);
686 /// # }
687 /// ```
688 #[inline]
689 fn values(self) -> ViewValues<'a, Self> {
690 ViewValues::new(self)
691 }
692
693 /// Takes a closure and creates a view which calls that closure for each value it yields.
694 ///
695 /// **Warning**: The closure `f` may not applied to all elements of the view if it is further
696 /// combined with others.
697 ///
698 /// ```
699 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
700 /// # #[cfg(feature = "ipnet")]
701 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
702 ///
703 /// # #[cfg(feature = "ipnet")]
704 /// # {
705 /// let mut data = PrefixMap::new();
706 /// data.insert(net!("192.168.0.0/20"), 1);
707 /// data.insert(net!("192.168.0.0/22"), 2);
708 /// data.insert(net!("192.168.0.0/24"), 3);
709 ///
710 /// let mapped = data.view().map(|x| *x * 2);
711 /// assert_eq!(mapped.values().collect::<Vec<_>>(), vec![2, 4, 6]);
712 /// # }
713 /// ```
714 fn map<F, U>(self, f: F) -> MapView<'a, Self, F, U>
715 where
716 F: Fn(Self::T) -> U,
717 U: 'a,
718 {
719 MapView {
720 view: self,
721 f,
722 _marker: Default::default(),
723 }
724 }
725
726 /// Takes a closure and creates a view which only yields values for which the closure
727 /// returns `true`.
728 ///
729 /// **Warning**: As with [`map`][Self::map], the predicate may not be evaluated on all
730 /// elements if this view is further combined with others: a branch that an outer
731 /// combinator never descends into is never visited, so the predicate never runs on it.
732 ///
733 /// ```
734 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
735 /// # #[cfg(feature = "ipnet")]
736 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
737 ///
738 /// # #[cfg(feature = "ipnet")]
739 /// # {
740 /// let mut data = PrefixMap::new();
741 /// data.insert(net!("192.0.0.0/8"), 1);
742 /// data.insert(net!("192.168.0.0/16"), 2);
743 /// data.insert(net!("192.168.0.0/24"), 3);
744 ///
745 /// let filtered = data.view().filter(|_, x| *x % 2 == 0).copied();
746 /// assert_eq!(filtered.values().collect::<Vec<_>>(), vec![2]);
747 /// # }
748 /// ```
749 fn filter<F>(self, f: F) -> FilterView<'a, Self, F>
750 where
751 F: Fn(Self::P, &Self::T) -> bool,
752 {
753 FilterView::new(self, f)
754 }
755
756 /// Creates a view which clones each value it yields.
757 ///
758 /// ```
759 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
760 /// # #[cfg(feature = "ipnet")]
761 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
762 ///
763 /// # #[cfg(feature = "ipnet")]
764 /// # {
765 /// let mut data = PrefixMap::new();
766 /// data.insert(net!("192.168.0.0/20"), vec![1]);
767 /// data.insert(net!("192.168.0.0/22"), vec![2]);
768 /// data.insert(net!("192.168.0.0/24"), vec![3]);
769 ///
770 /// assert_eq!(
771 /// data.view().cloned().values().collect::<Vec<_>>(),
772 /// vec![vec![1], vec![2], vec![3]]
773 /// );
774 /// # }
775 /// ```
776 fn cloned<'b, T>(self) -> ClonedView<'a, Self, T>
777 where
778 Self: TrieView<'a, T = &'b T>,
779 T: 'b + Clone,
780 {
781 ClonedView {
782 view: self,
783 _marker: Default::default(),
784 }
785 }
786
787 /// Creates a view which copies each value it yields.
788 ///
789 /// ```
790 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
791 /// # #[cfg(feature = "ipnet")]
792 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
793 ///
794 /// # #[cfg(feature = "ipnet")]
795 /// # {
796 /// let mut data = PrefixMap::new();
797 /// data.insert(net!("192.168.0.0/20"), 1);
798 /// data.insert(net!("192.168.0.0/22"), 2);
799 /// data.insert(net!("192.168.0.0/24"), 3);
800 ///
801 /// assert_eq!(data.view().copied().values().collect::<Vec<_>>(), vec![1, 2, 3]);
802 /// # }
803 /// ```
804 fn copied<'b, T>(self) -> CopiedView<'a, Self, T>
805 where
806 Self: TrieView<'a, T = &'b T>,
807 T: 'b + Copy,
808 {
809 CopiedView {
810 view: self,
811 _marker: Default::default(),
812 }
813 }
814
815 /// Return the intersection of `self` and `other` as a view, or `None` if disjoint.
816 ///
817 /// The returned [`IntersectionView`] iterates over every prefix present in **both**
818 /// sub-tries, yielding `(prefix, (left_value, right_value))` in lexicographic order.
819 ///
820 /// ```
821 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
822 /// # #[cfg(feature = "ipnet")]
823 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
824 ///
825 /// # #[cfg(feature = "ipnet")]
826 /// # {
827 /// let mut left = PrefixMap::new();
828 /// left.insert(net!("10.0.0.0/8"), 1);
829 /// left.insert(net!("10.1.0.0/16"), 2);
830 ///
831 /// let mut right = PrefixMap::new();
832 /// right.insert(net!("10.1.0.0/16"), 20);
833 /// right.insert(net!("10.1.1.0/24"), 30);
834 ///
835 /// let got: Vec<_> = left
836 /// .view()
837 /// .intersection(&right)
838 /// .unwrap()
839 /// .iter()
840 /// .map(|(prefix, (left, right))| (prefix, *left, *right))
841 /// .collect();
842 ///
843 /// assert_eq!(got, vec![(net!("10.1.0.0/16"), 2, 20)]);
844 /// # }
845 /// ```
846 #[inline]
847 fn intersection<R>(self, other: R) -> Option<IntersectionView<'a, Self, R::View>>
848 where
849 R: AsView<'a, P = Self::P>,
850 {
851 IntersectionView::new(self, other.view())
852 }
853
854 /// Return the union of `self` and `other` as a view.
855 ///
856 /// The returned [`UnionView`] iterates over every prefix present in **either** sub-trie,
857 /// yielding `(prefix, UnionItem)` in lexicographic order.
858 ///
859 /// ```
860 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
861 /// # use prefix_trie::trieview::union::UnionItem;
862 /// # #[cfg(feature = "ipnet")]
863 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
864 ///
865 /// # #[cfg(feature = "ipnet")]
866 /// # {
867 /// let mut left = PrefixMap::new();
868 /// left.insert(net!("10.0.0.0/8"), 1);
869 /// left.insert(net!("10.1.0.0/16"), 2);
870 ///
871 /// let mut right = PrefixMap::new();
872 /// right.insert(net!("10.1.0.0/16"), 20);
873 /// right.insert(net!("10.1.1.0/24"), 30);
874 ///
875 /// let got: Vec<_> = left
876 /// .view()
877 /// .union(&right)
878 /// .iter()
879 /// .map(|(prefix, item)| match item {
880 /// UnionItem::Left(left) => (prefix, Some(*left), None),
881 /// UnionItem::Right(right) => (prefix, None, Some(*right)),
882 /// UnionItem::Both(left, right) => (prefix, Some(*left), Some(*right)),
883 /// })
884 /// .collect();
885 ///
886 /// assert_eq!(
887 /// got,
888 /// vec![
889 /// (net!("10.0.0.0/8"), Some(1), None),
890 /// (net!("10.1.0.0/16"), Some(2), Some(20)),
891 /// (net!("10.1.1.0/24"), None, Some(30)),
892 /// ]
893 /// );
894 /// # }
895 /// ```
896 #[inline]
897 fn union<R>(self, other: R) -> UnionView<'a, Self, R::View>
898 where
899 R: AsView<'a, P = Self::P>,
900 {
901 UnionView::new(self, other.view())
902 }
903
904 /// Return the covering union of `self` and `other` as a view.
905 ///
906 /// The returned [`CoveringUnionView`] iterates over every prefix present in either sub-trie.
907 /// For prefixes present on only one side, the yielded item includes the longest prefix match
908 /// from the opposite side when one exists inside that opposite view.
909 ///
910 /// ```
911 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
912 /// # use prefix_trie::trieview::CoveringUnionItem;
913 /// # #[cfg(feature = "ipnet")]
914 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
915 ///
916 /// # #[cfg(feature = "ipnet")]
917 /// # {
918 /// let mut left = PrefixMap::new();
919 /// left.insert(net!("10.1.0.0/16"), 2);
920 ///
921 /// let mut right = PrefixMap::new();
922 /// right.insert(net!("10.0.0.0/8"), 10);
923 ///
924 /// let (_, item) = left
925 /// .view()
926 /// .covering_union(&right)
927 /// .iter()
928 /// .find(|(prefix, _)| prefix == &net!("10.1.0.0/16"))
929 /// .unwrap();
930 ///
931 /// match item {
932 /// CoveringUnionItem::Left {
933 /// left,
934 /// right_lpm: Some((right_prefix, right)),
935 /// } => {
936 /// assert_eq!(*left, 2);
937 /// assert_eq!(right_prefix, net!("10.0.0.0/8"));
938 /// assert_eq!(*right, 10);
939 /// }
940 /// _ => panic!("expected a left-only prefix covered by the right side"),
941 /// }
942 /// # }
943 /// ```
944 #[inline]
945 fn covering_union<R>(self, other: R) -> CoveringUnionView<'a, Self, R::View>
946 where
947 Self: Clone,
948 R: AsView<'a, P = Self::P>,
949 R::View: Clone,
950 {
951 CoveringUnionView::new(self, other.view())
952 }
953
954 /// Return the difference of `self` minus `other` as a view.
955 ///
956 /// The returned [`DifferenceView`] iterates over every prefix present in `self` but
957 /// **not** in `other`, yielding values from `self` in lexicographic order.
958 ///
959 /// ```
960 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
961 /// # #[cfg(feature = "ipnet")]
962 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
963 ///
964 /// # #[cfg(feature = "ipnet")]
965 /// # {
966 /// let mut left = PrefixMap::new();
967 /// left.insert(net!("10.0.0.0/8"), 1);
968 /// left.insert(net!("10.1.0.0/16"), 2);
969 /// left.insert(net!("10.1.1.0/24"), 3);
970 ///
971 /// let mut right = PrefixMap::new();
972 /// right.insert(net!("10.1.0.0/16"), 20);
973 ///
974 /// let got: Vec<_> = left
975 /// .view()
976 /// .difference(&right)
977 /// .iter()
978 /// .map(|(prefix, value)| (prefix, *value))
979 /// .collect();
980 ///
981 /// assert_eq!(got, vec![(net!("10.0.0.0/8"), 1), (net!("10.1.1.0/24"), 3)]);
982 /// # }
983 /// ```
984 #[inline]
985 fn difference<R>(self, other: R) -> DifferenceView<'a, Self, R::View>
986 where
987 R: AsView<'a, P = Self::P>,
988 {
989 DifferenceView::new(self, other.view())
990 }
991
992 /// Check whether `self` and `other` contain exactly the same set of prefixes,
993 /// ignoring values.
994 ///
995 /// This uses a bitmap-based structural comparison (no prefix reconstruction)
996 /// and short-circuits as soon as a difference is found.
997 ///
998 /// ```
999 /// # use prefix_trie::{PrefixMap, PrefixSet, AsView, TrieView};
1000 /// # type P = (u32, u8);
1001 /// let a: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 2)].into_iter().collect();
1002 /// let b: PrefixMap<P, _> = [((0, 8), 9), ((0, 16), 9)].into_iter().collect();
1003 /// let c: PrefixMap<P, _> = [((0, 8), 1)].into_iter().collect();
1004 ///
1005 /// assert!(a.view().eq_keys(&b)); // same keys, different values
1006 /// assert!(!a.view().eq_keys(&c)); // different key sets
1007 /// ```
1008 fn eq_keys<R: AsView<'a, P = Self::P>>(self, other: R) -> bool {
1009 equality::eq_keys_recursive(self, other.view())
1010 }
1011
1012 /// Check whether `self` and `other` contain the same prefixes with equal values,
1013 /// using `cmp` to compare each value pair.
1014 ///
1015 /// Iterates both views in lexicographic order, verifying that prefixes match
1016 /// and `cmp` returns `true` for every value pair, and that both views have the
1017 /// same number of entries.
1018 ///
1019 /// ```
1020 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
1021 /// # type P = (u32, u8);
1022 /// let a: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 2)].into_iter().collect();
1023 /// let b: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 2)].into_iter().collect();
1024 /// let c: PrefixMap<P, _> = [((0, 8), 1), ((0, 16), 9)].into_iter().collect();
1025 ///
1026 /// assert!(a.view().eq_by(&b, |a, b| a == b));
1027 /// assert!(!a.view().eq_by(&c, |a, b| a == b));
1028 /// ```
1029 fn eq_by<R, F>(self, other: R, mut cmp: F) -> bool
1030 where
1031 Self::P: PartialEq,
1032 R: AsView<'a, P = Self::P>,
1033 F: FnMut(Self::T, <<R as AsView<'a>>::View as TrieView<'a>>::T) -> bool,
1034 {
1035 let mut left = self.iter();
1036 let mut right = other.view().iter();
1037 loop {
1038 match (left.next(), right.next()) {
1039 (None, None) => return true,
1040 (Some((lp, lv)), Some((rp, rv))) if lp == rp => {
1041 if !cmp(lv, rv) {
1042 return false;
1043 }
1044 }
1045 _ => return false,
1046 }
1047 }
1048 }
1049
1050 /// Return the covering difference of `self` minus `other` as a view.
1051 ///
1052 /// Iterates over every prefix `P_l` in `self` for which no covering prefix `P_r`
1053 /// exists in `other` (`P_r.len ≤ P_l.len` and `P_r` matches `P_l`'s leading bits).
1054 ///
1055 /// ```
1056 /// # use prefix_trie::{PrefixMap, AsView, TrieView};
1057 /// # #[cfg(feature = "ipnet")]
1058 /// macro_rules! net { ($x:literal) => { $x.parse::<ipnet::Ipv4Net>().unwrap() }; }
1059 ///
1060 /// # #[cfg(feature = "ipnet")]
1061 /// # {
1062 /// let mut left = PrefixMap::new();
1063 /// left.insert(net!("10.0.0.0/8"), 1);
1064 /// left.insert(net!("10.1.0.0/16"), 2);
1065 /// left.insert(net!("10.1.1.0/24"), 3);
1066 ///
1067 /// let mut right = PrefixMap::new();
1068 /// right.insert(net!("10.1.0.0/16"), 20);
1069 ///
1070 /// let got: Vec<_> = left
1071 /// .view()
1072 /// .covering_difference(&right)
1073 /// .iter()
1074 /// .map(|(prefix, value)| (prefix, *value))
1075 /// .collect();
1076 ///
1077 /// assert_eq!(got, vec![(net!("10.0.0.0/8"), 1)]);
1078 /// # }
1079 /// ```
1080 #[inline]
1081 fn covering_difference<R>(self, other: R) -> CoveringDifferenceView<'a, Self, R::View>
1082 where
1083 R: AsView<'a, P = Self::P>,
1084 {
1085 CoveringDifferenceView::new(self, other.view())
1086 }
1087}
1088
1089// -----------------------------------------------------------------------------
1090// Private helper
1091// -----------------------------------------------------------------------------
1092
1093/// Step one binary level deeper, going left (0-bit) or right (1-bit).
1094fn step<'a, V, P, T>(mut view: V, go_right: bool) -> Option<V>
1095where
1096 V: TrieView<'a, P = P, T = T>,
1097 P: Prefix,
1098{
1099 let num_bits = P::R::zero().count_zeros();
1100 // Cannot descend past the key width.
1101 if view.prefix_len() >= num_bits {
1102 return None;
1103 }
1104 let new_prefix_len = view.prefix_len() + 1;
1105 let new_key = if go_right {
1106 let bit_pos = num_bits - view.prefix_len() - 1;
1107 view.key() | P::R::one().unsigned_shl(bit_pos)
1108 } else {
1109 view.key()
1110 };
1111
1112 if new_prefix_len < view.depth() + K {
1113 // Intra-node: narrow the position cursor within the same node.
1114 // SAFETY: view is not used for data access after this; only `view` is used.
1115 unsafe { view.reposition(new_key, new_prefix_len) };
1116 if view.is_non_empty() {
1117 Some(view)
1118 } else {
1119 None
1120 }
1121 } else {
1122 // Cross into a child node (new_prefix_len == depth + K).
1123 let child_bit = child_bit(view.depth(), new_key);
1124 if (view.child_bitmap() >> child_bit) & 1 == 0 {
1125 return None;
1126 }
1127 // SAFETY: step is called for one direction at a time; child_bit is used once.
1128 Some(unsafe { view.get_child(child_bit) })
1129 }
1130}
1131
1132/// Navigate toward `(target_key, target_len)` from this view's node.
1133///
1134/// Returns `None` if a required child node does not exist in [`child_bitmap`][Self::child_bitmap].
1135fn navigate_to<'a, V, P, T>(mut view: V, target_key: P::R, target_len: u32) -> Option<V>
1136where
1137 V: TrieView<'a, P = P, T = T>,
1138 P: Prefix,
1139{
1140 if !contains_key::<P>(view.key(), view.prefix_len(), target_key, target_len) {
1141 return None;
1142 }
1143
1144 while target_len >= view.depth() + K {
1145 let child_bit = child_bit(view.depth(), target_key);
1146 if (view.child_bitmap() >> child_bit) & 1 == 0 {
1147 return None;
1148 }
1149 // SAFETY: follows a single path; each child_bit used exactly once per
1150 // view instance before view is replaced by the returned child.
1151 view = unsafe { view.get_child(child_bit) };
1152 }
1153
1154 // SAFETY: view is replaced by the repositioned cursor; the old position is
1155 // not used for data access after this point. `target` is checked above to sit at or
1156 // below the view's current position.
1157 unsafe { view.reposition(target_key, target_len) }
1158 Some(view)
1159}
1160
1161fn contains_key<P: Prefix>(
1162 root_key: P::R,
1163 root_len: u32,
1164 target_key: P::R,
1165 target_len: u32,
1166) -> bool {
1167 if root_len > target_len {
1168 return false;
1169 }
1170 let mask = mask_from_prefix_len(root_len as u8);
1171 root_key & mask == target_key & mask
1172}
1173
1174fn lpm_data_bit<'a, V: TrieView<'a>>(
1175 view: &V,
1176 target_key: <V::P as Prefix>::R,
1177 target_len: u32,
1178) -> Option<u32> {
1179 let data_bits = view.data_bitmap() & data_lpm_mask(view.depth(), target_key, target_len);
1180 if data_bits == 0 {
1181 None
1182 } else {
1183 Some(u32::BITS - 1 - data_bits.leading_zeros())
1184 }
1185}
1186
1187/// Reconstruct the prefix at `data_bit` within the node starting at `depth`.
1188pub(crate) fn reconstruct_prefix<P: Prefix>(depth: u32, key: P::R, data_bit: u32) -> P {
1189 let (offset, level) = DATA_BIT_TO_PREFIX[data_bit as usize];
1190 let prefix_len = depth + level as u32;
1191 let root = key & mask_from_prefix_len(depth as u8);
1192 let offset_r = <P::R as num_traits::cast::NumCast>::from(offset).unwrap();
1193 let offset_bits = K - 1;
1194 let total_width = P::num_bits();
1195 let shifted = if total_width > depth + offset_bits {
1196 offset_r << (total_width - (depth + offset_bits)) as usize
1197 } else {
1198 offset_r >> (depth + offset_bits - total_width) as usize
1199 };
1200 P::from_repr_len(root | shifted, prefix_len as u8)
1201}
1202
1203/// Trait that is implemented on structures that can be turned into a view.
1204pub trait AsView<'a> {
1205 /// The prefix type.
1206 type P: Prefix;
1207 /// The concrete view type returned by [`view`][AsView::view].
1208 type View: TrieView<'a, P = Self::P>;
1209
1210 /// Get a view rooted at the origin (the entire trie).
1211 fn view(self) -> Self::View;
1212
1213 /// Get a view rooted at `prefix`, or `None` if the sub-trie is empty.
1214 ///
1215 /// The emptiness check may over-approximate on composed views (see
1216 /// [`TrieView::is_non_empty`]): the returned view may yield no entries when iterated.
1217 /// `None` always means that the view contains nothing at or below `prefix`. To check
1218 /// exactly whether the sub-trie contains an entry, iterate the returned view:
1219 /// `view.iter().next().is_none()`. Note that [`TrieView::iter`] takes the view by value;
1220 /// clone it first if you still need it afterwards.
1221 fn view_at(self, prefix: &Self::P) -> Option<Self::View>
1222 where
1223 Self: Sized,
1224 {
1225 self.view().find(prefix)
1226 }
1227}