use std::{fmt::Debug, hash::Hash, mem};
use crate::path::Path;
use super::{iter::Iter, node::TreeNode, DiffTree, NodeIDX, Tree};
impl<N, B> Tree<N, B>
where
B: Clone + Debug + Default + PartialEq + Eq + PartialOrd + Ord + Hash,
N: Debug + PartialEq,
{
pub fn iter(&self) -> Iter<'_, N, B> {
Iter::new(self)
}
}
impl<N, B> Tree<N, B>
where
B: Clone + Debug + Default + PartialEq + Eq + PartialOrd + Ord + Hash,
N: Debug + Default + PartialEq,
{
pub(super) fn extend(&mut self, path: &Path<B>, from_idx: Option<NodeIDX>) -> NodeIDX {
match self.get_idx(path, from_idx) {
Ok(idx) => idx,
Err(node) => {
let (mut node_idx, path_idx) = node.unwrap_or_else(|| {
self.insert_root(Default::default());
(0, 0)
});
for attr in path.path_from(path_idx) {
let node_idx_new = self.nodes.len();
self.nodes.push(TreeNode::default());
self.nodes[node_idx].children.insert(attr, node_idx_new);
node_idx = node_idx_new;
}
node_idx
}
}
}
pub fn insert_extend(&mut self, path: &Path<B>, value: N) -> N {
let idx = self.extend(path, None);
mem::replace(&mut self.nodes[idx].value, value)
}
pub fn overwrite_extend(&mut self, diff: DiffTree<N, B>) {
for (ph, d) in diff {
if let Some(now) = d.1 {
self.insert_extend(&ph, now);
} else if d.0.is_some() {
self.remove_sub_tree(&ph);
}
}
}
pub fn apply_extend(&mut self, diff: DiffTree<N, B>) -> Result<(), Path<B>> {
for (ph, d) in diff.iter() {
if let Some(before) = &d.0 {
let node_idx = self
.get_idx(&ph, None)
.map_err(|r| ph.path_to(r.unwrap_or((0, 0)).1))?;
if &self.nodes[node_idx].value != before {
return Err(ph);
}
} else if d.1.is_some() {
let mut ph = ph.clone();
ph.pop_leaf();
self.get_idx(&ph, None)
.map_err(|r| ph.path_to(r.unwrap_or((0, 0)).1))?;
}
}
self.overwrite_extend(diff);
Ok(())
}
pub fn remove_sub_tree_trim(&mut self, path: &Path<B>) -> Result<(), Option<Path<B>>> {
let mut path = path.clone();
self.remove_sub_tree(&path)?;
if let Some(mut branch) = path.pop_leaf() {
let mut parents = self
.get_path_idxs(&path)
.map_err(|r| path.path_to(*r.unwrap_or((vec![0], 0)).0.last().unwrap_or(&0)))?;
while !parents.is_empty() {
let parent = &mut self.nodes[*parents.last().unwrap()];
if parent.children.len() == 1 && parent.value == Default::default() {
self.nodes.remove(parents.pop().unwrap());
branch = path.pop_leaf().unwrap();
}
}
if !parents.is_empty() {
self.nodes[*parents.last().unwrap()]
.children
.remove(&branch);
}
}
Ok(())
}
pub fn try_build(self) -> Option<Tree<N, B>> {
self.into_iter()
.try_fold(Tree::new(), |mut tree, (path, value)| {
tree.insert(&path, value).map(|_| tree).ok()
})
}
}