1use std::fs::File;
2use std::io::{self, Read, Seek, SeekFrom};
3use std::path::Path;
4use xxhash_rust::xxh64::Xxh64;
5
6#[derive(Debug, Clone)]
8pub struct PartialOptions {
9 pub head: usize,
10 pub tail: usize,
11}
12
13impl Default for PartialOptions {
14 fn default() -> Self {
15 Self {
16 head: 64 * 1024,
17 tail: 64 * 1024,
18 }
19 }
20}
21
22pub fn partial_digest(path: &Path, opts: &PartialOptions) -> io::Result<String> {
24 let mut file = File::open(path)?;
25 let len = file.metadata()?.len() as usize;
26 let mut hasher = Xxh64::new(0);
27
28 if len <= opts.head + opts.tail {
29 let mut buf = Vec::new();
30 file.read_to_end(&mut buf)?;
31 hasher.update(&buf);
32 } else {
33 let mut head = vec![0u8; opts.head];
34 file.read_exact(&mut head)?;
35 hasher.update(&head);
36
37 let tail_start = len.saturating_sub(opts.tail);
38 file.seek(SeekFrom::Start(tail_start as u64))?;
39 let mut tail = vec![0u8; opts.tail];
40 file.read_exact(&mut tail)?;
41 hasher.update(&tail);
42 }
43
44 Ok(format!("{:016x}", hasher.digest()))
45}