1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// 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);
        })
    }
}