use crate::store::NodeStore;
use super::cursor::TreeError;
use super::mutate::batch_mutate_owned;
use super::node::{Hash, LeafNode, Node};
use super::policy::TreePolicy;
pub fn stream_and_rebuild<S: NodeStore + ?Sized>(
store: &mut S,
source_root: Hash,
policy: TreePolicy,
) -> Result<Hash, TreeError> {
let mut entries = Vec::new();
collect_leaf_entries(store, source_root, &mut entries)?;
let empty = store
.put(&Node::Leaf(LeafNode::new(Vec::new())?))
.map_err(|_| TreeError::InvalidNode)?;
if entries.is_empty() {
return Ok(empty);
}
let batch: Vec<(Vec<u8>, Option<Vec<u8>>)> = entries
.into_iter()
.map(|(key, value)| (key, Some(value)))
.collect();
batch_mutate_owned(store, empty, batch, policy)
}
fn collect_leaf_entries<S: NodeStore + ?Sized>(
store: &S,
root: Hash,
out: &mut Vec<(Vec<u8>, Vec<u8>)>,
) -> Result<(), TreeError> {
let mut stack = vec![root];
while let Some(hash) = stack.pop() {
let node = store
.get(&hash)
.map_err(|_| TreeError::InvalidNode)?
.ok_or(TreeError::MissingNode { hash })?;
match &*node {
Node::Leaf(leaf) => {
for (key, value) in leaf.entries() {
out.push((key.clone(), value.clone()));
}
}
Node::Internal(internal) => {
for (_separator, child) in internal.children() {
stack.push(*child);
}
}
}
}
Ok(())
}