use md5::Context as Md5Context;
use sha1::{Digest, Sha1};
use sha3::Sha3_256;
pub fn sha1_hex(data: &[u8]) -> String {
let mut hasher = Sha1::new();
hasher.update(data);
hex::encode(hasher.finalize())
}
pub fn sha3_256_hex(data: &[u8]) -> String {
let mut hasher = Sha3_256::new();
Digest::update(&mut hasher, data);
hex::encode(hasher.finalize())
}
pub fn md5_hex(data: &[u8]) -> String {
let mut ctx = Md5Context::new();
ctx.consume(data);
format!("{:x}", ctx.compute())
}
pub fn manifest_checksum(content: &[u8]) -> String {
md5_hex(content)
}
pub fn delta_checksum(data: &[u8]) -> u32 {
let mut sum: u64 = 0;
let mut chunks = data.chunks_exact(4);
for chunk in &mut chunks {
let word = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
sum = sum.wrapping_add(word as u64);
}
let remainder = chunks.remainder();
if !remainder.is_empty() {
let mut padded = [0u8; 4];
padded[..remainder.len()].copy_from_slice(remainder);
let word = u32::from_be_bytes(padded);
sum = sum.wrapping_add(word as u64);
}
while sum > 0xFFFFFFFF {
sum = (sum & 0xFFFFFFFF) + (sum >> 32);
}
sum as u32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sha1() {
let hash = sha1_hex(b"hello world");
assert_eq!(hash, "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed");
}
#[test]
fn test_md5() {
let hash = md5_hex(b"hello world");
assert_eq!(hash, "5eb63bbbe01eeed093cb22bb8f5acdc3");
}
}