1use std::fs::File;
5use std::io::{Read, Result as IoResult};
6use std::path::Path;
7
8use sha2::{Digest, Sha256};
9
10const READ_CHUNK: usize = 64 * 1024;
11
12pub fn sha256_hex(path: impl AsRef<Path>) -> IoResult<String> {
21 let mut file = File::open(path)?;
22 let mut hasher = Sha256::new();
23 let mut buf = vec![0u8; READ_CHUNK];
24 loop {
25 let n = file.read(&mut buf)?;
26 if n == 0 {
27 break;
28 }
29 hasher.update(&buf[..n]);
30 }
31 Ok(hex::encode(hasher.finalize()))
32}
33
34#[cfg(test)]
35mod tests {
36 #![allow(clippy::unwrap_used)]
37
38 use std::io::Write;
39
40 use tempfile::NamedTempFile;
41
42 use super::*;
43
44 #[test]
45 fn sha256_empty_file_matches_known_constant() {
46 let tmp = NamedTempFile::new().unwrap();
47 let digest = sha256_hex(tmp.path()).unwrap();
48 assert_eq!(
49 digest,
50 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
51 );
52 }
53
54 #[test]
55 fn sha256_known_vector_for_abc() {
56 let mut tmp = NamedTempFile::new().unwrap();
57 tmp.write_all(b"abc").unwrap();
58 tmp.flush().unwrap();
59 let digest = sha256_hex(tmp.path()).unwrap();
60 assert_eq!(
61 digest,
62 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
63 );
64 }
65}