use super::inter::*;
use super::node::NodeBase;
use core::marker::PhantomData;
pub(super) fn dummy_post_callback<K, C>(_cache: &mut C, _node: InterNode<K>) {}
macro_rules! _move_to_ancestor {
($queue: expr, $pop: ident, $cond: expr, $post: expr) => {{
let mut res = None;
while let Some((_grand_parent, idx)) = $queue.$pop() {
let grand_parent = InterNode::from(_grand_parent);
if $cond(&grand_parent, idx) {
res.replace((grand_parent, idx));
break;
} else {
($post)($queue, grand_parent);
}
}
res
}};
}
pub(crate) trait PathBuffer: Sized {
fn inc_leaf_count(&mut self);
fn dec_leaf_count(&mut self);
fn inc_inter_count(&mut self);
fn dec_inter_count(&mut self);
fn buffer_len(&self) -> u8;
fn buffer_pos(&self) -> i8;
fn _push(&mut self, inter: NodeBase, idx: u8);
fn _pop(&mut self) -> Option<(NodeBase, u8)>;
fn _last(&self) -> Option<(NodeBase, u8)>;
fn _set_pos(&mut self, buffer_pos: i8);
unsafe fn _get_unchecked(&self, idx: u8) -> (NodeBase, u8);
#[inline]
fn iter<'a, K>(&'a self) -> PathBufferIter<'a, K, Self> {
PathBufferIter { idx: self.buffer_len(), buf: self, _phan: Default::default() }
}
#[inline]
fn last<K>(&self) -> Option<(InterNode<K>, u8)> {
self._last().map(|(n, idx)| (InterNode::<K>::from(n), idx))
}
#[inline(always)]
fn assert_center(&self) {
debug_assert_eq!(self.buffer_pos(), 0);
}
#[inline]
fn _move_left_and_pop<K: Ord, F>(
&mut self, mut pos: i8, mut post_callback: F,
) -> Option<(InterNode<K>, u8)>
where
F: FnMut(&mut Self, InterNode<K>),
{
if let Some((_parent, mut idx)) = self._pop() {
let mut parent = InterNode::<K>::from(_parent);
loop {
debug_assert!(pos < 0);
let move_step = (-pos) as u8;
if idx > 0 {
if move_step <= idx {
return Some((parent, idx - move_step)); } else {
pos += idx as i8 + 1
}
} else {
pos += 1;
}
let pre_height = parent.height();
post_callback(self, parent);
let cond = |_node: &InterNode<K>, idx: u8| -> bool { idx > 0 };
if let Some((grand_parent, grand_idx)) =
_move_to_ancestor!(self, _pop, cond, post_callback)
{
(parent, idx) = grand_parent.find_child_branch::<false, Self>(
pre_height,
grand_idx - 1,
self,
);
if pos == 0 {
return Some((parent, idx));
}
} else {
return None;
}
}
}
None
}
#[inline]
fn _move_right_and_pop<K: Ord, F>(
&mut self, mut pos: i8, mut post_callback: F,
) -> Option<(InterNode<K>, u8)>
where
F: FnMut(&mut Self, InterNode<K>),
{
if let Some((_parent, mut idx)) = self._pop() {
let mut parent = InterNode::<K>::from(_parent);
loop {
debug_assert!(pos > 0);
let right_count = parent.key_count() - idx;
if right_count > 0 {
if right_count >= pos as u8 {
idx += pos as u8;
return Some((parent, idx)); } else {
pos -= right_count as i8 - 1;
}
} else {
pos -= 1;
}
let pre_height = parent.height();
post_callback(self, parent);
if let Some((grand_parent, grand_idx)) = _move_to_ancestor!(
self,
_pop,
|node: &InterNode<K>, idx: u8| -> bool { node.key_count() > idx },
post_callback
) {
(parent, idx) = grand_parent.find_child_branch::<true, Self>(
pre_height,
grand_idx + 1,
self,
);
if pos == 0 {
return Some((parent, idx));
}
} else {
return None;
}
}
}
None
}
#[inline(always)]
fn peek_parent<K: Ord>(&mut self) -> Option<(InterNode<K>, u8)> {
self.assert_center();
let (parent, idx) = self.last::<K>()?;
Some((parent.clone(), idx))
}
#[inline(always)]
fn peek_ancestor<K: Ord, FC>(&mut self, cond: FC) -> Option<(InterNode<K>, u8)>
where
FC: Fn(&InterNode<K>, u8) -> bool,
{
self.fix_path_center::<K>();
let iter = self.iter::<K>();
for (grand_parent, idx) in iter {
if cond(&grand_parent, idx) {
return Some((grand_parent.clone(), idx));
}
}
None
}
#[inline(always)]
fn move_path_to_ancestor<K: Ord, FC, FP>(
&mut self, cond: FC, mut post_callback: FP,
) -> Option<(InterNode<K>, u8)>
where
FC: Fn(&InterNode<K>, u8) -> bool,
FP: FnMut(&mut Self, InterNode<K>),
{
_move_to_ancestor!(self, pop_path, cond, post_callback)
}
#[inline(always)]
fn move_path_left<K: Ord>(&mut self) {
let mut pos = self.buffer_pos();
if pos > i8::MIN {
} else {
self._fix_center_from_left::<K>(pos);
pos = 0;
}
pos -= 1;
self._set_pos(pos);
}
#[inline(always)]
fn move_path_right<K: Ord>(&mut self) {
let mut pos = self.buffer_pos();
if pos < i8::MAX {
} else {
self._fix_center_from_right::<K>(pos);
pos = 0;
}
pos += 1;
self._set_pos(pos);
}
#[inline(always)]
fn _fix_center_from_left<K: Ord>(&mut self, pos: i8) {
debug_assert_eq!(self.buffer_pos(), pos);
debug_assert!(pos < 0);
if let Some((parent, idx)) =
self._move_left_and_pop::<K, _>(pos, dummy_post_callback::<K, Self>)
{
self._push(parent.into(), idx);
}
}
#[inline(always)]
fn _fix_center_from_right<K: Ord>(&mut self, pos: i8) {
debug_assert_eq!(self.buffer_pos(), pos);
debug_assert!(pos > 0);
if let Some((parent, idx)) =
self._move_right_and_pop::<K, _>(pos, dummy_post_callback::<K, Self>)
{
self._push(parent.into(), idx);
}
}
#[inline(always)]
fn fix_path_center<K: Ord>(&mut self) {
let pos = self.buffer_pos();
if pos == 0 {
return;
}
if pos > 0 {
self._fix_center_from_right::<K>(pos);
} else {
debug_assert!(pos < 0);
self._fix_center_from_left::<K>(pos);
}
self._set_pos(0);
}
#[inline(always)]
fn push_path<K>(&mut self, inter: InterNode<K>, idx: u8) {
self._push(inter.into(), idx);
}
#[inline(always)]
fn pop_path<K: Ord>(&mut self) -> Option<(InterNode<K>, u8)> {
let pos = self.buffer_pos();
let r = if pos == 0 {
return self._pop().map(|(node, idx)| (InterNode::from(node), idx));
} else if pos > 0 {
self._move_right_and_pop::<K, _>(pos, dummy_post_callback::<K, Self>)
} else {
debug_assert!(pos < 0);
self._move_left_and_pop::<K, _>(pos, dummy_post_callback::<K, Self>)
};
self._set_pos(0);
r
}
#[inline(always)]
fn move_path_right_and_pop_l1<K: Ord, F>(
&mut self, post_callback: F,
) -> Option<(InterNode<K>, u8)>
where
F: FnMut(&mut Self, InterNode<K>) + Clone,
{
let old_pos = self.buffer_pos();
let mut pos = old_pos;
if pos < i8::MAX {
} else {
self._fix_center_from_right::<K>(pos);
pos = 0;
}
pos += 1;
let r = self._move_right_and_pop::<K, F>(pos, post_callback);
if old_pos == 0 {
r
} else {
self._set_pos(0);
r
}
}
#[inline(always)]
fn move_path_left_and_pop_l1<K: Ord, F>(
&mut self, post_callback: F,
) -> Option<(InterNode<K>, u8)>
where
F: Fn(&mut Self, InterNode<K>) + Clone,
{
let old_pos = self.buffer_pos();
let mut pos = old_pos;
if pos > i8::MIN {
} else {
self._fix_center_from_left::<K>(pos);
pos = 0;
}
pos -= 1;
let r = self._move_left_and_pop::<K, F>(pos, post_callback);
if old_pos == 0 {
r
} else {
self._set_pos(0);
r
}
}
#[cfg(test)]
fn to_vec<K>(&self) -> alloc::vec::Vec<(InterNode<K>, u8)> {
let mut v = alloc::vec::Vec::new();
for (parent, idx) in self.iter() {
v.push((parent.clone(), idx));
}
v
}
}
pub(crate) struct PathBufferIter<'a, K, T: PathBuffer> {
pub buf: &'a T,
pub idx: u8,
pub _phan: PhantomData<fn(&K)>,
}
impl<'a, K, T: PathBuffer> Iterator for PathBufferIter<'a, K, T> {
type Item = (InterNode<K>, u8);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.idx > 0 {
self.idx -= 1;
let (node, idx) = unsafe { self.buf._get_unchecked(self.idx) };
Some((InterNode::<K>::from(node), idx))
} else {
None
}
}
}