use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, convert::TryFrom, fmt::Debug};
use thiserror::Error;
use crate::{
binary_tree::{array_representation::treemath::sibling, LeafIndex, TreeSize},
error::LibraryError,
};
use super::{
tree::{to_node_index, ABinaryTree, ABinaryTreeError, NodeIndex},
treemath::{direct_path, left, lowest_common_ancestor, parent, right, root, TreeMathError},
};
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct StagedAbDiff<T: Clone + Debug> {
diff: BTreeMap<NodeIndex, T>,
size: TreeSize,
}
impl<'a, T: Clone + Debug> From<AbDiff<'a, T>> for StagedAbDiff<T> {
fn from(diff: AbDiff<'a, T>) -> Self {
StagedAbDiff {
diff: diff.diff,
size: diff.size,
}
}
}
impl<T: Clone + Debug> StagedAbDiff<T> {
pub(super) fn diff(self) -> BTreeMap<NodeIndex, T> {
self.diff
}
pub(super) fn tree_size(&self) -> TreeSize {
self.size
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) struct NodeId {
node_index: NodeIndex,
}
impl NodeId {
pub(super) fn try_from_node_index<T: Clone + Debug>(
diff: &AbDiff<T>,
node_index: NodeIndex,
) -> Result<Self, OutOfBoundsError> {
diff.out_of_bounds(node_index)?;
Ok(NodeId { node_index })
}
pub(crate) fn node_index(&self) -> LeafIndex {
self.node_index
}
}
pub(crate) struct AbDiff<'a, T: Clone + Debug> {
original_tree: &'a ABinaryTree<T>,
diff: BTreeMap<NodeIndex, T>,
size: TreeSize,
}
impl<'a, T: Clone + Debug> TryFrom<&'a ABinaryTree<T>> for AbDiff<'a, T> {
type Error = ABinaryTreeDiffError;
fn try_from(tree: &'a ABinaryTree<T>) -> Result<AbDiff<'a, T>, ABinaryTreeDiffError> {
Ok(AbDiff {
original_tree: tree,
diff: BTreeMap::new(),
size: tree.size()?,
})
}
}
impl<'a, T: Clone + Debug> AbDiff<'a, T> {
pub(crate) fn add_leaf(
&mut self,
parent_node: T,
new_leaf: T,
) -> Result<LeafIndex, ABinaryTreeDiffError> {
if self.tree_size() >= NodeIndex::MAX - 1 {
return Err(ABinaryTreeDiffError::TreeTooLarge);
}
let original_size = self.tree_size();
let previous_parent = self.diff.insert(original_size, parent_node);
debug_assert!(previous_parent.is_none());
let previous_leaf = self.diff.insert(original_size + 1, new_leaf);
debug_assert!(previous_leaf.is_none());
self.size += 2;
Ok(self.leaf_count() - 1)
}
pub(crate) fn remove_leaf(&mut self) -> Result<(), ABinaryTreeDiffError> {
self.remove_node()?;
self.remove_node()
}
pub(crate) fn replace_leaf(
&mut self,
leaf_index: LeafIndex,
new_leaf: T,
) -> Result<(), ABinaryTreeDiffError> {
let node_index = to_node_index(leaf_index);
self.replace_node(node_index, new_leaf)
}
pub(crate) fn leaf(&self, leaf_index: LeafIndex) -> Result<NodeId, ABinaryTreeDiffError> {
let node_index = to_node_index(leaf_index);
Ok(NodeId::try_from_node_index(self, node_index)?)
}
pub(crate) fn leaves(&self) -> Result<Vec<NodeId>, LibraryError> {
let mut leaf_references = Vec::new();
for leaf_index in 0..self.leaf_count() {
let node_index = to_node_index(leaf_index);
let node_ref = NodeId::try_from_node_index(self, node_index)
.map_err(|_| LibraryError::custom("Expected a valid node reference"))?;
leaf_references.push(node_ref);
}
Ok(leaf_references)
}
pub(crate) fn direct_path(
&self,
leaf_index: LeafIndex,
) -> Result<Vec<NodeId>, OutOfBoundsError> {
let node_index = to_node_index(leaf_index);
let direct_path_indices = direct_path(node_index, self.tree_size())
.map_err(|_| OutOfBoundsError::IndexOutOfBounds)?;
let mut direct_path = Vec::new();
for node_index in direct_path_indices {
let node_ref = NodeId::try_from_node_index(self, node_index)
.map_err(|_| OutOfBoundsError::IndexOutOfBounds)?;
direct_path.push(node_ref);
}
Ok(direct_path)
}
pub(crate) fn set_direct_path_to_node(
&mut self,
leaf_index: LeafIndex,
node: &T,
) -> Result<(), ABinaryTreeDiffError> {
let node_index = to_node_index(leaf_index);
let direct_path = direct_path(node_index, self.tree_size())?;
for node_index in &direct_path {
self.replace_node(*node_index, node.clone())?;
}
Ok(())
}
pub(crate) fn set_direct_path(
&mut self,
leaf_index: LeafIndex,
path: Vec<T>,
) -> Result<(), ABinaryTreeDiffError> {
let node_index = to_node_index(leaf_index);
let direct_path = direct_path(node_index, self.tree_size())?;
if path.len() != direct_path.len() {
return Err(ABinaryTreeDiffError::PathLengthMismatch);
}
for (node_index, node) in direct_path.iter().zip(path.into_iter()) {
self.replace_node(*node_index, node)?;
}
Ok(())
}
pub(crate) fn subtree_root_position(
&self,
leaf_index_1: LeafIndex,
leaf_index_2: LeafIndex,
) -> Result<usize, ABinaryTreeDiffError> {
self.leaf_pair_check(leaf_index_1, leaf_index_2)?;
let subtree_root_node_index =
lowest_common_ancestor(to_node_index(leaf_index_1), to_node_index(leaf_index_2));
let leaf_index_1_direct_path = direct_path(to_node_index(leaf_index_1), self.tree_size())?;
leaf_index_1_direct_path
.iter()
.position(|&direct_path_node_index| direct_path_node_index == subtree_root_node_index)
.ok_or_else(|| LibraryError::custom("index should be in the direct path").into())
}
pub(crate) fn subtree_root_copath_node(
&self,
leaf_index_1: LeafIndex,
leaf_index_2: LeafIndex,
) -> Result<NodeId, ABinaryTreeDiffError> {
self.leaf_pair_check(leaf_index_1, leaf_index_2)?;
let subtree_root_node_index =
lowest_common_ancestor(to_node_index(leaf_index_1), to_node_index(leaf_index_2));
let copath_node_index = if leaf_index_2 < leaf_index_1 {
left(subtree_root_node_index)?
} else {
right(subtree_root_node_index, self.tree_size())?
};
Ok(NodeId::try_from_node_index(self, copath_node_index)?)
}
pub(crate) fn subtree_path(
&self,
leaf_index_1: LeafIndex,
leaf_index_2: LeafIndex,
) -> Result<Vec<NodeId>, ABinaryTreeDiffError> {
let node_index_1 = to_node_index(leaf_index_1);
let node_index_2 = to_node_index(leaf_index_2);
self.out_of_bounds(node_index_1)?;
self.out_of_bounds(node_index_2)?;
let lca = lowest_common_ancestor(node_index_1, node_index_2);
let direct_path_indices = direct_path(lca, self.tree_size())?;
let mut full_path = vec![NodeId::try_from_node_index(self, lca)?];
for node_index in direct_path_indices {
let node_ref = NodeId::try_from_node_index(self, node_index)?;
full_path.push(node_ref);
}
Ok(full_path)
}
pub(crate) fn iter(&'a self) -> DiffIterator<'a, T> {
DiffIterator {
diff: self,
current_index: 0u32,
}
}
pub(crate) fn export_nodes(&self) -> Result<Vec<T>, LibraryError> {
let mut nodes = Vec::new();
for node_index in 0..self.tree_size() {
let node = self
.node_by_index(node_index)
.map_err(|_| LibraryError::custom("Expected node to be in the tree"))?;
nodes.push(node.clone());
}
Ok(nodes)
}
pub(in crate::binary_tree) fn tree_size(&self) -> NodeIndex {
self.size
}
pub(crate) fn leaf_count(&self) -> LeafIndex {
((self.tree_size() - 1) / 2) + 1
}
pub(crate) fn node(&self, node_ref: NodeId) -> Result<&T, ABinaryTreeDiffError> {
self.node_by_index(node_ref.node_index)
}
pub(crate) fn node_mut(&mut self, node_ref: NodeId) -> Result<&mut T, ABinaryTreeDiffError> {
self.node_mut_by_index(node_ref.node_index)
}
pub(crate) fn root(&self) -> NodeId {
let root_index = root(self.tree_size());
NodeId {
node_index: root_index,
}
}
pub(crate) fn is_leaf(&self, node_ref: NodeId) -> bool {
node_ref.node_index % 2 == 0
}
pub(crate) fn parent(&self, node_ref: NodeId) -> Result<NodeId, ABinaryTreeDiffError> {
let parent_index = parent(node_ref.node_index, self.tree_size())?;
Ok(NodeId::try_from_node_index(self, parent_index)?)
}
pub(crate) fn sibling(&self, node_ref: NodeId) -> Result<NodeId, ABinaryTreeDiffError> {
let sibling_index = sibling(node_ref.node_index, self.tree_size())?;
Ok(NodeId::try_from_node_index(self, sibling_index)?)
}
pub(crate) fn left_child(&self, node_ref: NodeId) -> Result<NodeId, ABinaryTreeDiffError> {
let left_child_index = left(node_ref.node_index)?;
Ok(NodeId::try_from_node_index(self, left_child_index)?)
}
pub(crate) fn right_child(&self, node_ref: NodeId) -> Result<NodeId, ABinaryTreeDiffError> {
let right_child_index = right(node_ref.node_index, self.tree_size())?;
Ok(NodeId::try_from_node_index(self, right_child_index)?)
}
pub(crate) fn leaf_index(&self, node_ref: NodeId) -> Option<LeafIndex> {
if self.is_leaf(node_ref) {
Some(node_ref.node_index / 2)
} else {
None
}
}
fn node_by_index(&self, node_index: NodeIndex) -> Result<&T, ABinaryTreeDiffError> {
self.out_of_bounds(node_index)?;
if let Some(node) = self.diff.get(&node_index) {
return Ok(node);
}
Ok(self.original_tree.node_by_index(node_index)?)
}
fn node_mut_by_index(&mut self, node_index: NodeIndex) -> Result<&mut T, ABinaryTreeDiffError> {
self.out_of_bounds(node_index)?;
if self.diff.contains_key(&node_index) {
return self
.diff
.get_mut(&node_index)
.ok_or_else(|| LibraryError::custom("index should exist").into());
}
let tree_node = self.original_tree.node_by_index(node_index)?;
self.replace_node(node_index, tree_node.clone())?;
self.diff
.get_mut(&node_index)
.ok_or_else(|| LibraryError::custom("node should exist").into())
}
fn replace_node(&mut self, node_index: NodeIndex, node: T) -> Result<(), ABinaryTreeDiffError> {
self.out_of_bounds(node_index)?;
self.diff.insert(node_index, node);
Ok(())
}
fn remove_node(&mut self) -> Result<(), ABinaryTreeDiffError> {
if self.tree_size() <= 1 {
return Err(ABinaryTreeDiffError::TreeTooSmall);
}
let removed = self.diff.remove(&(self.tree_size() - 1));
if self.tree_size() > self.original_tree.size()? {
debug_assert!(removed.is_some());
}
self.size -= 1;
Ok(())
}
fn out_of_bounds(&self, node_index: NodeIndex) -> Result<(), OutOfBoundsError> {
if node_index >= self.tree_size() {
return Err(OutOfBoundsError::IndexOutOfBounds);
}
Ok(())
}
fn leaf_pair_check(
&self,
leaf_index_1: LeafIndex,
leaf_index_2: LeafIndex,
) -> Result<(), ABinaryTreeDiffError> {
if leaf_index_1 == leaf_index_2 {
return Err(ABinaryTreeDiffError::SameLeafError);
}
let node_index_1 = to_node_index(leaf_index_1);
let node_index_2 = to_node_index(leaf_index_2);
self.out_of_bounds(node_index_1)?;
self.out_of_bounds(node_index_2)?;
Ok(())
}
#[cfg(test)]
pub(crate) fn deref_vec(
&self,
node_ref_vec: Vec<NodeId>,
) -> Result<Vec<&T>, ABinaryTreeDiffError> {
let mut node_vec = Vec::new();
for node_ref in node_ref_vec {
let node = self.node(node_ref)?;
node_vec.push(node);
}
Ok(node_vec)
}
}
pub(crate) struct DiffIterator<'a, T: Clone + Debug> {
diff: &'a AbDiff<'a, T>,
current_index: NodeIndex,
}
impl<'a, T: Clone + Debug> Iterator for DiffIterator<'a, T> {
type Item = NodeId;
fn next(&mut self) -> Option<Self::Item> {
if self.diff.node_by_index(self.current_index).is_ok() {
let node_ref_option = Some(NodeId {
node_index: self.current_index,
});
self.current_index += 1;
node_ref_option
} else {
None
}
}
}
#[derive(Error, Debug, PartialEq, Clone)]
pub(crate) enum ABinaryTreeDiffError {
#[error(transparent)]
LibraryError(#[from] LibraryError),
#[error("Can't compute the copath node of the subtree root of a single leaf.")]
SameLeafError,
#[error("Maximum tree size reached.")]
TreeTooLarge,
#[error("Minimum tree size reached.")]
TreeTooSmall,
#[error("The given path index is not the same length as the direct path.")]
PathLengthMismatch,
#[error("Error while executing folding function.")]
FoldingError,
#[error(transparent)]
ABinaryTreeError(#[from] ABinaryTreeError),
#[error(transparent)]
TreeError(#[from] TreeMathError),
#[error(transparent)]
IndexOutOfBounds(#[from] OutOfBoundsError),
}
#[derive(Error, Debug, PartialEq, Clone)]
pub(crate) enum OutOfBoundsError {
#[error(transparent)]
LibraryError(#[from] LibraryError),
#[error("The given index is not within the bounds of the tree.")]
IndexOutOfBounds,
}