Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I9e0ff5ea33a5cf697473423e88f167ce6a6a6964
45 lines
1.1 KiB
Rust
45 lines
1.1 KiB
Rust
use std::path::Path;
|
|
|
|
use crate::{error::Result, model::ContentHash};
|
|
|
|
const BUFFER_SIZE: usize = 65536;
|
|
|
|
/// Computes the BLAKE3 hash of a file asynchronously.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `path` - Path to the file to hash
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// The content hash
|
|
///
|
|
/// # Errors
|
|
///
|
|
/// Returns I/O errors or task execution errors
|
|
pub async fn compute_file_hash(path: &Path) -> Result<ContentHash> {
|
|
let path = path.to_path_buf();
|
|
let hash = tokio::task::spawn_blocking(move || -> Result<ContentHash> {
|
|
let mut hasher = blake3::Hasher::new();
|
|
let mut file = std::fs::File::open(&path)?;
|
|
let mut buf = vec![0u8; BUFFER_SIZE];
|
|
loop {
|
|
let n = std::io::Read::read(&mut file, &mut buf)?;
|
|
if n == 0 {
|
|
break;
|
|
}
|
|
hasher.update(&buf[..n]);
|
|
}
|
|
Ok(ContentHash::new(hasher.finalize().to_hex().to_string()))
|
|
})
|
|
.await
|
|
.map_err(|e| crate::error::PinakesError::Io(std::io::Error::other(e)))??;
|
|
Ok(hash)
|
|
}
|
|
|
|
/// Computes the BLAKE3 hash of a byte slice synchronously.
|
|
#[must_use]
|
|
pub fn compute_hash_sync(data: &[u8]) -> ContentHash {
|
|
let hash = blake3::hash(data);
|
|
ContentHash::new(hash.to_hex().to_string())
|
|
}
|