1use std::hash::{Hash, Hasher};
2
3use data_encoding::BASE32_DNSSEC;
4use xxhash_rust::xxh3::Xxh3;
5
6#[derive(Default)]
11pub struct StableHasher(Xxh3);
12
13impl StableHasher {
14 pub fn new() -> Self {
15 Default::default()
16 }
17
18 pub fn finish_as_short_hash(&self) -> String {
19 let hash = self.finish();
20 BASE32_DNSSEC.encode(&hash.to_le_bytes())
21 }
22}
23
24impl Hasher for StableHasher {
25 fn finish(&self) -> u64 {
26 self.0.finish()
27 }
28
29 fn write(&mut self, bytes: &[u8]) {
30 self.0.write(bytes)
31 }
32}
33
34pub fn short_hash(hashable: impl Hash) -> String {
35 let mut hasher = StableHasher::new();
36 hashable.hash(&mut hasher);
37 hasher.finish_as_short_hash()
38}
39
40#[cfg(test)]
41mod tests {
42 use super::short_hash;
43
44 #[test]
45 fn short_hash_is_stable() {
46 assert_eq!(short_hash("abcd"), "e1p6jp2ak1nmk");
47 assert_eq!(short_hash(123), "8fupdqgl2ulsq");
48 }
49}