1use anyhow::Result;
2use std::fs::File;
3use std::io::{Read, Seek, SeekFrom};
4use std::path::Path;
5
6const QUICK_HASH_BYTES: usize = 64 * 1024;
7
8pub fn quick_hash(path: &Path) -> Result<blake3::Hash> {
9 let mut f = File::open(path)?;
10 let mut buf = vec![0u8; QUICK_HASH_BYTES];
11 let n = f.read(&mut buf)?;
12 Ok(blake3::hash(&buf[..n]))
13}
14
15pub fn full_hash(path: &Path) -> Result<blake3::Hash> {
16 let mut f = File::open(path)?;
17 let mut hasher = blake3::Hasher::new();
18 std::io::copy(&mut f, &mut hasher)?;
19 Ok(hasher.finalize())
20}
21
22pub fn bytes_equal(a: &Path, b: &Path) -> Result<bool> {
23 const CHUNK: usize = 256 * 1024;
24 let mut fa = File::open(a)?;
25 let mut fb = File::open(b)?;
26 fa.seek(SeekFrom::Start(0))?;
27 fb.seek(SeekFrom::Start(0))?;
28 let mut ba = vec![0u8; CHUNK];
29 let mut bb = vec![0u8; CHUNK];
30 loop {
31 let na = fa.read(&mut ba)?;
32 let nb = fb.read(&mut bb)?;
33 if na != nb { return Ok(false); }
34 if na == 0 { return Ok(true); }
35 if ba[..na] != bb[..nb] { return Ok(false); }
36 }
37}