use core::fmt;
use core::mem::size_of;
use core::ops::Range;
use crate::flavor::Flavor;
use crate::links::Links;
use crate::node::{Ancestors, Children, Event, Siblings, Walk, WalkEvents};
use crate::pointer::Pointer;
use crate::span::Span;
pub struct Node<'a, T, F>
where
T: Copy,
F: Flavor,
{
links: &'a Links<T, F::Index, F::Pointer>,
tree: &'a [Links<T, F::Index, F::Pointer>],
}
impl<'a, T, F> Node<'a, T, F>
where
T: Copy,
F: Flavor,
{
pub(crate) const fn new(
links: &'a Links<T, F::Index, F::Pointer>,
tree: &'a [Links<T, F::Index, F::Pointer>],
) -> Self {
Self { links, tree }
}
#[must_use]
pub fn value(&self) -> T {
self.links.data.get()
}
pub fn replace(&self, value: T) -> T {
self.links.data.replace(value)
}
#[must_use]
pub const fn has_children(&self) -> bool {
self.links.first.is_some()
}
#[must_use]
pub const fn span(&self) -> &Span<F::Index> {
&self.links.span
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.links.first.is_none()
}
#[must_use]
pub fn ancestors(&self) -> Ancestors<'a, T, F> {
Ancestors::new(Some(*self))
}
#[must_use]
pub fn siblings(&self) -> Siblings<'a, T, F> {
Siblings::new(self.tree, self.links)
}
#[must_use]
pub fn children(&self) -> Children<'a, T, F> {
Children::new(self.tree, self.links.first, self.links.last)
}
#[must_use]
pub fn walk(&self) -> Walk<'a, T, F> {
Walk::new(self.tree, Some(self.id()), Event::Next)
}
#[must_use]
pub fn walk_from(&self) -> Walk<'a, T, F> {
Walk::new(self.tree, Some(self.id()), Event::Up)
}
#[must_use]
pub fn walk_events(&self) -> WalkEvents<'a, T, F> {
WalkEvents::new(self.tree, Some(self.id()), Event::Next)
}
}
impl<'a, T, F> Node<'a, T, F>
where
T: Copy,
F: Flavor,
{
#[must_use]
pub fn parent(&self) -> Option<Node<'a, T, F>> {
self.node_at(self.links.parent?)
}
#[must_use]
pub fn prev(&self) -> Option<Node<'a, T, F>> {
self.node_at(self.links.prev?)
}
#[must_use]
pub fn next(&self) -> Option<Node<'a, T, F>> {
self.node_at(self.links.next?)
}
#[must_use]
pub fn first(&self) -> Option<Node<'a, T, F>> {
self.node_at(self.links.first?)
}
#[must_use]
pub fn last(&self) -> Option<Node<'a, T, F>> {
self.node_at(self.links.last?)
}
pub fn find_preceding<P>(&self, mut predicate: P) -> Option<Node<'a, T, F>>
where
P: FnMut(Node<'a, T, F>) -> bool,
{
let mut n = *self;
let mut n = loop {
let Some(prev) = n.prev() else {
n = n.parent()?;
continue;
};
if predicate(prev) {
break prev;
}
n = n.parent()?;
};
loop {
let Some(last) = n.last() else {
return Some(n);
};
if !predicate(last) {
return Some(n);
}
n = last;
}
}
fn node_at(&self, id: F::Pointer) -> Option<Node<'a, T, F>> {
let cur = self.tree.get(id.get())?;
Some(Self {
links: cur,
tree: self.tree,
})
}
#[must_use]
pub fn id(&self) -> F::Pointer {
let current = self.links as *const _ as usize;
let base = self.tree.as_ptr() as usize;
let id = (current - base) / size_of::<Links<T, F::Index, F::Pointer>>();
debug_assert!(id < self.tree.len(), "identifier outside of tree length");
unsafe { F::Pointer::new_unchecked(id) }
}
}
impl<T, F> Node<'_, T, F>
where
T: Copy,
F: Flavor,
{
#[must_use]
#[inline]
pub fn range(&self) -> Range<usize> {
self.links.span.range()
}
}
impl<T, F> fmt::Debug for Node<'_, T, F>
where
T: Copy + fmt::Debug,
F: Flavor<Index: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Node")
.field("data", &self.links.data.get())
.field("span", &self.links.span)
.finish()
}
}
impl<T, F> Clone for Node<'_, T, F>
where
T: Copy,
F: Flavor,
{
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T, F> Copy for Node<'_, T, F>
where
T: Copy,
F: Flavor,
{
}
impl<T, A, B> PartialEq<Node<'_, T, A>> for Node<'_, T, B>
where
T: Copy + PartialEq,
A: Flavor,
B: Flavor<Index: PartialEq<A::Index>>,
{
fn eq(&self, other: &Node<'_, T, A>) -> bool {
self.links.data.get() == other.links.data.get() && self.links.span == other.links.span
}
}
impl<T, F> Eq for Node<'_, T, F>
where
T: Copy + Eq,
F: Flavor<Index: Eq>,
{
}