pub struct HashTree<S: Store> { /* private fields */ }Expand description
HashTree - unified create, read, and edit merkle tree operations
Implementations§
Source§impl<S: Store> HashTree<S>
impl<S: Store> HashTree<S>
pub fn new(config: HashTreeConfig<S>) -> Self
Sourcepub fn is_encrypted(&self) -> bool
pub fn is_encrypted(&self) -> bool
Check if encryption is enabled
Sourcepub async fn put(&self, data: &[u8]) -> Result<(Cid, u64), HashTreeError>
pub async fn put(&self, data: &[u8]) -> Result<(Cid, u64), HashTreeError>
Store content, returns (Cid, size) where Cid is hash + optional key Encrypts by default when encryption feature is enabled
Sourcepub async fn get(&self, cid: &Cid) -> Result<Option<Vec<u8>>, HashTreeError>
pub async fn get(&self, cid: &Cid) -> Result<Option<Vec<u8>>, HashTreeError>
Get content by Cid (handles decryption automatically)
Sourcepub async fn put_stream<R: AsyncRead + Unpin>(
&self,
reader: R,
) -> Result<(Cid, u64), HashTreeError>
pub async fn put_stream<R: AsyncRead + Unpin>( &self, reader: R, ) -> Result<(Cid, u64), HashTreeError>
Store content from an async reader (streaming put)
Reads data in chunks and builds a merkle tree incrementally. Useful for large files or streaming data sources. Returns (Cid, size) where Cid is hash + optional key
Sourcepub fn get_stream(
&self,
cid: &Cid,
) -> Pin<Box<dyn Stream<Item = Result<Vec<u8>, HashTreeError>> + Send + '_>>
pub fn get_stream( &self, cid: &Cid, ) -> Pin<Box<dyn Stream<Item = Result<Vec<u8>, HashTreeError>> + Send + '_>>
Read content as a stream of chunks by Cid (handles decryption automatically)
Returns an async stream that yields chunks as they are read. Useful for large files or when you want to process data incrementally.
Sourcepub async fn put_blob(&self, data: &[u8]) -> Result<Hash, HashTreeError>
pub async fn put_blob(&self, data: &[u8]) -> Result<Hash, HashTreeError>
Store a blob directly (small data, no encryption) Returns the content hash
Sourcepub async fn put_file(&self, data: &[u8]) -> Result<(Cid, u64), HashTreeError>
pub async fn put_file(&self, data: &[u8]) -> Result<(Cid, u64), HashTreeError>
Store a file, chunking if necessary Returns (Cid, size) where Cid is hash + optional key
Sourcepub async fn put_directory(
&self,
entries: Vec<DirEntry>,
) -> Result<Cid, HashTreeError>
pub async fn put_directory( &self, entries: Vec<DirEntry>, ) -> Result<Cid, HashTreeError>
Build a directory from entries Returns Cid with key if encrypted
For large directories, the messagepack-encoded TreeNode is stored via put() which automatically chunks the data. The reader uses read_file() to reassemble.
Sourcepub async fn put_tree_node(
&self,
links: Vec<Link>,
) -> Result<Hash, HashTreeError>
pub async fn put_tree_node( &self, links: Vec<Link>, ) -> Result<Hash, HashTreeError>
Create a tree node with custom links
Sourcepub async fn get_blob(
&self,
hash: &Hash,
) -> Result<Option<Vec<u8>>, HashTreeError>
pub async fn get_blob( &self, hash: &Hash, ) -> Result<Option<Vec<u8>>, HashTreeError>
Get raw data by hash
Sourcepub async fn get_tree_node(
&self,
hash: &Hash,
) -> Result<Option<TreeNode>, HashTreeError>
pub async fn get_tree_node( &self, hash: &Hash, ) -> Result<Option<TreeNode>, HashTreeError>
Get and decode a tree node (unencrypted)
Sourcepub async fn get_node(
&self,
cid: &Cid,
) -> Result<Option<TreeNode>, HashTreeError>
pub async fn get_node( &self, cid: &Cid, ) -> Result<Option<TreeNode>, HashTreeError>
Get and decode a tree node using Cid (with decryption if key present)
Sourcepub async fn get_directory_node(
&self,
cid: &Cid,
) -> Result<Option<TreeNode>, HashTreeError>
pub async fn get_directory_node( &self, cid: &Cid, ) -> Result<Option<TreeNode>, HashTreeError>
Get directory node, handling chunked directory data Use this when you know the target is a directory (from parent link_type)
Sourcepub async fn is_tree(&self, hash: &Hash) -> Result<bool, HashTreeError>
pub async fn is_tree(&self, hash: &Hash) -> Result<bool, HashTreeError>
Check if hash points to a tree node (no decryption)
Sourcepub async fn is_dir(&self, cid: &Cid) -> Result<bool, HashTreeError>
pub async fn is_dir(&self, cid: &Cid) -> Result<bool, HashTreeError>
Check if Cid points to a directory (with decryption)
Sourcepub async fn is_directory(&self, hash: &Hash) -> Result<bool, HashTreeError>
pub async fn is_directory(&self, hash: &Hash) -> Result<bool, HashTreeError>
Check if hash points to a directory (tree with named links, no decryption)
Sourcepub async fn read_file(
&self,
hash: &Hash,
) -> Result<Option<Vec<u8>>, HashTreeError>
pub async fn read_file( &self, hash: &Hash, ) -> Result<Option<Vec<u8>>, HashTreeError>
Read a complete file (reassemble chunks if needed)
Sourcepub async fn read_file_range(
&self,
hash: &Hash,
start: u64,
end: Option<u64>,
) -> Result<Option<Vec<u8>>, HashTreeError>
pub async fn read_file_range( &self, hash: &Hash, start: u64, end: Option<u64>, ) -> Result<Option<Vec<u8>>, HashTreeError>
Read a byte range from a file (fetches only necessary chunks)
start: Starting byte offset (inclusive)end: Ending byte offset (exclusive), or None to read to end
This is more efficient than read_file() for partial reads of large files.
Sourcepub fn read_file_stream(
&self,
hash: Hash,
) -> Pin<Box<dyn Stream<Item = Result<Vec<u8>, HashTreeError>> + Send + '_>>
pub fn read_file_stream( &self, hash: Hash, ) -> Pin<Box<dyn Stream<Item = Result<Vec<u8>, HashTreeError>> + Send + '_>>
Read a file as stream of chunks Returns an async stream that yields chunks as they are read
Sourcepub async fn read_file_chunks(
&self,
hash: &Hash,
) -> Result<Vec<Vec<u8>>, HashTreeError>
pub async fn read_file_chunks( &self, hash: &Hash, ) -> Result<Vec<Vec<u8>>, HashTreeError>
Read file chunks as Vec (non-streaming version)
Sourcepub async fn list(&self, cid: &Cid) -> Result<Vec<TreeEntry>, HashTreeError>
pub async fn list(&self, cid: &Cid) -> Result<Vec<TreeEntry>, HashTreeError>
List directory entries (Cid-based, supports encrypted directories)
Sourcepub async fn list_directory(
&self,
cid: &Cid,
) -> Result<Vec<TreeEntry>, HashTreeError>
pub async fn list_directory( &self, cid: &Cid, ) -> Result<Vec<TreeEntry>, HashTreeError>
List directory entries using Cid (with decryption if key present) Handles both regular and chunked directory data
Sourcepub async fn resolve(
&self,
cid: &Cid,
path: &str,
) -> Result<Option<Cid>, HashTreeError>
pub async fn resolve( &self, cid: &Cid, path: &str, ) -> Result<Option<Cid>, HashTreeError>
Resolve a path within a tree (returns Cid with key if encrypted)
Sourcepub async fn resolve_path(
&self,
cid: &Cid,
path: &str,
) -> Result<Option<Cid>, HashTreeError>
pub async fn resolve_path( &self, cid: &Cid, path: &str, ) -> Result<Option<Cid>, HashTreeError>
Resolve a path within a tree using Cid (with decryption if key present)
Sourcepub async fn get_size(&self, hash: &Hash) -> Result<u64, HashTreeError>
pub async fn get_size(&self, hash: &Hash) -> Result<u64, HashTreeError>
Get total size of a tree
Sourcepub async fn walk(
&self,
cid: &Cid,
path: &str,
) -> Result<Vec<WalkEntry>, HashTreeError>
pub async fn walk( &self, cid: &Cid, path: &str, ) -> Result<Vec<WalkEntry>, HashTreeError>
Walk entire tree depth-first (returns Vec)
Sourcepub async fn walk_parallel(
&self,
cid: &Cid,
path: &str,
concurrency: usize,
) -> Result<Vec<WalkEntry>, HashTreeError>
pub async fn walk_parallel( &self, cid: &Cid, path: &str, concurrency: usize, ) -> Result<Vec<WalkEntry>, HashTreeError>
Walk entire tree with parallel fetching
Uses a work-stealing approach: always keeps concurrency requests in flight
Sourcepub async fn walk_parallel_with_progress(
&self,
cid: &Cid,
path: &str,
concurrency: usize,
progress: Option<&AtomicUsize>,
) -> Result<Vec<WalkEntry>, HashTreeError>
pub async fn walk_parallel_with_progress( &self, cid: &Cid, path: &str, concurrency: usize, progress: Option<&AtomicUsize>, ) -> Result<Vec<WalkEntry>, HashTreeError>
Walk entire tree with parallel fetching and optional progress counter The counter is incremented for each node fetched (not just entries found)
OPTIMIZATION: Blobs are NOT fetched - their metadata (hash, size, link_type) comes from the parent node’s link, so we just add them directly to entries. This avoids downloading file contents during tree traversal.
Sourcepub fn walk_stream(
&self,
cid: Cid,
initial_path: String,
) -> Pin<Box<dyn Stream<Item = Result<WalkEntry, HashTreeError>> + Send + '_>>
pub fn walk_stream( &self, cid: Cid, initial_path: String, ) -> Pin<Box<dyn Stream<Item = Result<WalkEntry, HashTreeError>> + Send + '_>>
Walk tree as stream
Sourcepub async fn set_entry(
&self,
root: &Cid,
path: &[&str],
name: &str,
entry_cid: &Cid,
size: u64,
link_type: LinkType,
) -> Result<Cid, HashTreeError>
pub async fn set_entry( &self, root: &Cid, path: &[&str], name: &str, entry_cid: &Cid, size: u64, link_type: LinkType, ) -> Result<Cid, HashTreeError>
Add or update an entry in a directory Returns new root Cid (immutable operation)
Sourcepub async fn remove_entry(
&self,
root: &Cid,
path: &[&str],
name: &str,
) -> Result<Cid, HashTreeError>
pub async fn remove_entry( &self, root: &Cid, path: &[&str], name: &str, ) -> Result<Cid, HashTreeError>
Remove an entry from a directory Returns new root Cid
Sourcepub async fn rename_entry(
&self,
root: &Cid,
path: &[&str],
old_name: &str,
new_name: &str,
) -> Result<Cid, HashTreeError>
pub async fn rename_entry( &self, root: &Cid, path: &[&str], old_name: &str, new_name: &str, ) -> Result<Cid, HashTreeError>
Rename an entry in a directory Returns new root Cid
Sourcepub async fn move_entry(
&self,
root: &Cid,
source_path: &[&str],
name: &str,
target_path: &[&str],
) -> Result<Cid, HashTreeError>
pub async fn move_entry( &self, root: &Cid, source_path: &[&str], name: &str, target_path: &[&str], ) -> Result<Cid, HashTreeError>
Move an entry to a different directory Returns new root Cid
Sourcepub fn chunk_size(&self) -> usize
pub fn chunk_size(&self) -> usize
Get chunk size configuration