use core::{
borrow::Borrow,
fmt::{Debug, Formatter},
};
use ts_array256::{Array256, ArrayStorage};
use ts_bitset::Bitset256;
use crate::BaseIndex;
mod child;
mod child_storage;
mod descendants;
mod stride_ops;
pub use child::Child;
pub use child_storage::{BoxStorage, InlineStorage, Storage};
pub use stride_ops::{
NodePrefixIter, PrefixOps, PrefixOpsExt, PrefixReadOps, Stats, StrideBase, StrideOps,
StrideOpsExt,
};
pub type DefaultStorage = BoxStorage;
pub type DefaultNode<T> = Node<T, DefaultStorage>;
cfg_if::cfg_if! {
if #[cfg(feature = "smallvec")] {
type ArrayStore<T> = smallvec::SmallVec<[T; 1]>;
} else {
type ArrayStore<T> = alloc::vec::Vec<T>;
}
}
#[derive(PartialEq, Eq, Hash)]
pub struct Node<T, C = DefaultStorage>
where
C: Storage + ?Sized,
{
pub prefixes: Array256<ArrayStore<T>>,
pub children: Array256<ArrayStore<Child<C::Container<Self>, T>>>,
}
impl<T, C> Clone for Node<T, C>
where
C: Storage + ?Sized,
T: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
prefixes: self.prefixes.clone(),
children: self.children.clone_with(&|c| match c {
Child::Path(p) => Child::Path(C::clone(p)),
Child::Fringe(p) => Child::Fringe(p.clone()),
Child::Leaf { prefix, value } => Child::Leaf {
prefix: *prefix,
value: value.clone(),
},
}),
}
}
}
impl<T, C> Debug for Node<T, C>
where
T: Debug,
C: Storage + ?Sized,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
struct IdArrayFormatter<'a, S> {
ary: &'a Array256<S>,
}
impl<S> Debug for IdArrayFormatter<'_, S>
where
S: ArrayStorage + AsRef<[S::T]>,
S::T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_map()
.entries(self.ary.bitset().bits().map(|i| {
(
BaseIndex::new(i as _).fmt_prefix(),
self.ary.get(i as _).unwrap(),
)
}))
.finish()
}
}
f.debug_struct("Node")
.field(
"prefixes",
&IdArrayFormatter {
ary: &self.prefixes,
},
)
.field(
"children",
&self
.children
.custom_storage_fmt(&Child::as_node_ref::<C, _>),
)
.finish()
}
}
impl<T, C> Default for Node<T, C>
where
C: Storage + ?Sized,
{
#[inline]
fn default() -> Self {
Self::EMPTY
}
}
impl<T, C> Node<T, C>
where
C: Storage + ?Sized,
{
pub const EMPTY: Self = Self {
prefixes: Array256::EMPTY,
children: Array256::EMPTY,
};
#[inline]
pub const fn is_empty(&self) -> bool {
self.prefixes.is_empty() && self.children.is_empty()
}
pub fn stats(&self) -> Stats
where
Self: StrideOps,
{
self.descendant_nodes(true)
.fold(Stats::default(), |mut stats, (_path, node)| {
let (leaves, fringes) = node.direct_children().fold(
(0, 0),
|(leaves, fringes), (_, child)| match child {
Child::Fringe(..) => (leaves, fringes + 1),
Child::Leaf { .. } => (leaves + 1, fringes),
_ => (leaves, fringes),
},
);
stats.node_count += 1;
stats.prefix_count += node.prefix_count();
stats.child_count += node.child_count();
stats.leaf_count += leaves;
stats.fringe_count += fringes;
stats
})
}
}
impl<T, C> StrideBase for Node<T, C>
where
T: 'static,
C: Storage + ?Sized,
{
type T = T;
}
impl<T, C> PrefixReadOps for Node<T, C>
where
T: 'static,
C: Storage + ?Sized,
{
fn prefix_bitset(&self) -> &Bitset256 {
self.prefixes.bitset()
}
fn prefix_count(&self) -> usize {
self.prefixes.len()
}
fn lookup_index(&self, idx: BaseIndex) -> Option<(BaseIndex, &Self::T)> {
let top = self.prefixes.intersection_top(crate::lpm(idx).borrow())?;
Some((BaseIndex::try_new(top)?, self.prefixes.get(top)?))
}
fn get_prefix_exact(&self, idx: BaseIndex) -> Option<&Self::T> {
self.prefixes.get(idx.get())
}
}
impl<T, C> PrefixOps for Node<T, C>
where
T: 'static,
C: Storage + ?Sized,
{
fn insert_prefix(&mut self, idx: BaseIndex, value: Self::T) -> Option<Self::T> {
self.prefixes.insert(idx.into(), value)
}
fn remove_prefix(&mut self, idx: BaseIndex) -> Option<Self::T> {
self.prefixes.remove(idx.into())
}
fn get_prefix_exact_mut(&mut self, idx: BaseIndex) -> Option<&mut Self::T> {
self.prefixes.get_mut(idx.get())
}
}
impl<T, C> StrideOps for Node<T, C>
where
T: 'static,
C: Storage + ?Sized,
{
fn child_bitset(&self) -> &Bitset256 {
self.children.bitset()
}
fn child_count(&self) -> usize {
self.children.len()
}
fn stats(&self) -> Stats {
self.stats()
}
fn insert_child(
&mut self,
addr: u8,
child: Child<Self, Self::T>,
) -> Option<Child<Self, Self::T>> {
self.children
.insert(addr, child.map_node(C::new))
.map(|ret| ret.map_node(C::into_inner))
}
fn direct_children(&self) -> impl Iterator<Item = (u8, Child<&Self, &T>)> {
self.children
.iter()
.map(|(addr, child)| (addr, child.as_node_ref::<C, _>()))
}
fn remove_child(&mut self, addr: u8) -> Option<Child<Self, Self::T>> {
self.children
.remove(addr)
.map(|ret| ret.map_node(C::into_inner))
}
fn get_child(&self, addr: u8) -> Option<Child<&Self, &Self::T>> {
self.children.get(addr).map(Child::as_node_ref::<C, _>)
}
fn get_child_mut(&mut self, addr: u8) -> Option<Child<&mut Self, &mut Self::T>> {
self.children.get_mut(addr).map(Child::as_node_mut::<C, _>)
}
fn direct_prefixes(&self) -> impl Iterator<Item = (BaseIndex, &T)> {
self.prefixes
.iter()
.map(|(idx, value)| (BaseIndex::new(idx), value))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn bart_examples_prefix_crud() {
let mut node = Node::<usize>::EMPTY;
let index = BaseIndex::new(32);
assert_eq!(None, node.insert_prefix(index, 100));
assert_eq!(1, node.prefix_count());
assert_eq!(Some(100), node.insert_prefix(index, 111));
assert_eq!(1, node.prefix_count());
assert_eq!(Some(111), node.lookup(index).copied());
assert_eq!(Some(111), node.remove_prefix(index));
assert_eq!(0, node.prefix_count());
assert_eq!(None, node.lookup(index));
assert_eq!(None, node.remove_prefix(index));
}
#[test]
fn bart_examples_contains() {
let mut node = Node::<()>::EMPTY;
node.insert_prefix(BaseIndex::new(32), ());
for idx in [32, 64, 65, 128, 129, 130, 131] {
assert!(node.supersets_prefix(BaseIndex::new(idx)));
}
for idx in [1, 16, 33, 63, 127, 132, 255] {
assert!(!node.supersets_prefix(BaseIndex::new(idx)));
}
}
#[test]
fn bart_examples_lookup() {
let mut node = Node::<usize>::EMPTY;
node.insert_prefix(BaseIndex::new(32), 1);
node.insert_prefix(BaseIndex::new(64), 2);
assert_eq!(Some(&2), node.lookup(BaseIndex::new(128)));
assert_eq!(
Some((BaseIndex::new(64), &2)),
node.lookup_index(BaseIndex::new(128))
);
assert_eq!(None, node.lookup(BaseIndex::new(127)));
}
#[test]
fn bart_examples_children_crud() {
let mut child = Node::<usize>::EMPTY;
child.insert_prefix(BaseIndex::new(1), 10);
let mut node = Node::<usize>::EMPTY;
assert!(node.insert_child(10, Child::Path(child)).is_none());
assert_eq!(1, node.child_count());
assert!(node.get_child(10).is_some_and(|c| match c {
Child::Path(inner) => inner.supersets_prefix(BaseIndex::new(1)),
_ => false,
}));
assert!(node.remove_child(10).is_some());
assert_eq!(0, node.child_count());
assert!(node.remove_child(10).is_none());
}
}