use crate::ancestor::{Ancestor, AncestorType};
const INITIAL_STACK_CAPACITY: usize = 64;
pub struct TraverseAncestry<'a> {
stack: Vec<Ancestor<'a>>,
}
impl<'a> TraverseAncestry<'a> {
#[inline]
pub fn parent(&self) -> &Ancestor<'a> {
unsafe { self.stack.last().unwrap_unchecked() }
}
#[inline]
pub fn ancestor(&self, level: usize) -> Option<&Ancestor<'a>> {
self.stack.get(self.stack.len() - level)
}
pub fn ancestors<'b>(&'b self) -> impl Iterator<Item = &'b Ancestor<'a>> {
self.stack.iter().rev()
}
#[inline]
pub fn ancestors_depth(&self) -> usize {
self.stack.len()
}
}
impl<'a> TraverseAncestry<'a> {
pub(super) fn new() -> Self {
let mut stack = Vec::with_capacity(INITIAL_STACK_CAPACITY);
stack.push(Ancestor::None);
Self { stack }
}
#[inline]
pub(crate) fn push_stack(&mut self, ancestor: Ancestor<'a>) {
self.stack.push(ancestor);
}
#[inline]
pub(crate) unsafe fn pop_stack(&mut self) {
self.stack.pop().unwrap_unchecked();
}
#[inline]
#[allow(unsafe_code, clippy::ptr_as_ptr, clippy::ref_as_ptr)]
pub(crate) unsafe fn retag_stack(&mut self, ty: AncestorType) {
*(self.stack.last_mut().unwrap_unchecked() as *mut _ as *mut AncestorType) = ty;
}
}