duplicate_finder/
hashing.rs

1use crate::{constants, file_info::FileInfo, output_msg::OutputMsg};
2use siphasher::sip128::Hasher128;
3use std::{fs::File, hash::Hasher, io::Read, path::PathBuf, sync::mpsc::Sender, sync::Arc};
4
5pub struct CalculateHash {
6    file: File,
7    hasher: siphasher::sip128::SipHasher,
8    path_buf: Arc<PathBuf>,
9    progress_in_bytes: u64,
10    size_in_bytes: u64,
11    sender: Sender<OutputMsg>,
12}
13
14impl CalculateHash {
15    pub fn new(path_buf: PathBuf, sender: Sender<OutputMsg>) -> Self {
16        let file = File::open(&path_buf).expect("can not read file");
17        let size_in_bytes = file.metadata().unwrap().len();
18
19        let path_buf = Arc::new(path_buf);
20
21        CalculateHash {
22            file,
23            hasher: siphasher::sip128::SipHasher::new(),
24            path_buf,
25            progress_in_bytes: 0,
26            size_in_bytes,
27            sender,
28        }
29    }
30
31    fn send_output_msg(&mut self, progress: OutputMsg) {
32        match self.sender.send(progress) {
33            Ok(_) => (),
34            Err(e) => panic!("Error sending data with mpsc : {}", e),
35        }
36    }
37
38    pub fn calculate(&mut self) -> FileInfo {
39        loop {
40            let mut chunk = Vec::with_capacity(constants::HASHING_CHUNK_SIZE);
41            let size = self
42                .file
43                .by_ref()
44                .take(constants::HASHING_CHUNK_SIZE as u64)
45                .read_to_end(&mut chunk)
46                .expect("Can't read chunk.");
47
48            if size == 0 {
49                let hash_128 = self.hasher.finish128();
50
51                let file_info = FileInfo {
52                    path: self.path_buf.clone(),
53                    hash: hash_128.into(),
54                };
55
56                self.send_output_msg(OutputMsg::Summary);
57
58                return file_info;
59            }
60
61            self.progress_in_bytes += size as u64;
62
63            self.send_output_msg(OutputMsg::FileProgress(
64                self.progress_in_bytes * 100 / self.size_in_bytes,
65                self.path_buf.clone(),
66            ));
67
68            self.hasher.write(&chunk);
69        }
70    }
71}