use std::fs::File;
use std::io::Read;
use camino::Utf8PathBuf;
use sha2::{Digest, Sha256};
use crate::ScanError;
const BUF_SIZE: usize = 65_536;
#[allow(clippy::missing_errors_doc)]
pub fn sha256_file(path: &Utf8PathBuf) -> Result<String, ScanError> {
let mut f = File::open(path.as_std_path()).map_err(|e| ScanError::Io {
path: path.clone(),
source: e,
})?;
let mut hasher = Sha256::new();
let mut buf = vec![0u8; BUF_SIZE];
loop {
let n = f.read(&mut buf).map_err(|e| ScanError::Io {
path: path.clone(),
source: e,
})?;
if n == 0 {
break;
}
hasher.update(&buf[..n]);
}
Ok(hex::encode(hasher.finalize()))
}
#[cfg(test)]
mod tests {
use std::io::Write;
use super::*;
#[test]
fn known_sha256_of_empty_file() {
let dir = tempfile::tempdir().expect("tempdir");
let p = dir.path().join("empty.bin");
File::create(&p)
.expect("create")
.write_all(b"")
.expect("write");
let utf8: Utf8PathBuf = p.try_into().expect("utf8");
let h = sha256_file(&utf8).expect("hash");
assert_eq!(
h,
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
}