use std::{
hash::{DefaultHasher, Hasher},
io::{self, Read, Seek, SeekFrom, Write},
};
pub fn copy<R, W>(reader: &mut R, writer: &mut W, bytes_to_copy: u64) -> io::Result<()>
where
R: Read,
W: Write,
{
const BUFFER_SIZE: u64 = 1024;
let mut buf = vec![0u8; BUFFER_SIZE as usize];
let mut to_copy = bytes_to_copy;
while to_copy >= BUFFER_SIZE {
reader.read_exact(&mut buf)?;
writer.write_all(&buf)?;
to_copy -= BUFFER_SIZE;
}
if to_copy > 0 {
buf.resize(to_copy as usize, 0);
reader.read_exact(&mut buf)?;
writer.write_all(&buf)?;
}
Ok(())
}
#[derive(Default, Debug, Clone)]
pub struct FileHasher {
hasher: DefaultHasher,
}
impl FileHasher {
pub fn new() -> Self {
Self {
hasher: DefaultHasher::new(),
}
}
pub fn hash<R>(mut self, reader: &mut R, from_byte: u64, length: u64) -> io::Result<u64>
where
R: Read + Seek,
{
reader.seek(SeekFrom::Start(from_byte))?;
copy(reader, &mut self, length)?;
Ok(self.hasher.finish())
}
pub fn finish(self) -> u64 {
self.hasher.finish()
}
}
impl Write for FileHasher {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.hasher.write(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}