pub mod covering_difference;
pub mod covering_union;
pub mod difference;
pub mod intersection;
pub(crate) mod iter;
pub mod trie_ref;
pub mod trie_ref_mut;
pub mod union;
pub use covering_difference::CoveringDifferenceView;
pub use covering_union::{CoveringUnionItem, CoveringUnionView};
pub use difference::DifferenceView;
pub use intersection::IntersectionView;
pub use iter::{ViewIter, ViewKeys, ViewValues};
pub use trie_ref::TrieRef;
pub use trie_ref_mut::TrieRefMut;
pub use union::{UnionItem, UnionView};
use num_traits::{One, PrimInt, Zero};
use crate::{
prefix::mask_from_prefix_len,
Prefix,
{
node::{child_bit, data_bit, data_lpm_mask, DATA_BIT_TO_PREFIX},
table::K,
},
};
pub trait TrieView<'a>: Sized {
type P: Prefix;
type T: 'a;
fn depth(&self) -> u32;
fn key(&self) -> <Self::P as Prefix>::R;
fn prefix_len(&self) -> u32;
fn data_bitmap(&self) -> u32;
fn child_bitmap(&self) -> u32;
unsafe fn get_data(&mut self, data_bit: u32) -> Self::T;
unsafe fn get_child(&mut self, child_bit: u32) -> Self;
unsafe fn reposition(&mut self, key: <Self::P as Prefix>::R, prefix_len: u32);
#[inline]
fn is_non_empty(&self) -> bool {
self.data_bitmap() != 0 || self.child_bitmap() != 0
}
#[inline]
fn prefix(&self) -> Self::P {
let masked = self.key() & mask_from_prefix_len(self.prefix_len() as u8);
Self::P::from_repr_len(masked, self.prefix_len() as u8)
}
#[inline]
fn value(mut self) -> Option<Self::T> {
let data_bit = data_bit(self.key(), self.prefix_len());
if (self.data_bitmap() >> data_bit) & 1 == 1 {
Some(unsafe { self.get_data(data_bit) })
} else {
None
}
}
#[inline]
fn prefix_value(mut self) -> Option<(Self::P, Self::T)> {
let data_bit = data_bit(self.key(), self.prefix_len());
if (self.data_bitmap() >> data_bit) & 1 == 1 {
let prefix = self.prefix();
Some((prefix, unsafe { self.get_data(data_bit) }))
} else {
None
}
}
#[inline]
fn left(self) -> Option<Self> {
self.step(false)
}
#[inline]
fn right(self) -> Option<Self> {
self.step(true)
}
fn navigate_to(mut self, target_key: <Self::P as Prefix>::R, target_len: u32) -> Option<Self> {
while target_len >= self.depth() + K {
let child_bit = child_bit(self.depth(), target_key);
if (self.child_bitmap() >> child_bit) & 1 == 0 {
return None;
}
self = unsafe { self.get_child(child_bit) };
}
unsafe { self.reposition(target_key, target_len) }
Some(self)
}
#[inline]
fn find(self, prefix: &Self::P) -> Option<Self> {
let view = self.navigate_to(prefix.mask(), prefix.prefix_len() as u32)?;
if view.is_non_empty() {
Some(view)
} else {
None
}
}
#[inline]
fn find_exact(self, prefix: &Self::P) -> Option<Self> {
let view = self.navigate_to(prefix.mask(), prefix.prefix_len() as u32)?;
let data_bit = data_bit(view.key(), view.prefix_len());
if (view.data_bitmap() >> data_bit) & 1 == 1 {
Some(view)
} else {
None
}
}
#[inline]
fn find_exact_value(self, prefix: &Self::P) -> Option<(Self::P, Self::T)> {
let view = self.navigate_to(prefix.mask(), prefix.prefix_len() as u32)?;
view.prefix_value()
}
fn find_lpm(mut self, prefix: &Self::P) -> Option<Self>
where
Self: Clone,
{
let target_key = prefix.mask();
let target_len = prefix.prefix_len() as u32;
if !contains_key::<Self::P>(self.key(), self.prefix_len(), target_key, target_len) {
return None;
}
let mut best = None;
loop {
if let Some(data_bit) = lpm_data_bit(&self, target_key, target_len) {
let prefix = reconstruct_prefix::<Self::P>(self.depth(), self.key(), data_bit);
let mut view = self.clone();
unsafe { view.reposition(prefix.mask(), prefix.prefix_len() as u32) };
best = Some(view);
}
if target_len < self.depth() + K {
return best;
}
let child_bit = child_bit(self.depth(), target_key);
if (self.child_bitmap() >> child_bit) & 1 == 0 {
return best;
}
self = unsafe { self.get_child(child_bit) };
}
}
fn find_lpm_value(mut self, prefix: &Self::P) -> Option<(Self::P, Self::T)> {
let target_key = prefix.mask();
let target_len = prefix.prefix_len() as u32;
if !contains_key::<Self::P>(self.key(), self.prefix_len(), target_key, target_len) {
return None;
}
let mut best = None;
loop {
if let Some(data_bit) = lpm_data_bit(&self, target_key, target_len) {
let prefix = reconstruct_prefix::<Self::P>(self.depth(), self.key(), data_bit);
drop(best.take());
best = Some((prefix, unsafe { self.get_data(data_bit) }));
}
if target_len < self.depth() + K {
return best;
}
let child_bit = child_bit(self.depth(), target_key);
if (self.child_bitmap() >> child_bit) & 1 == 0 {
return best;
}
self = unsafe { self.get_child(child_bit) };
}
}
#[inline]
fn iter(self) -> ViewIter<'a, Self> {
ViewIter::new(self)
}
#[inline]
fn keys(self) -> ViewKeys<'a, Self> {
ViewKeys::new(self)
}
#[inline]
fn values(self) -> ViewValues<'a, Self> {
ViewValues::new(self)
}
#[inline]
fn intersection<R>(self, other: R) -> Option<IntersectionView<'a, Self, R::View>>
where
R: AsView<'a, P = Self::P>,
{
IntersectionView::new(self, other.view())
}
#[inline]
fn union<R>(self, other: R) -> UnionView<'a, Self, R::View>
where
R: AsView<'a, P = Self::P>,
{
UnionView::new(self, other.view())
}
#[inline]
fn covering_union<R>(self, other: R) -> CoveringUnionView<'a, Self, R::View>
where
Self: Clone,
R: AsView<'a, P = Self::P>,
R::View: Clone,
{
CoveringUnionView::new(self, other.view())
}
#[inline]
fn difference<R>(self, other: R) -> DifferenceView<'a, Self, R::View>
where
R: AsView<'a, P = Self::P>,
{
DifferenceView::new(self, other.view())
}
#[inline]
fn covering_difference<R>(self, other: R) -> CoveringDifferenceView<'a, Self, R::View>
where
R: AsView<'a, P = Self::P>,
{
CoveringDifferenceView::new(self, other.view())
}
fn step(mut self, go_right: bool) -> Option<Self> {
let new_prefix_len = self.prefix_len() + 1;
let new_key = if go_right {
let bit_pos = <Self::P as Prefix>::R::zero().count_zeros() - self.prefix_len() - 1;
self.key() | <Self::P as Prefix>::R::one().unsigned_shl(bit_pos)
} else {
self.key()
};
if new_prefix_len < self.depth() + K {
unsafe { self.reposition(new_key, new_prefix_len) };
if self.is_non_empty() {
Some(self)
} else {
None
}
} else {
let child_bit = child_bit(self.depth(), new_key);
if (self.child_bitmap() >> child_bit) & 1 == 0 {
return None;
}
Some(unsafe { self.get_child(child_bit) })
}
}
}
fn contains_key<P: Prefix>(
root_key: P::R,
root_len: u32,
target_key: P::R,
target_len: u32,
) -> bool {
if root_len > target_len {
return false;
}
let mask = mask_from_prefix_len(root_len as u8);
root_key & mask == target_key & mask
}
fn lpm_data_bit<'a, V: TrieView<'a>>(
view: &V,
target_key: <V::P as Prefix>::R,
target_len: u32,
) -> Option<u32> {
let data_bits = view.data_bitmap() & data_lpm_mask(view.depth(), target_key, target_len);
if data_bits == 0 {
None
} else {
Some(u32::BITS - 1 - data_bits.leading_zeros())
}
}
pub(crate) fn reconstruct_prefix<P: Prefix>(depth: u32, key: P::R, data_bit: u32) -> P {
let (offset, level) = DATA_BIT_TO_PREFIX[data_bit as usize];
let prefix_len = depth + level as u32;
let root = key & mask_from_prefix_len(depth as u8);
let offset_r = <P::R as num_traits::cast::NumCast>::from(offset).unwrap();
let offset_bits = K - 1;
let total_width = P::num_bits();
let shifted = if total_width > depth + offset_bits {
offset_r << (total_width - (depth + offset_bits)) as usize
} else {
offset_r >> (depth + offset_bits - total_width) as usize
};
P::from_repr_len(root | shifted, prefix_len as u8)
}
pub trait AsView<'a> {
type P: Prefix;
type View: TrieView<'a, P = Self::P>;
fn view(self) -> Self::View;
fn view_at(self, prefix: &Self::P) -> Option<Self::View>
where
Self: Sized,
{
self.view().find(prefix)
}
}