pub(crate) mod clone;
pub(crate) mod default;
pub use default::TreeBuilder;
pub(crate) mod diff;
pub use diff::{DiffMap, DiffNode, DiffTree};
pub mod iter;
pub(crate) mod node;
use node::TreeNode;
pub mod entry;
pub(crate) mod position;
pub use position::Position;
use replace_with::replace_with_or_abort;
use self::diff::DiffApplyError;
use self::entry::{TreeMutEntry, TREEBOUND};
use self::iter::depth::IntoIter;
use self::{
entry::{detached::DetachedEntry, node::Node, Entry},
position::{AttachedPosition, DetachedPosition},
};
use super::path::Path;
use crate::path::PathIDX;
use iter::depth::{Iter, Traversal, TreeIterTarget};
use std::hash::Hash;
use std::mem;
use std::ops::Index;
use std::{fmt::Debug as Dbg, ops::Deref};
use tracing::{debug, error, trace, trace_span};
macro_rules! or_return {
( $e:expr, $r:expr ) => {
match $e {
Some(x) => x,
None => return $r,
}
};
}
pub(crate) type NodeIDX = usize;
#[derive(Debug, Clone)]
pub struct Tree<N, B> {
nodes: Vec<TreeNode<N, B>>,
removed: Vec<NodeIDX>,
}
impl<N, B> Default for Tree<N, B> {
fn default() -> Self {
Self {
nodes: Vec::default(),
removed: Vec::default(),
}
}
}
impl<N, B> Index<&Path<B>> for Tree<N, B>
where
B: Eq + Hash + Clone,
{
type Output = N;
fn index(&self, index: &Path<B>) -> &Self::Output {
self.get(index)
.unwrap_or_else(|_| panic!("Could not index into the tree with the given path"))
}
}
impl<N, B> PartialEq for Tree<N, B>
where
N: Eq,
B: Eq + Hash,
{
fn eq(&self, other: &Self) -> bool {
(self.is_empty() && other.is_empty())
|| (!self.is_empty()
&& !other.is_empty()
&& self.is_subtree_eq(
self.get_root_idx().unwrap(),
other,
other.get_root_idx().unwrap(),
))
}
}
impl<N, B> Eq for Tree<N, B>
where
N: Eq,
B: Eq + Hash,
{
}
impl<N, B> Tree<N, B> {
pub fn new() -> Self {
Default::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
nodes: Vec::with_capacity(capacity),
..Default::default()
}
}
pub fn reserve(&mut self, additional: usize) {
self.nodes.reserve(additional)
}
pub fn get_root(&self) -> Option<&N> {
if self.is_empty() {
None
} else {
Some(&self.nodes[0].value)
}
}
fn get_root_idx(&self) -> Option<NodeIDX> {
(!self.is_empty()).then_some(0)
}
pub fn insert_root(&mut self, value: N) -> Option<N> {
if self.nodes.is_empty() {
self.nodes.push(value.into());
None
} else if self.removed.last() == Some(&0) {
self.removed.pop();
self.removed
.append(&mut self.nodes[0].children.values().cloned().collect());
self.nodes[0] = value.into();
self.nodes[0].children = Default::default();
None
} else {
debug_assert!(
!self.removed.contains(&0),
"Root has been removed but is not the most recent deletion"
);
Some(mem::replace(&mut self.nodes[0].value, value))
}
}
fn clear(&mut self) {
*self = Tree::default();
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty() || self.removed.last() == Some(&0)
}
pub fn len(&self) -> usize {
self.iter_on::<()>().count()
}
pub fn values(&self) -> Vec<&N> {
self.iter().map(|n| n.take()).collect()
}
fn iter_on<'a, T: TreeIterTarget<'a, N, B>>(&'a self) -> Iter<'a, N, B, T> {
Iter::new(self)
}
pub fn iter(&self) -> Iter<N, B, &N> {
self.iter_on()
}
}
impl<N, B> Tree<N, B>
where
B: Eq + Hash,
{
fn get_idx(
&self,
path: &Path<B>,
from_idx: Option<NodeIDX>,
) -> Result<NodeIDX, Option<(NodeIDX, PathIDX)>> {
let root_idx = if let Some(idx) = self.get_root_idx() {
idx
} else {
return Err(None);
};
path.iter().enumerate().try_fold(
from_idx.unwrap_or(root_idx),
|node_idx, (path_idx, branch)| {
self.nodes[node_idx]
.children
.get(branch)
.cloned()
.ok_or(Some((node_idx, path_idx)))
},
)
}
fn get_path_idxs(&self, path: &Path<B>) -> Result<Vec<NodeIDX>, Option<(Vec<NodeIDX>, usize)>> {
let root_idx = if let Some(idx) = self.get_root_idx() {
idx
} else {
return Err(None);
};
path.iter()
.enumerate()
.try_fold(vec![root_idx], |mut node_idx, (path_idx, branch)| {
node_idx.push(
self.nodes[*node_idx.last().unwrap()]
.children
.get(branch)
.cloned()
.ok_or(Some((node_idx.clone(), path_idx)))?,
);
Ok(node_idx)
})
}
fn insert_at(&mut self, parent_idx: NodeIDX, child: B, value: N) -> (Option<N>, NodeIDX) {
if let Some(child_idx) = self.nodes[parent_idx].children.get(&child).cloned() {
(
Some(mem::replace(&mut self.nodes[child_idx].value, value)),
child_idx,
)
} else {
let idx = if let Some(idx) = self.removed.pop() {
self.removed
.append(&mut self.nodes[idx].children.values().cloned().collect());
self.nodes[idx] = From::from(value);
self.nodes[parent_idx].children.insert(child, idx);
idx
} else {
let idx = self.nodes.len();
self.nodes.push(From::from(value));
self.nodes[parent_idx].children.insert(child, idx);
idx
};
(None, idx)
}
}
fn remove_subtree_at(&mut self, parent_idx: NodeIDX, child: B) -> Option<NodeIDX> {
let idx = self.nodes[parent_idx].children.remove(&child)?;
self.remove_subtree_idx(idx)
}
fn remove_subtree_idx(&mut self, idx: NodeIDX) -> Option<NodeIDX> {
self.removed.push(idx);
Some(idx)
}
}
impl<N, B> Tree<N, B>
where
B: Eq + Hash + Clone,
{
pub fn get(&self, path: &Path<B>) -> Result<&N, Option<Path<B>>> {
Ok(&self.nodes[self
.get_idx(path, None)
.map_err(|r| r.map(|(_, i)| path.path_to(i)))?]
.value)
}
pub fn get_mut(&mut self, path: &Path<B>) -> Result<&mut N, Option<Path<B>>> {
let idx = self
.get_idx(path, None)
.map_err(|r| r.map(|(_, i)| path.path_to(i)))?;
Ok(&mut self.nodes[idx].value)
}
pub fn root_entry(&self) -> Entry<&Self, N, B, TREEBOUND> {
match self.get_root_idx() {
Some(root) => {
Node::from(self, AttachedPosition::from(Path::new(), Path::with(root))).into()
}
None => {
DetachedEntry::from(self, DetachedPosition::from(Path::new(), Path::new())).into()
}
}
}
pub fn root_entry_mut(&mut self) -> Entry<&mut Self, N, B, TREEBOUND> {
match self.get_root_idx() {
Some(root) => {
Node::from(self, AttachedPosition::from(Path::new(), Path::with(root))).into()
}
None => {
DetachedEntry::from(self, DetachedPosition::from(Path::new(), Path::new())).into()
}
}
}
pub fn entry(&self, path: &Path<B>) -> Entry<&Self, N, B, TREEBOUND> {
Self::get_entry(self, path)
}
pub fn entry_mut(&mut self, path: &Path<B>) -> Entry<&mut Self, N, B, TREEBOUND> {
Self::get_entry(self, path)
}
fn get_entry<R: Deref<Target = Tree<N, B>>>(s: R, path: &Path<B>) -> Entry<R, N, B, TREEBOUND> {
match s.get_path_idxs(path) {
Ok(idxs) => Node::from(s, AttachedPosition::from(path.clone(), idxs.into())).into(),
Err(e) => DetachedEntry::from(
s,
DetachedPosition::from(
path.clone(),
e.map(|(idxs, _)| idxs.into()).unwrap_or_default(),
),
)
.into(),
}
}
pub fn insert(&mut self, path: &Path<B>, value: N) -> Result<Option<N>, Option<Path<B>>> {
let mut path = path.clone();
if let Some(child) = path.pop_last() {
Ok(self
.insert_at(
self.get_idx(&path, None)
.map_err(|r| r.map(|(_, i)| path.path_to(i)))?,
child,
value,
)
.0)
} else {
Ok(self.insert_root(value))
}
}
pub fn remove_subtree(&mut self, path: &Path<B>) -> Result<(), Option<Path<B>>> {
let mut path = path.clone();
if self.is_empty() {
Err(None)
} else if let Some(child) = path.pop_last() {
let parent_idx = self
.get_idx(&path, None)
.map_err(|r| r.map(|(_, i)| path.path_to(i)))?;
self.remove_subtree_at(parent_idx, child)
.map(|_| ())
.ok_or(Some(path))
} else {
self.nodes.clear();
self.removed.clear();
Ok(())
}
}
pub fn force_apply(&mut self, diff: DiffTree<N, B>) -> bool {
self.force_apply_with(
diff,
|entry, now| entry.insert(now).is_some(),
|entry| {
replace_with_or_abort(entry, |e| e.remove_subtree());
true
},
)
}
pub fn force_apply_with<'a>(
&'a mut self,
diff: DiffTree<N, B>,
insert: InsertWith<&'a mut Tree<N, B>, N, B, false>,
delete: DeleteWith<&'a mut Tree<N, B>, N, B, false>,
) -> bool {
let mut apply_success = true;
let mut diff = diff.into_iter();
let mut entry = self.entry_mut(&Path::new());
let mut deleted = None;
match diff.next() {
Some(Traversal::Start((b, n))) => {
if let Some(now) = n {
apply_success = insert(&mut entry, now);
} else if b.is_some() {
delete(&mut entry);
return diff.next().is_none();
}
}
None => {
return true;
}
Some(_) => {
unreachable!("Tree iteration should always start with a Root node");
}
};
for d in diff {
entry.apply_move(&d);
if let Some(d) = deleted {
if d >= entry.path().len() {
deleted = None;
}
}
let (b, n) = d.take();
if let Some(now) = n {
if deleted.is_some() {
apply_success = false;
} else if !insert(&mut entry, now) {
apply_success = false;
}
} else if b.is_some() {
if deleted.is_none() {
deleted = Some(entry.path().len());
if entry.is_node() {
delete(&mut entry);
} else {
apply_success = false;
}
} }
}
apply_success
}
pub fn combine(&mut self, tree: Tree<N, B>, mode: CombinationMode) -> bool {
self.combine_with(tree, mode, |entry, now| entry.insert(now).is_some())
}
pub(crate) fn combine_with<'a>(
&'a mut self,
tree: Tree<N, B>,
mode: CombinationMode,
grow: InsertWith<&'a mut Tree<N, B>, N, B, false>,
) -> bool {
let mut entry = self.root_entry_mut();
let iter: IntoIter<N, B, TreeNode<N, B>> = IntoIter::new(tree);
for step in iter {
if entry.apply_move(&step).is_err() {
return false;
}
if let Some(node) = entry.node_mut() {
if !mode.keep() {
node.remove_child_subtrees(
node.children()
.into_iter()
.filter(|&c| step.data().children.contains_key(c))
.cloned()
.collect(),
);
}
if mode.overwrite() {
node.insert(step.take().value);
}
} else if mode.grow() {
grow(&mut entry, step.take().value);
}
}
true
}
}
type InsertWith<R, N, B, const BND: bool> = fn(&mut Entry<R, N, B, BND>, N) -> bool;
type DeleteWith<R, N, B, const BND: bool> = fn(&mut Entry<R, N, B, BND>) -> bool;
pub enum CombinationMode {
Union(bool),
Intersection(bool),
Free {
keep: bool,
grow: bool,
overwrite: bool,
},
}
impl CombinationMode {
pub fn keep(&self) -> bool {
use CombinationMode::*;
match self {
Union(_) => true,
Intersection(_) => false,
Free { keep, .. } => *keep,
}
}
pub fn grow(&self) -> bool {
use CombinationMode::*;
match self {
Union(_) => true,
Intersection(_) => false,
Free { grow, .. } => *grow,
}
}
pub fn overwrite(&self) -> bool {
use CombinationMode::*;
match self {
Union(overwrite) => *overwrite,
Intersection(overwrite) => *overwrite,
Free { overwrite, .. } => *overwrite,
}
}
}
impl<N, B> Tree<N, B>
where
B: Eq + Hash + Clone + Dbg,
{
pub fn i(&mut self, path: impl Into<Path<B>>, value: N) -> &mut Self {
let ph: Path<B> = path.into();
self.insert(&ph, value)
.unwrap_or_else(|_| panic!("Could not insert into the tree at {:?}", &ph));
self
}
}
impl<N, B> Tree<N, B>
where
N: Eq,
B: Eq + Hash,
{
fn is_subtree_eq(&self, idx_s: usize, o: &Self, idx_o: usize) -> bool {
let ns = &self.nodes[idx_s];
let no = &o.nodes[idx_o];
ns.value == no.value
&& ns.children.len() == no.children.len()
&& !ns.children.keys().any(|branch| {
!self.is_subtree_eq(
*or_return!(ns.children.get(branch), false),
o,
*or_return!(no.children.get(branch), false),
)
})
}
}
impl<N, B> Tree<N, B>
where
N: Eq,
B: Eq + Hash + Clone,
{
pub fn apply(&mut self, diff: DiffTree<N, B>) -> Result<bool, DiffApplyError<B>> {
diff.is_applicable(self)?;
Ok(self.force_apply(diff))
}
pub fn apply_diff(
&mut self,
path: Path<B>,
diff: DiffNode<N>,
) -> Result<(), DiffApplyError<B>> {
self.apply_diff_with(path, diff, |entry, v| {
if entry.offshoot_len() <= 1 {
entry.insert(v);
Ok(())
} else {
Err(DiffApplyError::Other("Expected Parent".to_string()))
}
})
}
fn apply_diff_with(
&mut self,
path: Path<B>,
diff: DiffNode<N>,
insert: fn(&mut TreeMutEntry<N, B, TREEBOUND>, N) -> Result<(), DiffApplyError<B>>,
) -> Result<(), DiffApplyError<B>> {
let mut entry = self.entry_mut(&path);
if diff.0.is_some() {
if entry.is_detached() {
return Err(DiffApplyError::Expected(path));
}
if let Some(value) = diff.1 {
entry.insert(value);
Ok(())
} else {
entry.remove_subtree();
Ok(())
}
} else if let Some(value) = diff.1 {
insert(&mut entry, value)
} else {
Ok(())
}
}
pub fn apply_map(&mut self, map: DiffMap<N, B>) -> bool {
map.into_iter().fold(true, |mut res, (ph, diff)| {
if self.apply_diff(ph, diff).is_err() {
res = false;
}
res
})
}
}
#[cfg(test)]
mod tests {
use std::collections::{HashMap, HashSet};
use test_log::test;
use tracing::{debug, trace};
use crate::prelude::{iter::depth::Traversal, DiffTree, Tree};
fn new_tree() -> Tree<usize, String> {
let mut tree: Tree<usize, String> = Tree::new();
tree.i("/", 0)
.i("/a", 1)
.i("/a/b", 2)
.i("/c", 3)
.i("/f", 4)
.i("/f/d", 5);
tree
}
#[test]
fn index() {
let mut tree1 = new_tree();
assert_eq!(tree1[&"/".into()], 0);
assert_eq!(tree1[&"/a".into()], 1);
assert_eq!(tree1[&"/f/d".into()], 5);
tree1.i("/z", 2);
assert_eq!(tree1[&"/z".into()], 2);
}
#[test]
#[should_panic]
fn index_inexistent1() {
let tree1 = new_tree();
tree1[&"/w".into()];
}
#[test]
#[should_panic]
fn index_inexistent2() {
let tree1 = new_tree();
tree1[&"/f/d/z".into()];
}
#[test]
#[should_panic]
fn index_inexistent3() {
let tree1 = new_tree();
tree1[&"/f/a".into()];
}
#[test]
fn eq_tree() {
let tree1 = new_tree();
assert_eq!(tree1, new_tree());
assert_eq!(Tree::<usize, usize>::new(), Tree::<usize, usize>::new());
let mut tree_branch = new_tree();
tree_branch.i("/w", 7);
assert_ne!(tree1, tree_branch);
let mut tree_value = new_tree();
tree_value.i("/a", 7);
assert_ne!(tree1, tree_value);
assert_ne!(tree1, Tree::<usize, String>::new());
}
#[test]
fn new() {
let tree1: Tree<usize, String> = Tree::new();
assert!(tree1.is_empty());
}
#[test]
fn get_root() {
let mut tree1: Tree<usize, String> = Tree::new();
assert!(tree1.get_root().is_none());
tree1.i("/", 5);
assert_eq!(tree1.get_root(), Some(&5));
}
#[test]
fn get_root_idx() {
let mut tree1: Tree<usize, String> = Tree::new();
assert!(tree1.get_root().is_none());
tree1.i("/", 5);
assert!(tree1.get_root().is_some());
}
#[test]
fn insert_root() {
let mut tree1: Tree<usize, String> = Tree::new();
assert_eq!(tree1.insert_root(0), None);
assert_eq!(tree1.len(), 1);
assert_eq!(tree1.insert_root(1), Some(0));
assert_eq!(tree1.insert_root(1), Some(1));
assert_eq!(tree1.insert_root(2), Some(1));
assert_eq!(tree1.insert_root(3), Some(2));
tree1.clear();
assert_eq!(tree1.insert_root(1), None);
assert_eq!(tree1.insert_root(3), Some(1));
tree1.i("/branch", 7);
assert_eq!(tree1.len(), 2);
assert_eq!(tree1.insert_root(5), Some(3));
assert_eq!(tree1.len(), 2);
assert_eq!(tree1.get_root(), Some(&5));
}
#[test]
fn clear() {
let mut tree1: Tree<usize, String> = new_tree();
tree1.clear();
assert_eq!(tree1, Tree::new());
tree1.i("/", 1);
let mut small_tree = Tree::new();
small_tree.i("/", 1);
assert_eq!(tree1, small_tree);
tree1.clear();
assert_eq!(tree1, Tree::new());
tree1.i("/", 1);
tree1.i("/i", 2);
tree1.i("/v", 2);
tree1.i("/c", 5);
tree1.i("/c/d", 3);
tree1.remove_subtree(&"/c".into()).unwrap();
tree1.remove_subtree(&"/i".into()).unwrap();
tree1.remove_subtree(&"/v".into()).unwrap();
assert_eq!(tree1, small_tree);
tree1.clear();
assert_eq!(tree1, Tree::new());
}
#[test]
fn is_empty() {
let mut tree1: Tree<usize, String> = Tree::new();
assert!(tree1.is_empty());
tree1.i("/", 0);
assert!(!tree1.is_empty());
tree1.clear();
assert!(tree1.is_empty());
tree1.ix("/a", 1);
assert!(!tree1.is_empty());
}
#[test]
fn len() {
let mut tree1: Tree<usize, String> = Tree::new();
assert_eq!(tree1.len(), 0);
tree1.i("/", 1);
assert_eq!(tree1.len(), 1);
tree1.i("/a", 5);
assert_eq!(tree1.len(), 2);
tree1.i("/", 3);
assert_eq!(tree1.len(), 2);
tree1.i("/a/c", 6);
assert_eq!(tree1.len(), 3);
tree1.i("/a/c/d", 4);
assert_eq!(tree1.len(), 4);
tree1.i("/b", 8);
assert_eq!(tree1.len(), 5);
tree1.i("/b/e", 9);
assert_eq!(tree1.len(), 6);
tree1.remove_subtree(&"/a".into()).unwrap();
assert_eq!(tree1.len(), 3);
tree1.ix("/a/c", 1);
assert_eq!(tree1.len(), 5);
tree1.insert_root(10);
assert_eq!(tree1.len(), 5);
tree1.clear();
assert_eq!(tree1.len(), 0);
tree1.insert_root(100);
assert_eq!(tree1.len(), 1);
}
#[test]
fn values() {
let mut tree1 = new_tree();
tree1.i("/z", 2);
let values: HashSet<usize> = HashSet::from_iter([0, 1, 2, 3, 4, 5, 2].into_iter());
let tree_values: HashSet<usize> = HashSet::from_iter(tree1.values().into_iter().cloned());
assert_eq!(tree_values, values);
}
#[test]
fn iter_iter_on() {
let tree1 = new_tree();
let mut iter = tree1.iter_on::<()>();
match iter.next().expect("Root node expected") {
Traversal::Start(()) => (),
_ => panic!("Expected a Root node"),
}
match iter.next().expect("Root child Node expected") {
Traversal::Step {
up,
branch,
data: (),
} => {
assert_eq!(up, 0);
assert!(["a", "c", "f"].contains(&branch.as_str()));
}
_ => panic!("Expected Root child node"),
}
let mut tree2: Tree<Option<usize>, String> = Tree::new();
tree2
.i("/", Some(0))
.i("/a", Some(1))
.i("/a/b", Some(2))
.i("/c", Some(3))
.i("/f", Some(4))
.i("/f/d", Some(5));
let mut entry = tree2.root_entry_mut();
let mut iter = tree1.iter();
if let Traversal::Start(root) = iter.next().unwrap() {
assert_eq!(entry.value().unwrap(), &Some(*root));
entry.insert(None);
} else {
panic!("Expected a Root node")
}
for item in iter {
if let Traversal::Step { up, branch, data } = item {
entry.move_up(up);
entry.move_down_branch(branch.clone());
assert_eq!(
entry
.value()
.expect("Node inexistent")
.expect("Node already visited"),
*data
);
entry.insert(None);
} else {
panic!("Expected a Node")
}
}
assert!(!tree2.iter().any(|item| item.data().is_some()));
}
#[test]
fn get_idx_path_idxs() {
let mut tree1 = new_tree();
let mut map = HashMap::new();
map.insert("/", tree1.get_idx(&"/".into(), None).unwrap());
map.insert("/a", tree1.get_idx(&"/a".into(), None).unwrap());
map.insert("/a/b", tree1.get_idx(&"/a/b".into(), None).unwrap());
map.insert("/c", tree1.get_idx(&"/c".into(), None).unwrap());
map.insert("/f", tree1.get_idx(&"/f".into(), None).unwrap());
map.insert("/f/d", tree1.get_idx(&"/f/d".into(), None).unwrap());
let values: HashSet<usize> = HashSet::from_iter(map.values().copied());
assert_eq!(values.len(), 6);
assert_eq!(tree1.get_idx(&"/b".into(), None), Err(Some((map["/"], 0))));
assert_eq!(tree1.get_idx(&"/w".into(), None), Err(Some((map["/"], 0))));
assert_eq!(
tree1.get_idx(&"/b/a".into(), None),
Err(Some((map["/"], 0)))
);
assert_eq!(
tree1.get_idx(&"/x/y/z".into(), None),
Err(Some((map["/"], 0)))
);
assert_eq!(
tree1.get_idx(&"/a/d".into(), None),
Err(Some((map["/a"], 1)))
);
assert_eq!(
tree1.get_idx(&"/a/b/x".into(), None),
Err(Some((map["/a/b"], 2)))
);
assert_eq!(
Tree::<usize, String>::new().get_idx(&"/a".into(), None),
Err(None)
);
assert_eq!(
tree1.get_path_idxs(&"/a/b".into()),
Ok(vec![map["/"], map["/a"], map["/a/b"]])
);
assert_eq!(
tree1.get_path_idxs(&"/f/d".into()),
Ok(vec![map["/"], map["/f"], map["/f/d"]])
);
assert_eq!(
tree1.get_path_idxs(&"/a/b/w".into()),
Err(Some((vec![map["/"], map["/a"], map["/a/b"]], 2)))
);
assert_eq!(
Tree::<usize, String>::new().get_path_idxs(&"/a/b/w".into()),
Err(None)
);
}
#[test]
fn insert_at() {
let mut tree1 = Tree::new();
assert_eq!(tree1.len(), 0);
tree1.insert_root(0);
assert_eq!(tree1.len(), 1);
let (_, a_idx) = tree1.insert_at(tree1.get_root_idx().unwrap(), "a".to_string(), 1);
assert_eq!(tree1.len(), 2);
tree1.insert_at(a_idx, "b".to_string(), 2);
assert_eq!(tree1.len(), 3);
tree1.insert_at(tree1.get_root_idx().unwrap(), "c".to_string(), 3);
assert_eq!(tree1.len(), 4);
let (_, f_idx) = tree1.insert_at(tree1.get_root_idx().unwrap(), "f".to_string(), 4);
assert_eq!(tree1.len(), 5);
tree1.insert_at(f_idx, "d".to_string(), 5);
assert_eq!(tree1.len(), 6);
assert_eq!(tree1, new_tree());
tree1.insert_at(tree1.get_root_idx().unwrap(), "a".to_string(), 1);
assert_eq!(tree1.len(), 6);
assert_eq!(tree1, new_tree());
}
#[test]
#[should_panic]
fn insert_at_panic_parent() {
new_tree().insert_at(7, "P".to_string(), 2);
}
#[test]
fn remove_subtree_at() {
let mut tree1 = new_tree();
tree1.remove_subtree_at(tree1.get_root_idx().unwrap(), "a".to_string());
assert_eq!(tree1.len(), 4);
tree1.remove_subtree_at(tree1.get_root_idx().unwrap(), "c".to_string());
assert_eq!(tree1.len(), 3);
tree1.remove_subtree_at(tree1.get_idx(&"/f".into(), None).unwrap(), "d".to_string());
assert_eq!(tree1.len(), 2);
tree1.remove_subtree_at(tree1.get_root_idx().unwrap(), "f".to_string());
assert_eq!(tree1.len(), 1);
}
#[test]
fn get() {
let mut tree1: Tree<usize, String> = Tree::new();
assert_eq!(tree1.get(&"/a/b/w".into()), Err(None));
tree1 = new_tree();
assert_eq!(tree1.get(&"/a".into()), Ok(&1));
assert_eq!(tree1.get(&"/a/b".into()), Ok(&2));
assert_eq!(tree1.get(&"/a/b/w".into()), Err(Some("/a/b".into())));
assert_eq!(tree1.get(&"/b/a".into()), Err(Some("/".into())));
}
#[test]
fn get_mut() {
let mut tree1: Tree<usize, String> = Tree::new();
assert_eq!(tree1.get_mut(&"/a/b/w".into()), Err(None));
tree1 = new_tree();
assert_eq!(tree1.get_mut(&"/a".into()), Ok(&mut 1));
assert_eq!(tree1.get_mut(&"/a/b".into()), Ok(&mut 2));
assert_eq!(tree1.get_mut(&"/a/b/w".into()), Err(Some("/a/b".into())));
assert_eq!(tree1.get_mut(&"/b/a".into()), Err(Some("/".into())));
}
#[test]
fn root_entry() {
let mut tree1: Tree<usize, String> = Tree::new();
let entry = tree1.root_entry();
assert!(!entry.is_node());
tree1.i("/", 7).i("/c1", 1);
let mut entry = tree1.root_entry();
assert_eq!(entry.value(), Some(&7));
entry.move_down_branch("c1".into());
assert_eq!(entry.value(), Some(&1));
tree1.clear();
let entry = tree1.root_entry();
assert!(!entry.is_node());
}
#[test]
fn root_entry_mut() {
let mut tree1: Tree<usize, String> = Tree::new();
let mut entry = tree1.root_entry_mut();
assert!(!entry.is_node());
assert_eq!(entry.or_insert(5), &mut 5);
entry.move_down_branch("c1".into());
assert_eq!(entry.or_insert(1), &mut 1);
entry.move_up(1);
assert!(entry.is_node());
}
#[test]
fn entry() {
let mut tree1: Tree<usize, String> = Tree::new();
tree1.i("/", 0).i("/a", 1).i("/a/b", 2).i("/c", 3);
let mut entry = tree1.entry(&"/a/b".into());
assert_eq!(entry.value(), Some(&2));
entry.move_up(1);
assert_eq!(entry.value(), Some(&1));
entry.move_up(1);
assert_eq!(entry.value(), Some(&0));
}
#[test]
fn entry_mut() {
let mut tree1: Tree<usize, String> = Tree::new();
tree1.i("/", 0).i("/a", 1).i("/a/b", 2).i("/c", 3);
let mut entry = tree1.entry_mut(&"/a/b".into());
assert_eq!(entry.or_insert(4), &mut 2);
entry.move_up(2);
entry.move_down_branch("f".into());
assert_eq!(entry.or_insert(4), &mut 4);
entry.move_down_branch("e".into());
assert_eq!(entry.or_insert(5), &mut 5);
assert_eq!(tree1, new_tree());
}
#[test]
fn insert() {
let mut tree1: Tree<_, String> = Tree::new();
assert_eq!(tree1.insert(&"/".into(), 0), Ok(None));
assert_eq!(tree1.insert(&"/a".into(), 2), Ok(None));
assert_eq!(tree1.insert(&"/a".into(), 1), Ok(Some(2)));
assert_eq!(tree1.insert(&"/a/b/c".into(), 2), Err(Some("/a".into())));
assert_eq!(tree1.insert(&"/a/b".into(), 2), Ok(None));
assert_eq!(tree1.insert(&"/c".into(), 3), Ok(None));
assert_eq!(tree1.insert(&"/f".into(), 4), Ok(None));
assert_eq!(tree1.insert(&"/f/e".into(), 5), Ok(None));
assert_eq!(tree1, new_tree());
tree1.clear();
assert_eq!(tree1.len(), 0);
assert_eq!(tree1.insert(&"/a/b/c".into(), 2), Err(None));
assert_eq!(tree1.insert(&"/".into(), 7), Ok(None));
assert_eq!(tree1.len(), 1);
assert_eq!(tree1[&"/".into()], 7);
}
#[test]
fn remove_subtree() {
let mut tree1: Tree<usize, String> = Tree::new();
tree1.insert(&"/".into(), 0).unwrap();
tree1.insert(&"/a".into(), 1).unwrap();
tree1.insert(&"/a".into(), 2).unwrap();
tree1.insert(&"/b".into(), 3).unwrap();
let mut tree2 = tree1.clone();
tree2.insert(&"/c".into(), 4).unwrap();
tree2.insert(&"/c/d".into(), 5).unwrap();
tree2.remove_subtree(&"/c".into()).unwrap();
assert_eq!(tree1, tree2);
}
#[test]
fn force_apply() {
let mut tree1 = new_tree();
let mut diff = Tree::new();
let mut tree_res = Tree::new();
diff.i("/", (Some(0), Some(9)))
.i("/a", (None, None))
.i("/a/b", (Some(2), Some(8)))
.i("/f", (Some(4), None))
.i("/f/g", (Some(1000), Some(14))) .i("/c", (None, Some(12))) .i("/c/e", (None, Some(11)));
assert!(!tree1.force_apply(diff.clone()));
tree_res
.i("/", 9)
.i("/a", 1)
.i("/a/b", 8)
.i("/c", 12)
.i("/c/e", 11);
assert_eq!(tree1, tree_res, "Both trees are not equal");
}
#[test]
fn combine() {}
#[test]
fn i() {}
#[test]
fn is_subtree_eq() {}
#[test]
fn apply() {
let mut tree1 = new_tree();
let mut tree_diff = DiffTree::new();
tree_diff
.i("/", (None, None))
.i("/a", (Some(1), None))
.i("/c", (Some(3), Some(10)))
.i("/c/f", (None, Some(11)))
.i("/c/f/g", (None, Some(12)));
let mut tree_res: Tree<usize, String> = Tree::new();
tree_res
.i("/", 0)
.i("/c", 10)
.i("/c/f", 11)
.i("/c/f/g", 12)
.i("/f", 4)
.i("/f/d", 5);
tree1.apply(tree_diff).unwrap();
assert_eq!(tree1, tree_res, "Both trees are not equal");
}
#[test]
fn apply_diff() {}
#[test]
fn apply_diff_with() {}
#[test]
fn apply_map() {}
}