blob: 7a6e16f50221d416d89a38505a360577f44cce37 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! `fuchsia_merkle` contains types and methods for building and working with merkle trees.
#![deny(missing_docs)]
use {
futures::{AsyncRead, AsyncReadExt as _},
std::io::{self, Read},
};
pub use fuchsia_hash::{Hash, HASH_SIZE};
/// The size of a single block of data (or hashes), in bytes.
pub const BLOCK_SIZE: usize = 8192;
mod util;
pub use crate::util::{crypto_library_init, hash_block};
mod tree;
pub use crate::tree::MerkleTree;
mod builder;
pub use crate::builder::MerkleTreeBuilder;
mod writer;
pub use crate::writer::MerkleTreeWriter;
/// Compute a merkle tree from a `&[u8]`.
pub fn from_slice(slice: &[u8]) -> MerkleTree {
let mut builder = MerkleTreeBuilder::new();
builder.write(slice);
builder.finish()
}
/// Compute a merkle tree from a `std::io::Read`.
pub fn from_read<R>(reader: &mut R) -> Result<MerkleTree, io::Error>
where
R: Read,
{
MerkleTree::from_reader(reader)
}
/// Compute a merkle tree from a `futures::io::AsyncRead`.
pub async fn from_async_read<R>(reader: &mut R) -> Result<MerkleTree, io::Error>
where
R: AsyncRead + Unpin,
{
let mut buf = [0; BLOCK_SIZE];
let mut builder = MerkleTreeBuilder::new();
loop {
let len = reader.read(&mut buf).await?;
if len == 0 {
break;
}
builder.write(&buf[0..len]);
}
Ok(builder.finish())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_slice() {
let file = b"hello world";
let mut builder = MerkleTreeBuilder::new();
builder.write(&file[..]);
let expected = builder.finish();
let actual = from_slice(&file[..]);
assert_eq!(expected, actual);
}
#[test]
fn test_from_read() {
let file = b"hello world";
let mut builder = MerkleTreeBuilder::new();
builder.write(&file[..]);
let expected = builder.finish();
let actual = from_read(&mut &file[..]).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_from_async_read() {
futures::executor::block_on(async {
let file = b"hello world";
let mut builder = MerkleTreeBuilder::new();
builder.write(&file[..]);
let expected = builder.finish();
let actual = from_async_read(&mut &file[..]).await.unwrap();
assert_eq!(expected, actual);
})
}
}