Skip to main content

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}