use ts_bitset::Bitset256;
use crate::{BaseIndex, StrideBase};
pub trait PrefixOps: PrefixReadOps {
fn insert_prefix(&mut self, idx: BaseIndex, value: Self::T) -> Option<Self::T>;
fn remove_prefix(&mut self, idx: BaseIndex) -> Option<Self::T>;
fn get_prefix_exact_mut(&mut self, idx: BaseIndex) -> Option<&mut Self::T>;
}
static_assertions::assert_obj_safe!(PrefixOps<T = ()>);
impl<T> PrefixOps for &mut T
where
T: PrefixOps + ?Sized,
{
fn insert_prefix(&mut self, idx: BaseIndex, value: Self::T) -> Option<Self::T> {
(*self).insert_prefix(idx, value)
}
fn remove_prefix(&mut self, idx: BaseIndex) -> Option<Self::T> {
(*self).remove_prefix(idx)
}
fn get_prefix_exact_mut(&mut self, idx: BaseIndex) -> Option<&mut Self::T> {
(*self).get_prefix_exact_mut(idx)
}
}
pub trait PrefixReadOps: StrideBase {
fn prefix_bitset(&self) -> &Bitset256;
fn lookup_index(&self, idx: BaseIndex) -> Option<(BaseIndex, &Self::T)>;
fn get_prefix_exact(&self, idx: BaseIndex) -> Option<&Self::T>;
fn prefix_count(&self) -> usize {
self.prefix_bitset().count_ones()
}
}
static_assertions::assert_obj_safe!(PrefixReadOps<T = ()>);
impl<T> PrefixReadOps for &T
where
T: PrefixReadOps + ?Sized,
{
fn prefix_bitset(&self) -> &Bitset256 {
(*self).prefix_bitset()
}
fn lookup_index(&self, idx: BaseIndex) -> Option<(BaseIndex, &Self::T)> {
(*self).lookup_index(idx)
}
fn get_prefix_exact(&self, idx: BaseIndex) -> Option<&Self::T> {
(*self).get_prefix_exact(idx)
}
}
impl<T> PrefixReadOps for &mut T
where
T: PrefixReadOps + ?Sized,
{
fn prefix_bitset(&self) -> &Bitset256 {
(**self).prefix_bitset()
}
fn lookup_index(&self, idx: BaseIndex) -> Option<(BaseIndex, &Self::T)> {
(**self).lookup_index(idx)
}
fn get_prefix_exact(&self, idx: BaseIndex) -> Option<&Self::T> {
(**self).get_prefix_exact(idx)
}
}
pub trait PrefixOpsExt: PrefixOps {
#[inline]
fn supersets_prefix(&self, idx: BaseIndex) -> bool {
use core::borrow::Borrow;
self.prefix_bitset().intersects(crate::lpm(idx).borrow())
}
#[inline]
fn lookup(&self, idx: BaseIndex) -> Option<&Self::T> {
let (_idx, ret) = self.lookup_index(idx)?;
Some(ret)
}
#[inline]
fn with_prefix(mut self, idx: BaseIndex, value: Self::T) -> Self
where
Self: Sized,
{
self.insert_prefix(idx, value);
self
}
fn matching_prefixes(&self, octet: u8) -> NodePrefixIter<'_, Self::T>
where
Self: Sized,
{
NodePrefixIter::for_octet(self, octet)
}
}
impl<T> PrefixOpsExt for T where T: PrefixOps + ?Sized {}
pub struct NodePrefixIter<'n, T> {
node: &'n dyn PrefixReadOps<T = T>,
yield_state: Bitset256,
}
impl<'n, T> NodePrefixIter<'n, T>
where
T: 'static,
{
pub fn for_octet(node: &'n dyn PrefixReadOps<T = T>, octet: u8) -> Self {
use core::borrow::Borrow;
let idx = BaseIndex::from_pfx_7(octet);
let mut yield_state = *node.prefix_bitset();
yield_state.intersect_inplace(crate::lpm(idx).borrow());
Self { node, yield_state }
}
}
impl<'n, T> Iterator for NodePrefixIter<'n, T>
where
T: 'static,
{
type Item = (BaseIndex, &'n T);
fn next(&mut self) -> Option<Self::Item> {
while let Some(bit) = self.yield_state.last_set() {
self.yield_state.clear(bit);
let index = BaseIndex::new(bit as _);
if let Some(val) = self.node.get_prefix_exact(index) {
return Some((index, val));
}
}
None
}
}
impl<T> core::iter::FusedIterator for NodePrefixIter<'_, T> where T: 'static {}