1use belt_hash::{BeltHash, Digest};
6
7use crate::contract::{Hasher, Identified};
8use crate::error::Result;
9
10#[derive(Debug, Default, Clone, Copy)]
12pub struct BeltHashHasher;
13
14impl BeltHashHasher {
15 pub const IDENTIFIER: &'static str = "belt-hash";
16
17 pub fn new() -> Self {
18 Self
19 }
20}
21
22impl Identified for BeltHashHasher {
23 fn identifier(&self) -> &str {
24 Self::IDENTIFIER
25 }
26}
27
28impl Hasher for BeltHashHasher {
29 fn digest(&self, data: &[u8]) -> Result<Vec<u8>> {
30 Ok(BeltHash::digest(data).to_vec())
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 const X: [u8; 13] = [
41 0xb1, 0x94, 0xba, 0xc8, 0x0a, 0x08, 0xf5, 0x3b, 0x36, 0x6d, 0x00, 0x8e, 0x58,
42 ];
43
44 #[test]
45 fn matches_stb_appendix_vector() {
46 let hasher = BeltHashHasher::new();
47 assert_eq!(
48 hasher.digest_hex(&X).unwrap(),
49 "abef9725d4c5a83597a367d14494cc2542f20f659ddfecc961a3ec550cba8c75"
50 );
51 assert_eq!(hasher.digest(&X).unwrap().len(), 32);
52 }
53
54 #[test]
56 fn digest_hex_is_lowercase_hex() {
57 let hex = BeltHashHasher::new().digest_hex(&X).unwrap();
58 assert_eq!(hex.len(), 64);
59 assert!(
60 hex.bytes()
61 .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
62 );
63 }
64
65 #[test]
67 fn distinct_inputs_distinct_digests() {
68 let hasher = BeltHashHasher::new();
69 assert_ne!(hasher.digest(&X).unwrap(), hasher.digest(b"abc").unwrap());
70 }
71}