use core::{
marker::PhantomData,
ops::{Index, IndexMut},
};
use crate::{
BTreeInteger, NodeRef,
node::NodePos,
node::{MAX_POOL_SIZE, node_layout},
};
#[inline]
pub(crate) const fn max_height<I: BTreeInteger>() -> usize {
let mut nodes = MAX_POOL_SIZE / node_layout::<I, ()>().0.size();
let mut height = 0;
while nodes > 1 {
height += 1;
if nodes < I::B {
break;
}
nodes = nodes.div_ceil(I::B / 2);
}
height
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct Height<I: BTreeInteger> {
height: usize,
marker: PhantomData<fn() -> I>,
}
impl<I: BTreeInteger> Height<I> {
#[inline]
pub(crate) fn leaf() -> Self {
Self {
height: 0,
marker: PhantomData,
}
}
#[inline]
pub(crate) fn max() -> Self {
Self {
height: max_height::<I>(),
marker: PhantomData,
}
}
#[inline]
pub(crate) fn down(self) -> Option<Self> {
if self.height == 0 {
None
} else {
Some(Self {
height: self.height - 1,
marker: PhantomData,
})
}
}
#[inline]
pub(crate) fn up(self, max: Height<I>) -> Option<Self> {
if self.height >= max.height {
None
} else {
Some(Self {
height: self.height + 1,
marker: PhantomData,
})
}
}
}
#[derive(Clone)]
pub(crate) struct Stack<I: BTreeInteger, const H: usize> {
entries: [(NodeRef, NodePos<I>); H],
}
impl<I: BTreeInteger, const H: usize> Default for Stack<I, H> {
#[inline]
fn default() -> Self {
Self {
entries: [(NodeRef::zero(), NodePos::zero()); H],
}
}
}
impl<I: BTreeInteger, const H: usize> Index<Height<I>> for Stack<I, H> {
type Output = (NodeRef, NodePos<I>);
#[inline]
fn index(&self, index: Height<I>) -> &Self::Output {
const { assert!(H == max_height::<I>()) };
unsafe { self.entries.get_unchecked(index.height) }
}
}
impl<I: BTreeInteger, const H: usize> IndexMut<Height<I>> for Stack<I, H> {
#[inline]
fn index_mut(&mut self, index: Height<I>) -> &mut Self::Output {
const { assert!(H == max_height::<I>()) };
unsafe { self.entries.get_unchecked_mut(index.height) }
}
}