tabby/crates/aim-downloader/src/hash.rs

78 lines
2.2 KiB
Rust

use std::{fs, io, str};
use sha2::{Digest, Sha256};
use crate::error::ValidateError;
pub struct HashChecker;
impl HashChecker {
pub fn check(filename: &str, expected_hash: &str) -> Result<(), ValidateError> {
let mut result = Ok(());
if filename != "stdout" && (!expected_hash.is_empty()) {
let actual_hash = HashChecker::sha256sum(filename);
if actual_hash != expected_hash {
result = Err(ValidateError::Sha256Mismatch);
}
match result {
Ok(()) => println!("✅ Checksum OK."),
Err(ValidateError::Sha256Mismatch) => println!(
"❌ Checksum verification failed for {filename}:\n expected: {expected_hash}\n got: {actual_hash}"),
}
}
result
}
fn sha256sum(filename: &str) -> String {
let mut hasher = Sha256::new();
let mut file = fs::File::open(filename).unwrap();
io::copy(&mut file, &mut hasher).unwrap();
let computed_hash = hasher.finalize();
drop(file);
format!("{computed_hash:x}")
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_err {
($expression:expr, $($pattern:tt)+) => {
match $expression {
$($pattern)+ => (),
ref e => panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), e),
}
}
}
#[test]
fn test_check_api_fails_when_checksum_mismatch() {
let expected = "AAAA847124bfb9d9a9d44af6f00d8003006c44b9ef9ba458b5d4d3fc5f81bde5";
assert_err!(
HashChecker::check("LICENCE.md", expected),
Err(ValidateError::Sha256Mismatch)
);
}
#[test]
fn test_sha256sum_api() {
let expected = "21d7847124bfb9d9a9d44af6f00d8003006c44b9ef9ba458b5d4d3fc5f81bde5";
let actual = HashChecker::sha256sum("LICENCE.md");
assert_eq!(actual, expected);
}
#[test]
fn test_check_api_works_when_typical() {
let expected = "21d7847124bfb9d9a9d44af6f00d8003006c44b9ef9ba458b5d4d3fc5f81bde5";
let is_match = HashChecker::check("LICENCE.md", expected).is_ok();
assert!(is_match);
}
}