use digest::{Digest, DynDigest}; use std::{fs::File, io::Read, path::Path}; pub const DEFAULT_HASHER: &str = "sha3-512"; pub fn find_hasher(s: &str) -> std::io::Result> { match s { "sha3-512" => Ok(Box::new(sha3::Sha3_512::new())), _ => Err(std::io::ErrorKind::InvalidInput.into()), } } pub fn hash_reader(hasher_name: &str, reader: &mut R) -> std::io::Result { let mut buf = [0u8; 1024]; let mut hasher = find_hasher(hasher_name)?; loop { let n = reader.read(&mut buf)?; hasher.update(&buf[..n]); if n == 0 { break; } } Ok(format!( "{hasher_name}:{}", const_hex::encode(hasher.finalize()), )) } pub fn verify_reader(reader: &mut R, expected: &str) -> std::io::Result { let hasher = expected.split(':').next().unwrap(); let hash = hash_reader(hasher, reader)?; Ok(hash == expected) } pub fn hash_file>(hasher: &str, path: P) -> std::io::Result { hash_reader(hasher, &mut File::open(path)?) } pub fn verify_file>(path: P, expected: &str) -> std::io::Result { verify_reader(&mut File::open(path)?, expected) }