Skip to content

Commit

Permalink
Added a builder pattern and added ability for sha256 hashing
Browse files Browse the repository at this point in the history
  • Loading branch information
hristogochev committed Jan 31, 2023
1 parent 98717e3 commit c3198ca
Show file tree
Hide file tree
Showing 18 changed files with 277 additions and 179 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "merkle_hash"
version = "3.0.2"
version = "3.1.0"
edition = "2021"
authors = ["hristogochev"]
description = "Finds the hashes of all files and directories in a directory tree."
Expand All @@ -19,4 +19,4 @@ rayon = "1"
blake3 = "1"
anyhow = "1"
camino = "1"

sha2 = { version = "0.10" ,default-features=false}
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,61 @@ To use this crate, add `merkle_hash` as a dependency to your project's `Cargo.to

```toml
[dependencies]
merkle_hash = "3"
merkle_hash = "3.1"
```

### Features

* Finds the master hash of a directory tree with ease.
* Offers [Blake3](https://crates.io/crates/blake3) and [SHA-256](https://crates.io/crates/sha2) as hashing algorithms.
* Offers ability to include names in the hashing process.
* Uses a merkle tree algorithm to compute the hashes of directories.
* External iteration over the paths and hashes of each file and directory.
* Ability to specify whether names should be included in the hashes of files and directories.
* Allows for external iteration over the paths and hashes of files and directories.


### Examples

Get the master hash of a directory tree:

```rust,no_run
use merkle_hash::MerkleTree;
use merkle_hash::{MerkleTree,Algorithm};
let tree = MerkleTree::new("/path/to/directory", true).unwrap();
let tree = MerkleTree::builder("/path/to/directory")
.algorithm(Algorithm::Blake3)
.hash_names(false)
.build()?;
let master_hash = tree.main_node.item.hash;
```

Iterate over a directory tree, getting the hash of each file and directory:

```rust,no_run
use merkle_hash::MerkleTree;
use merkle_hash::{MerkleTree,bytes_to_hex};
let tree = MerkleTree::new("/path/to/directory", true).unwrap();
let tree = MerkleTree::builder("/path/to/directory").build()?;
for item in tree {
println!("{}: {}", item.path.relative, item.hash);
println!("{}: {}", item.path.relative, bytes_to_hex(&item.hash));
}
```

Collapse the tree into any linear collection:

```rust,no_run
use std::collections::BTreeSet;
use merkle_hash::MerkleTree;
use merkle_hash::MerkleItem;
use merkle_hash::{MerkleTree,MerkleItem};
let tree = MerkleTree::new("/path/to/directory", true).unwrap();
let tree = MerkleTree::builder("/path/to/directory").build()?;
let btree_set: BTreeSet<MerkleItem> = tree.into_iter().collect();
```


### Used technologies

* [rayon](https://crates.io/crates/rayon) for multithreaded directory reading and hashing.
* [blake3](https://crates.io/crates/blake3) for the hashing of file contents.
* [camino](https://crates.io/crates/camino) to ensure that paths are always utf-8.
* [anyhow](https://crates.io/crates/anyhow) to ease-out the handling of errors.
* [blake3](https://crates.io/crates/blake3) for the blake3 hashing of file contents.
* [sha2](https://crates.io/crates/sha2) for the sha256 hashing of file contents.

### License

Expand Down
7 changes: 3 additions & 4 deletions src/merkle_item.rs → src/components/merkle_item.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
use crate::merkle_path::MerklePath;
use blake3::Hash;
use crate::components::merkle_path::MerklePath;
use std::cmp::Ordering;

/// Holds the path, hash and children paths of a file or directory
#[derive(Eq, PartialEq, Clone, Debug, Hash)]
pub struct MerkleItem {
pub path: MerklePath,
pub hash: Hash,
pub hash: [u8; 32],
pub children_paths: Vec<MerklePath>,
}

impl MerkleItem {
pub fn new(path: MerklePath, hash: Hash, children_paths: Vec<MerklePath>) -> Self {
pub fn new(path: MerklePath, hash: [u8; 32], children_paths: Vec<MerklePath>) -> Self {
Self {
path,
hash,
Expand Down
2 changes: 1 addition & 1 deletion src/merkle_path.rs → src/components/merkle_path.rs
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use camino::Utf8PathBuf;
use std::cmp::Ordering;

/// An utility struct containing an absolute path and a relative path
/// An utility struct that contains an absolute path and a relative path
#[derive(Eq, PartialEq, Clone, Debug, Hash)]
pub struct MerklePath {
pub relative: Utf8PathBuf,
Expand Down
2 changes: 2 additions & 0 deletions src/components/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod merkle_item;
pub mod merkle_path;
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::merkle_item::MerkleItem;
use crate::merkle_node::MerkleNode;
use std::collections::btree_set::IntoIter;

use crate::components::merkle_item::MerkleItem;
use crate::tree::merkle_node::MerkleNode;

/// Owned node iterator
#[derive(Default)]
pub struct MerkleNodeIntoIter {
value: Option<MerkleItem>,
Expand Down
6 changes: 4 additions & 2 deletions src/merkle_node_iter.rs → src/iters/merkle_node_iter.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::merkle_item::MerkleItem;
use crate::merkle_node::MerkleNode;
use std::collections::btree_set::Iter;
use std::iter::FusedIterator;

use crate::components::merkle_item::MerkleItem;
use crate::tree::merkle_node::MerkleNode;

/// Node iterator
#[derive(Default)]
pub struct MerkleNodeIter<'a> {
value: Option<&'a MerkleItem>,
Expand Down
2 changes: 2 additions & 0 deletions src/iters/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod merkle_node_into_iter;
pub mod merkle_node_iter;
64 changes: 31 additions & 33 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,69 +1,67 @@
/*!
Crate `merkle_hash` makes it easy to find the hashes of all files and directories in a directory tree.
# Features
* Finds the master hash of a directory tree with ease.
* External iteration over the paths and hashes of each file and directory.
* Ability to specify whether names should be included in the hashes of files and directories.
# Usage
To use this crate, add `merkle_hash` as a dependency to your project's `Cargo.toml`:
```toml
[dependencies]
merkle_hash = "3"
merkle_hash = "3.1"
```
# Features
* Finds the master hash of a directory tree with ease.
* Offers Blake3 and Sha256 as hashing algorithms.
* External iteration over the paths and hashes of each file and directory.
* Ability to specify whether names should be included in the hashes of files and directories.
# Example: Get the master hash of a directory tree:
```
use merkle_hash::MerkleTree;
use merkle_hash::{MerkleTree,Algorithm};
let tree = MerkleTree::new("/path/to/directory", true).unwrap();
let tree = MerkleTree::builder("/path/to/directory")
.algorithm(Algorithm::Blake3)
.hash_names(false)
.build()?;
let master_hash = tree.main_node.item.hash;
```
# Example: Iterate over a directory tree, getting the hash of each file and directory:
```
use merkle_hash::MerkleTree;
use merkle_hash::{MerkleTree,bytes_to_hex};
let tree = MerkleTree::new("/path/to/directory", true).unwrap();
let tree = MerkleTree::builder("/path/to/directory").build()?;
for item in tree {
println!("{}: {}", item.path.relative, item.hash);
println!("{}: {}", item.path.relative, bytes_to_hex(&item.hash));
}
```
# Example: Collapse the tree into any linear collection:
```
use std::collections::BTreeSet;
use merkle_hash::MerkleTree;
use merkle_hash::MerkleItem;
use merkle_hash::{MerkleTree,MerkleItem};
let tree = MerkleTree::new("/path/to/directory", true).unwrap();
let tree = MerkleTree::builder("/path/to/directory").build()?;
let btree_set: BTreeSet<MerkleItem> = tree.into_iter().collect();
```
*/

/// Holds the path, hash and children paths of a file or directory
pub mod merkle_item;
/// Represents a single node on the merkle tree
pub mod merkle_node;
/// Owned node iterator
pub mod merkle_node_into_iter;
/// Node iterator
pub mod merkle_node_iter;
/// Utility that represents relative and absolute paths
pub mod merkle_path;
/// The main tree with merkle hashes
pub mod merkle_tree;
/// Merkle hashing utility functions
pub mod merkle_utils;
mod components;
mod iters;
mod tree;
mod utils;

/// Merkle item reexport
pub use merkle_item::MerkleItem;
/// Merkle tree reexport
pub use merkle_tree::MerkleTree;
pub use components::merkle_item::MerkleItem;
pub use components::merkle_path::MerklePath;
pub use iters::merkle_node_into_iter::MerkleNodeIntoIter;
pub use iters::merkle_node_iter::MerkleNodeIter;
pub use tree::merkle_node::MerkleNode;
pub use tree::merkle_tree::MerkleTree;
pub use tree::merkle_tree_builder::MerkleTreeBuilder;
pub use utils::algorithm::Algorithm;
pub use utils::hex_encoding::bytes_to_hex;

/// Used dependencies reexport
pub use anyhow;
Expand Down
45 changes: 0 additions & 45 deletions src/merkle_tree.rs

This file was deleted.

36 changes: 0 additions & 36 deletions src/merkle_utils.rs

This file was deleted.

Loading

0 comments on commit c3198ca

Please sign in to comment.