1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
pub type SimpleProgress = dyn Fn(u64) + Sync;
pub type Verify =
std::sync::Arc<dyn Fn(std::path::PathBuf, &SimpleProgress) -> Verification + Send + Sync>;
#[derive(Debug, PartialEq)]
pub enum Verification {
NotVerified,
Failed,
Ok,
}
impl std::fmt::Display for Verification {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match &self {
Self::NotVerified => "not verified",
Self::Failed => "FAILED",
Self::Ok => "Ok",
}
)
}
}
#[must_use]
pub fn noop() -> crate::Verify {
std::sync::Arc::new(|_: std::path::PathBuf, _: &crate::SimpleProgress| {
Verification::NotVerified
})
}
#[cfg(feature = "verify")]
#[must_use]
pub fn sha3_256(hash: Vec<u8>) -> crate::Verify {
use sha3::Digest;
use std::io::Read;
std::sync::Arc::new(
move |path: std::path::PathBuf, cb: &crate::SimpleProgress| {
let mut hasher = sha3::Sha3_256::new();
if let Ok(file) = std::fs::OpenOptions::new().read(true).open(&path) {
let mut reader = std::io::BufReader::with_capacity(1024 * 1024, file);
let mut current = 0;
let mut buffer = [0_u8; 1024 * 1024];
while let Ok(n) = reader.read(&mut buffer[..]) {
if n == 0 {
break;
}
hasher.update(&buffer[..n]);
cb(current);
current += n as u64;
}
let result = hasher.finalize();
if result.len() != hash.len() {
return Verification::Failed;
}
for i in 0..result.len() {
if result[i] != hash[i] {
return Verification::Failed;
}
}
return Verification::Ok;
}
Verification::Failed
},
)
}