pub type SimpleProgress = dyn Fn(u64) + Sync;
pub type Verify =
std::sync::Arc<dyn Fn(std::path::PathBuf, &SimpleProgress) -> Verification + Send + Sync>;
#[derive(Debug, Eq, 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 with_digest<D: digest::Digest>(hash: Vec<u8>) -> crate::Verify {
use std::io::Read;
std::sync::Arc::new(
move |path: std::path::PathBuf, cb: &crate::SimpleProgress| {
let mut hasher = D::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
},
)
}