use std::{
hash::Hash,
ops::{Deref, DerefMut},
};
use crate::{
path::Path,
tree::{
position::{AttachedPosition, DetachedPosition},
Position,
},
};
use super::{node::Node, Entry, NodeIDX, Tree, TREEBOUND};
pub struct DetachedEntry<R, N, B, const BOUND: bool>
where
R: Deref<Target = Tree<N, B>>,
{
pub(super) tree: R,
pub(super) position: DetachedPosition<B, usize>,
}
impl<R, N, B, const BOUND: bool> From<(R, Path<B>, Path<NodeIDX>)> for DetachedEntry<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: DetachedPosition::from(path, idxs),
}
}
}
impl<R, N, B, const BOUND: bool> DetachedEntry<R, N, B, BOUND>
where
R: Deref<Target = Tree<N, B>>,
{
pub fn from(tree: R, position: DetachedPosition<B, usize>) -> Self {
Self { tree, position }
}
pub(super) fn into_node(self, position: AttachedPosition<B, NodeIDX>) -> Node<R, N, B, BOUND> {
Node {
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 path(&self) -> &Path<B> {
self.position.path()
}
pub fn iter_detached_path(&self) -> std::collections::vec_deque::Iter<'_, B> {
self.position.iter_detached_path()
}
}
impl<R, N, B, const BOUND: bool> DetachedEntry<R, N, B, BOUND>
where
R: DerefMut<Target = Tree<N, B>>,
B: Eq + Hash + Clone,
{
pub fn insert(
mut self,
value: N,
) -> Result<Node<R, N, B, BOUND>, DetachedEntry<R, N, B, BOUND>> {
if self.position.is_empty() {
self.tree.insert_root(value);
let idx = self.tree.get_root_idx().unwrap();
let pos = self.position.attach(idx).unwrap_attached();
return Ok(Node::from(self.tree, pos));
}
if !self.position.is_rooted() {
return Err(self);
}
let path: Path<B> = self.position.iter_detached_path().cloned().collect();
match path.len() {
1 => {
let idx = self
.tree
.insert_at(
*self.position.detached_at().unwrap(),
path.last().unwrap().clone(),
value,
)
.1;
let pos = self.position.attach(idx).unwrap_attached();
Ok(Node::from(self.tree, pos))
}
0 => {
unreachable!("DetachedEntry is not detached");
}
_ => Err(self),
}
}
}
impl<R, N, B> DetachedEntry<R, N, B, TREEBOUND>
where
R: DerefMut<Target = Tree<N, B>>,
N: Default,
B: Default + Eq + Hash + Clone,
{
pub fn insert_extend(mut self, value: N) -> Node<R, N, B, TREEBOUND> {
let detached_path = self.position.iter_detached_path().cloned().collect();
let pos = if let Some(idx) = self.position.detached_at().copied() {
self.position
.attach_all(self.tree.extend(&detached_path, Some(idx)))
.unwrap_attached()
} else {
self.tree.insert_root(Default::default());
let idx = self.tree.get_root_idx().unwrap();
let pos = self.position.attach(idx);
if pos.is_attached() {
pos.unwrap_attached()
} else {
pos.unwrap_detached()
.attach_all(self.tree.extend(&detached_path, Some(idx)))
.unwrap_attached()
}
};
self.tree.nodes[*pos.at()].value = value;
Node::from(self.tree, pos)
}
}
impl<R, N, B> DetachedEntry<R, N, B, TREEBOUND>
where
R: Deref<Target = Tree<N, B>>,
{
pub fn move_to_attached(
self,
) -> Result<Node<R, N, B, TREEBOUND>, DetachedEntry<R, N, B, TREEBOUND>> {
match self.position.move_to_attached() {
Ok(attached_position) => Ok(Node::from(self.tree, attached_position)),
Err(detached_position) => Err(DetachedEntry::from(self.tree, detached_position)),
}
}
pub fn move_down(&mut self, path: Path<B>) {
for branch in path {
self.position.move_down(branch);
}
}
pub fn move_down_branch(&mut self, branch: B) {
self.position.move_down(branch);
}
pub fn move_up(mut self, up: usize) -> (Entry<R, N, B, TREEBOUND>, Option<usize>) {
let (pos, overflow) = self.position.move_up(up);
(
match pos {
Position::Attached(position) => Node::from(self.tree, position).into(),
Position::Detached(position) => {
self.position = position;
self.into()
}
},
overflow,
)
}
}
impl<R, N, B, const BOUND: bool> DetachedEntry<R, N, B, BOUND>
where
R: Deref<Target = Tree<N, B>>,
{
pub fn offshoot_len(&self) -> usize {
self.position.offshoot_len()
}
}