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}