1use super::paths;
2use anyhow::{Context, Result};
3use sha2::{Digest, Sha256 as Sha2_sha256};
4use std::fs::File;
5use std::io::{self, Read};
6use std::path::Path;
7
8pub struct Sha256(Sha2_sha256);
9
10impl Sha256 {
11 pub fn new() -> Sha256 {
12 let hasher = Sha2_sha256::new();
13 Sha256(hasher)
14 }
15
16 pub fn update(&mut self, bytes: &[u8]) -> &mut Sha256 {
17 let _ = self.0.update(bytes);
18 self
19 }
20
21 pub fn update_file(&mut self, mut file: &File) -> io::Result<&mut Sha256> {
22 let mut buf = [0; 64 * 1024];
23 loop {
24 let n = file.read(&mut buf)?;
25 if n == 0 {
26 break Ok(self);
27 }
28 self.update(&buf[..n]);
29 }
30 }
31
32 pub fn update_path<P: AsRef<Path>>(&mut self, path: P) -> Result<&mut Sha256> {
33 let path = path.as_ref();
34 let file = paths::open(path)?;
35 self.update_file(&file)
36 .with_context(|| format!("failed to read `{}`", path.display()))?;
37 Ok(self)
38 }
39
40 pub fn finish(&mut self) -> [u8; 32] {
41 self.0.finalize_reset().into()
42 }
43
44 pub fn finish_hex(&mut self) -> String {
45 hex::encode(self.finish())
46 }
47}
48
49impl Default for Sha256 {
50 fn default() -> Self {
51 Self::new()
52 }
53}