1use std::{
2    hash::{DefaultHasher, Hasher},
3    io::{self, Read, Seek, SeekFrom, Write},
4};
5
6pub fn copy<R, W>(reader: &mut R, writer: &mut W, bytes_to_copy: u64) -> io::Result<()>
8where
9    R: Read,
10    W: Write,
11{
12    const BUFFER_SIZE: u64 = 1024;
13    let mut buf = vec![0u8; BUFFER_SIZE as usize];
14    let mut to_copy = bytes_to_copy;
15    while to_copy >= BUFFER_SIZE {
16        reader.read_exact(&mut buf)?;
17        writer.write_all(&buf)?;
18        to_copy -= BUFFER_SIZE;
19    }
20    if to_copy > 0 {
21        buf.resize(to_copy as usize, 0);
22        reader.read_exact(&mut buf)?;
23        writer.write_all(&buf)?;
24    }
25    Ok(())
26}
27
28#[derive(Default, Debug, Clone)]
30pub struct FileHasher {
31    hasher: DefaultHasher,
32}
33
34impl FileHasher {
35    pub fn new() -> Self {
36        Self {
37            hasher: DefaultHasher::new(),
38        }
39    }
40
41    pub fn hash<R>(mut self, reader: &mut R, from_byte: u64, length: u64) -> io::Result<u64>
43    where
44        R: Read + Seek,
45    {
46        reader.seek(SeekFrom::Start(from_byte))?;
47        copy(reader, &mut self, length)?;
48        Ok(self.hasher.finish())
49    }
50
51    pub fn finish(self) -> u64 {
53        self.hasher.finish()
54    }
55}
56
57impl Write for FileHasher {
58    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
59        self.hasher.write(buf);
60        Ok(buf.len())
61    }
62
63    fn flush(&mut self) -> io::Result<()> {
64        Ok(())
65    }
66}