use std::{
hash::Hash,
ops::{Deref, DerefMut},
};
use crate::{
path::Path,
prelude::iter::depth::{Iter, TreeIterTarget},
tree::{
position::{AttachedPosition, DetachedPosition},
Position,
},
};
use super::{detached::DetachedEntry, Entry, NodeIDX, Tree, NODEBOUND, TREEBOUND};
pub type TreeNode<R, N, B> = Node<R, N, B, NODEBOUND>;
pub struct Node<R, N, B, const BOUND: bool>
where
R: Deref<Target = Tree<N, B>>,
{
pub(super) tree: R,
pub(super) position: AttachedPosition<B, NodeIDX>,
}
impl<R, N, B, const BOUND: bool> Deref for Node<R, N, B, BOUND>
where
R: Deref<Target = Tree<N, B>>,
{
type Target = N;
fn deref(&self) -> &Self::Target {
self.value()
}
}
impl<R, N, B, const BOUND: bool> DerefMut for Node<R, N, B, BOUND>
where
R: DerefMut<Target = Tree<N, B>>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.value_mut()
}
}
impl<R, N, B, const BOUND: bool> From<(R, Path<B>, Path<NodeIDX>)> for Node<R, N, B, BOUND>
where
R: Deref<Target = Tree<N, B>>,
{
fn from((tree, path, idxs): (R, Path<B>, Path<NodeIDX>)) -> Self {
Self {
tree,
position: AttachedPosition::from(path, idxs),
}
}
}
impl<R, N, B, const BOUND: bool> Node<R, N, B, BOUND>
where
R: Deref<Target = Tree<N, B>>,
{
pub fn from(tree: R, position: AttachedPosition<B, NodeIDX>) -> Self {
Self { tree, position }
}
pub(super) fn into_detached_entry(
self,
position: DetachedPosition<B, NodeIDX>,
) -> DetachedEntry<R, N, B, BOUND> {
DetachedEntry {
tree: self.tree,
position,
}
}
pub fn into_entry(self) -> Entry<R, N, B, BOUND> {
self.into()
}
pub fn branch(&self) -> Option<&B> {
self.position.at_branch()
}
pub fn children(&self) -> Vec<&B> {
self.tree.nodes[*self.position.at()]
.children
.keys()
.collect() }
pub fn path(&self) -> &Path<B> {
self.position.path()
}
pub fn value(&self) -> &N {
&self.tree.nodes[*self.position.at()].value
}
}
impl<R, N, B, const BOUND: bool> Node<R, N, B, BOUND>
where
R: DerefMut<Target = Tree<N, B>>,
{
pub fn insert(&mut self, value: N) -> N {
std::mem::replace(&mut self.tree.nodes[*self.position.at()].value, value)
}
pub fn value_mut(&mut self) -> &mut N {
&mut self.tree.nodes[*self.position.at()].value
}
}
impl<'a, N, B> Node<&'a Tree<N, B>, N, B, TREEBOUND> {
pub fn iter<T: TreeIterTarget<'a, N, B>>(&self) -> Iter<'a, N, B, T> {
Iter::new(self.tree)
}
}
impl<R, N, B> Node<R, N, B, TREEBOUND>
where
R: Deref<Target = Tree<N, B>>,
{
pub fn move_up(&mut self, up: usize) -> Option<usize> {
self.position.move_up(up)
}
}
impl<R, N, B> Node<R, N, B, TREEBOUND>
where
R: Deref<Target = Tree<N, B>>,
B: Eq + Hash,
{
pub fn move_down(mut self, mut path: Path<B>) -> Entry<R, N, B, TREEBOUND> {
let mut position = Position::Attached(self.position);
let mut p_idx = *position.attached_mut().unwrap().at();
while position.is_attached() {
if path.is_empty() {
break;
}
let branch = path.pop_first().unwrap();
match self.tree.nodes[p_idx].children.get(&branch).copied() {
Some(idx) => {
position.attached_mut().unwrap().move_down(branch, idx);
p_idx = idx;
}
None => {
let detached = match position {
Position::Attached(attached) => attached.move_down_detach(branch),
Position::Detached(detached) => detached,
};
position = Position::Detached(detached);
}
}
}
if let Position::Detached(mut detached_position) = position {
for branch in path {
detached_position.move_down(branch);
}
DetachedEntry::from(self.tree, detached_position).into()
} else {
self.position = position.unwrap_attached();
self.into()
}
}
pub fn move_down_branch(mut self, branch: B) -> Entry<R, N, B, TREEBOUND> {
if let Some(idx) = self.tree.nodes[*self.position.at()]
.children
.get(&branch)
.copied()
{
self.position.move_down(branch, idx);
self.into()
} else {
DetachedEntry::from(self.tree, self.position.move_down_detach(branch)).into()
}
}
}
impl<R, N, B> Node<R, N, B, TREEBOUND>
where
R: DerefMut<Target = Tree<N, B>>,
B: Eq + Hash + Clone,
{
pub fn remove_subtree(mut self) -> DetachedEntry<R, N, B, TREEBOUND> {
if let Some((_, &p_idx)) = self.position.parent() {
self.tree
.remove_subtree_at(p_idx, self.position.at_branch().unwrap().clone());
} else {
self.tree.clear();
}
DetachedEntry::from(self.tree, self.position.remove_node())
}
pub fn remove_child_subtrees(&mut self, children: Vec<B>) {
for c in children {
self.tree.remove_subtree_at(*self.position.at(), c);
}
}
}