pub extern crate rayon;
use self::rayon::prelude::*;
use super::plumbing::FromNodes;
use hash::Hasher;
use leaf;
use tree;
use tree::{BuildResult, EmptyTree, MerkleTree};
#[derive(Clone, Debug, Default)]
pub struct Builder<D, L>
where
D: Hasher<L::Input>,
L: leaf::ExtractData,
{
inner: tree::Builder<D, L>,
}
impl<D, In> Builder<D, leaf::NoData<In>>
where
D: Hasher<In> + Default,
{
pub fn new() -> Self {
Builder {
inner: tree::Builder::new(),
}
}
}
impl<D, L> Builder<D, L>
where
D: Hasher<L::Input>,
L: leaf::ExtractData,
{
pub fn from_hasher_leaf_data(hasher: D, leaf_data_extractor: L) -> Self {
let inner =
tree::Builder::from_hasher_leaf_data(hasher, leaf_data_extractor);
Builder { inner }
}
pub fn make_leaf(
&self,
input: L::Input,
) -> MerkleTree<D::HashOutput, L::LeafData> {
self.inner.make_leaf(input)
}
pub fn chain_lone_child(
&self,
child: MerkleTree<D::HashOutput, L::LeafData>,
) -> MerkleTree<D::HashOutput, L::LeafData> {
self.inner.chain_lone_child(child)
}
}
impl<D, L> Builder<D, L>
where
D: Hasher<L::Input> + Clone + Send,
L: leaf::ExtractData + Clone + Send,
D::HashOutput: Send,
L::Input: Send,
L::LeafData: Send,
{
pub fn complete_tree_from<I>(
&self,
iterable: I,
) -> BuildResult<D::HashOutput, L::LeafData>
where
I: IntoParallelIterator<Item = L::Input>,
I::Iter: IndexedParallelIterator,
{
self.complete_tree_from_iter(iterable.into_par_iter())
}
fn complete_tree_from_iter<I>(
&self,
iter: I,
) -> BuildResult<D::HashOutput, L::LeafData>
where
I: IndexedParallelIterator<Item = L::Input>,
{
if iter.len() == 0 {
return Err(EmptyTree);
}
let leaves: Vec<_> = iter
.map_with(self.clone(), |master, input| master.make_leaf(input))
.collect();
assert!(
leaves.len() != 0,
"the parallel iterator that reported nonzero length \
has come up empty"
);
let perfect_len = leaves.len().checked_next_power_of_two().unwrap();
Ok(self.reduce_complete(leaves, perfect_len))
}
fn reduce_complete(
&self,
mut level_nodes: Vec<MerkleTree<D::HashOutput, L::LeafData>>,
perfect_len: usize,
) -> MerkleTree<D::HashOutput, L::LeafData> {
let len = level_nodes.len();
debug_assert!(len != 0);
let left_len = perfect_len / 2;
if len <= left_len {
let subtree = self.reduce_complete(level_nodes, left_len);
self.chain_lone_child(subtree)
} else if len == 1 {
level_nodes.pop().unwrap()
} else {
let right = level_nodes.split_off(left_len);
let left = level_nodes;
let left_builder = self.clone();
let right_builder = self.clone();
self.join(
move || left_builder.reduce_complete(left, left_len),
move || right_builder.reduce_complete(right, left_len),
)
}
}
pub fn full_tree_from<I>(
&self,
iterable: I,
) -> BuildResult<D::HashOutput, L::LeafData>
where
I: IntoParallelIterator<Item = L::Input>,
I::Iter: IndexedParallelIterator,
{
self.full_tree_from_iter(iterable.into_par_iter())
}
fn full_tree_from_iter<I>(
&self,
iter: I,
) -> BuildResult<D::HashOutput, L::LeafData>
where
I: IndexedParallelIterator<Item = L::Input>,
{
if iter.len() == 0 {
return Err(EmptyTree);
}
let leaves: Vec<_> = iter
.map_with(self.clone(), |master, input| master.make_leaf(input))
.collect();
assert!(
leaves.len() != 0,
"the parallel iterator that reported nonzero length \
has come up empty"
);
Ok(self.reduce_full(leaves))
}
fn reduce_full(
&self,
mut level_nodes: Vec<MerkleTree<D::HashOutput, L::LeafData>>,
) -> MerkleTree<D::HashOutput, L::LeafData> {
let len = level_nodes.len();
debug_assert!(len != 0);
let left_len = (len.saturating_add(1) / 2).next_power_of_two();
if len == 1 {
level_nodes.pop().unwrap()
} else {
let right = level_nodes.split_off(left_len);
let left = level_nodes;
let left_builder = self.clone();
let right_builder = self.clone();
self.join(
move || left_builder.reduce_full(left),
move || right_builder.reduce_full(right),
)
}
}
}
impl<D, L> Builder<D, L>
where
D: Hasher<L::Input>,
L: leaf::ExtractData,
D::HashOutput: Send,
L::LeafData: Send,
{
pub fn join<LF, RF>(
&self,
left: LF,
right: RF,
) -> MerkleTree<D::HashOutput, L::LeafData>
where
LF: FnOnce() -> MerkleTree<D::HashOutput, L::LeafData> + Send,
RF: FnOnce() -> MerkleTree<D::HashOutput, L::LeafData> + Send,
{
let (left_tree, right_tree) = rayon::join(left, right);
self.inner.join(left_tree, right_tree)
}
pub fn collect_children_from<I>(
&self,
iterable: I,
) -> BuildResult<D::HashOutput, L::LeafData>
where
I: IntoParallelIterator<Item = MerkleTree<D::HashOutput, L::LeafData>>,
{
self.collect_children_from_iter(iterable.into_par_iter())
}
fn collect_children_from_iter<I>(
&self,
iter: I,
) -> BuildResult<D::HashOutput, L::LeafData>
where
I: ParallelIterator<Item = MerkleTree<D::HashOutput, L::LeafData>>,
{
let nodes: Vec<_> = iter.map(|tree| tree.root).collect();
self.inner.tree_from_nodes(nodes)
}
}
#[cfg(test)]
mod tests {
use super::Builder;
use super::rayon::iter;
use super::rayon::prelude::*;
use super::super::testmocks::MockHasher;
use leaf;
use tree::Node;
const TEST_DATA: &'static [u8] =
b"The quick brown fox jumps over the lazy dog";
#[test]
fn complete_tree_from_empty() {
let builder = Builder::<MockHasher, _>::new();
builder
.complete_tree_from(iter::empty::<[u8; 1]>())
.unwrap_err();
}
#[test]
fn complete_leaf() {
let builder = Builder::<MockHasher, _>::new();
let iter = iter::repeatn(TEST_DATA, 1);
let tree = builder.complete_tree_from(iter).unwrap();
if let Node::Leaf(ref ln) = *tree.root() {
assert_eq!(ln.hash_bytes(), TEST_DATA);
} else {
unreachable!()
}
}
#[test]
fn complete_tree() {
let builder = Builder::<MockHasher, _>::new();
let data: Vec<_> = TEST_DATA.chunks(15).collect();
let tree = builder.complete_tree_from(data).unwrap();
if let Node::Hash(ref hn) = *tree.root() {
let expected: &[u8] = b"#(>The quick brown> fox jumps over)\
#(> the lazy dog)";
assert_eq!(hn.hash_bytes(), expected);
} else {
unreachable!()
}
}
#[test]
fn complete_tree_is_subgraph_of_its_math_definition() {
let builder = Builder::<MockHasher, _>::new();
let data: Vec<_> = TEST_DATA.chunks(10).collect();
let tree = builder.complete_tree_from(data).unwrap();
if let Node::Hash(ref hn) = *tree.root() {
let expected: &[u8] =
b"#(#(>The quick >brown fox )#(>jumps over> the lazy ))\
#(#(>dog))";
assert_eq!(hn.hash_bytes(), expected);
assert_eq!(hn.children.len(), 2);
if let Node::Hash(ref hn) = *hn.child_at(1) {
assert_eq!(hn.hash_bytes(), b"#(>dog)");
assert_eq!(hn.children.len(), 1);
if let Node::Hash(ref hn) = *hn.child_at(0) {
assert_eq!(hn.hash_bytes(), b">dog");
assert_eq!(hn.children.len(), 1);
if let Node::Leaf(ref ln) = *hn.child_at(0) {
assert_eq!(ln.hash_bytes(), b"dog");
} else {
unreachable!()
}
} else {
unreachable!()
}
} else {
unreachable!()
}
} else {
unreachable!()
}
}
#[test]
fn cant_make_full_from_empty() {
use super::rayon::iter::empty;
let builder = Builder::<MockHasher, _>::new();
let err = builder.full_tree_from(empty::<[u8; 1]>()).unwrap_err();
println!("error {:?}: {}", err, err);
}
#[test]
fn full_tree_is_full() {
let builder = Builder::<MockHasher, _>::new();
let data: Vec<_> = TEST_DATA.chunks(7).collect();
let tree = builder.full_tree_from(data).unwrap();
if let Node::Hash(ref hn) = *tree.root() {
let expected: &[u8] = b"#(#(>The qui>ck brow)#(>n fox j>umps ov))\
#(#(>er the >lazy do)>g)";
assert_eq!(hn.hash_bytes(), expected);
} else {
unreachable!()
}
}
const TEST_STRS: [&'static str; 3] =
["Panda eats,", "shoots,", "and leaves."];
#[test]
fn collect_nodes_for_arbitrary_arity_tree() {
let builder = Builder::<MockHasher, leaf::NoData<&'static str>>::new();
let iter = TEST_STRS
.into_par_iter()
.map_with(builder.clone(), |builder, input| {
builder.make_leaf(input)
});
let tree = builder.collect_children_from(iter).unwrap();
if let Node::Hash(ref hn) = *tree.root() {
assert_eq!(hn.hash_bytes(), b">Panda eats,>shoots,>and leaves.");
let mut peek_iter = hn.children().peekable();
assert!(peek_iter.peek().is_some());
for (i, child) in peek_iter.enumerate() {
if let Node::Leaf(ref ln) = *child {
assert_eq!(ln.hash_bytes(), TEST_STRS[i].as_bytes());
} else {
unreachable!()
}
}
} else {
unreachable!()
}
}
}