nb-tree 0.2.0-alpha01

Very simple tree structure with generic node and branch data.
Documentation
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() {
            // Insert at root
            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()
    }
    /*
    fn into_node(self) -> Node<R, N, B> {
        assert!(
            self.position.is_attached(),
            "Cannot convert to Node, position is detached"
        );
        Node {
            tree: self.tree,
            position: self.position,
        }
    }*/
}