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 { let path = path.to_path_buf(); let hash = tokio::task::spawn_blocking(move || -> Result { 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()) }