use super::*;
use ptrplus::AsPtr;
use std::{marker::PhantomPinned, ptr::NonNull};
#[derive(Debug, Default)]
pub struct NodeBuilder<T> {
pub content: T,
pub children: Vec<Self>,
}
impl<T> NodeBuilder<T> {
pub fn new(content: T) -> Self {
NodeBuilder {
content,
children: vec![],
}
}
pub fn child(mut self, child: Self) -> Self {
self.children.push(child);
self
}
pub fn build(self) -> Tree<T> {
let mut root = Box::pin(Node {
content: self.content,
parent: None,
children: vec![],
_pin: PhantomPinned,
});
unsafe { root.as_mut().get_unchecked_mut() }.children =
Self::build_children(root.ptr(), self.children);
Tree { root }
}
fn build_children(parent: Parent<Node<T>>, children: Vec<Self>) -> Vec<Owned<Node<T>>> {
children
.into_iter()
.map(|builder| {
let mut child = Box::pin(Node {
content: builder.content,
parent: Some(parent),
children: vec![],
_pin: PhantomPinned,
});
unsafe { child.as_mut().get_unchecked_mut() }.children =
Self::build_children(child.ptr(), builder.children);
child
})
.collect()
}
}
pub struct Node<T> {
pub content: T,
parent: Option<Parent<Self>>,
children: Vec<Owned<Self>>,
_pin: PhantomPinned,
}
impl<T> Node<T> {
#[inline]
pub fn builder(content: T) -> NodeBuilder<T> {
NodeBuilder::new(content)
}
pub fn parent(&self) -> Option<&Self> {
self.parent.map(|p| unsafe { p.as_ref() })
}
pub fn children(&self) -> Box<[&Self]> {
self.children
.iter()
.map(|child| child.as_ref().get_ref())
.collect()
}
fn is_descendant(&self, other: NonNull<Self>) -> bool {
if self.is_same_as(other) {
return false;
}
let mut ancestor = unsafe { other.as_ref() }.parent();
while let Some(node) = ancestor {
if self.is_same_as(node) {
return true;
}
ancestor = node.parent();
}
false
}
fn find_self_next<'a>(&self, iter: impl Iterator<Item = &'a Owned<Self>>) -> Option<&'a Self> {
let mut iter = iter.map(|sib| sib.as_ref().get_ref());
iter.find(|sib| self.is_same_as(*sib));
iter.next()
}
pub fn next_sibling(&self) -> Option<&Self> {
self.find_self_next(self.parent()?.children.iter())
}
pub fn prev_sibling(&self) -> Option<&Self> {
self.find_self_next(self.parent()?.children.iter().rev())
}
pub fn append_child(self: Pin<&mut Self>, mut child: Tree<T>) {
unsafe {
let this = self.get_unchecked_mut();
child.root_mut().get_unchecked_mut().parent = Some(NonNull::new_unchecked(this));
this.children.push(child.root)
}
}
pub fn insert_child(self: Pin<&mut Self>, mut child: Tree<T>, index: usize) {
unsafe {
let this = self.get_unchecked_mut();
child.root_mut().get_unchecked_mut().parent = Some(NonNull::new_unchecked(this));
this.children.insert(index, child.root)
}
}
pub(super) fn detach_descendant(self: Pin<&mut Self>, descendant: NonNull<Self>) -> Option<Tree<T>> {
if !self.is_descendant(descendant) {
return None;
}
let parent = unsafe { descendant.as_ref().parent.unwrap().as_mut() };
let index = parent
.children
.iter()
.position(|child| descendant.as_ptr() == child.ptr().as_ptr())
.expect("Node is not found in its parent");
let mut root = parent.children.remove(index);
unsafe { root.as_mut().get_unchecked_mut() }.parent = None;
Some(Tree { root })
}
pub(super) fn borrow_descendant(self: Pin<&mut Self>, descendant: NonNull<Self>) -> Option<Pin<&mut Self>> {
if self.is_descendant(descendant) {
Some(unsafe { Pin::new_unchecked(&mut *descendant.as_ptr()) })
} else {
None
}
}
#[inline]
pub fn iter_bfs(&self) -> IterBFS<T> {
IterBFS::new(self)
}
#[inline]
pub fn iter_dfs(&self) -> IterDFS<T> {
IterDFS::new(self)
}
#[inline]
pub fn is_same_as(&self, other: impl AsPtr<Raw = Self>) -> bool {
std::ptr::eq(self, other.as_ptr())
}
#[inline]
pub fn ptr(&self) -> NonNull<Self> {
NonNull::from(self)
}
}
impl<T: Default> Default for Node<T> {
fn default() -> Self {
Self {
content: T::default(),
parent: None,
children: vec![],
_pin: PhantomPinned,
}
}
}
impl<T: Clone> Clone for Node<T> {
fn clone(&self) -> Self {
Self {
content: self.content.clone(),
parent: None,
children: vec![],
_pin: PhantomPinned,
}
}
}
impl<T: Clone> Node<T> {
pub fn clone_deep(&self) -> Tree<T> {
let mut root = Box::pin(self.clone());
unsafe { root.as_mut().get_unchecked_mut() }.children =
self.clone_children_deep(root.ptr());
Tree { root }
}
fn clone_children_deep(&self, parent: Parent<Self>) -> Vec<Owned<Self>> {
self.children
.iter()
.map(|node| {
let mut child = Box::pin(node.as_ref().get_ref().clone());
let mut_child = unsafe { child.as_mut().get_unchecked_mut() };
mut_child.parent = Some(parent);
mut_child.children = node.clone_children_deep(mut_child.ptr());
child
})
.collect()
}
}
impl<T: Debug> Node<T> {
#[inline]
pub fn debug_tree(&self) -> DebugTree<T> {
DebugTree { root: self }
}
}
impl<T: Debug> Debug for Node<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Node")
.field("content", &self.content)
.field(
"children",
&self
.children()
.iter()
.map(|c| &c.content)
.collect::<Box<_>>(),
)
.finish()
}
}
impl<T: PartialEq> PartialEq for Node<T> {
fn eq(&self, other: &Self) -> bool {
self.content == other.content
}
}
impl<T: Eq> Eq for Node<T> {}