use belt_hash::{BeltHash, Digest};
use crate::contract::{Hasher, Identified};
use crate::error::Result;
#[derive(Debug, Default, Clone, Copy)]
pub struct BeltHashHasher;
impl BeltHashHasher {
pub const IDENTIFIER: &'static str = "belt-hash";
pub fn new() -> Self {
Self
}
}
impl Identified for BeltHashHasher {
fn identifier(&self) -> &str {
Self::IDENTIFIER
}
}
impl Hasher for BeltHashHasher {
fn digest(&self, data: &[u8]) -> Result<Vec<u8>> {
Ok(BeltHash::digest(data).to_vec())
}
}
#[cfg(test)]
mod tests {
use super::*;
const X: [u8; 13] = [
0xb1, 0x94, 0xba, 0xc8, 0x0a, 0x08, 0xf5, 0x3b, 0x36, 0x6d, 0x00, 0x8e, 0x58,
];
#[test]
fn matches_stb_appendix_vector() {
let hasher = BeltHashHasher::new();
assert_eq!(
hasher.digest_hex(&X).unwrap(),
"abef9725d4c5a83597a367d14494cc2542f20f659ddfecc961a3ec550cba8c75"
);
assert_eq!(hasher.digest(&X).unwrap().len(), 32);
}
#[test]
fn digest_hex_is_lowercase_hex() {
let hex = BeltHashHasher::new().digest_hex(&X).unwrap();
assert_eq!(hex.len(), 64);
assert!(
hex.bytes()
.all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
);
}
#[test]
fn distinct_inputs_distinct_digests() {
let hasher = BeltHashHasher::new();
assert_ne!(hasher.digest(&X).unwrap(), hasher.digest(b"abc").unwrap());
}
}