scarb_stable_hash/
lib.rs

1use std::hash::{Hash, Hasher};
2
3use data_encoding::BASE32_DNSSEC;
4use xxhash_rust::xxh3::Xxh3;
5
6/// Implementation of a hasher that produces the same values across Scarb releases.
7///
8/// The hasher should be fast and have a low chance of collisions (but is not sufficient for
9/// cryptographic purposes).
10#[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}