use sha2::Digest;
use std::error::Error;
use tackler_api::metadata::Checksum;
#[derive(Debug, Clone)]
pub struct Hash {
hash_algo: String,
}
impl Default for Hash {
fn default() -> Self {
Hash {
hash_algo: "SHA-256".to_string(),
}
}
}
impl Hash {
pub fn from(algo: &str) -> Result<Hash, Box<dyn Error>> {
match algo {
"SHA-256" => {
Ok(Hash {
hash_algo: "SHA-256".to_string(),
})
}
_ => {
let msg = format!("Unsupported hash algorithm: {algo}");
Err(msg.into())
}
}
}
pub fn checksum(&self, items: &[String], separator: &[u8]) -> Result<Checksum, Box<dyn Error>> {
let mut hasher = match self.hash_algo.as_str() {
"SHA-256" => sha2::Sha256::default(),
_ => {
let msg = format!("Unsupported hash algorithm: {}", self.hash_algo);
return Err(msg.into());
}
};
hasher.reset();
for i in items {
hasher.update(i.as_bytes());
hasher.update(separator);
}
let hash = hasher.finalize();
Ok(Checksum {
algorithm: self.hash_algo.clone(),
value: format!("{:x}", hash),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hasher() {
let uuids = vec![
"9c123cbe-4acd-475d-bbcf-96c1fcba58cb".to_string(),
"2e546b18-6ce6-4bb3-9f4b-21b77a768a4c".to_string(),
"67bdab27-da08-4647-b0d1-57c9ed129657".to_string(),
];
let hash = Hash::from("SHA-256").unwrap();
let cs = hash.checksum(&uuids, "\n".as_bytes()).unwrap();
assert_eq!(
cs.value,
"16418783ef294f830721159ee59cc3388c8b69c13afba2256cf756c6097fe687"
);
}
#[test]
fn hasher_err() {
let hash = Hash {
hash_algo: "foo".to_string(),
};
assert_eq!(hash.hash_algo, "foo".to_string());
}
}