Skip to main content

ps_hash_core/hash/implementations/
hash_trait.rs

1use super::super::Hash;
2
3impl std::hash::Hash for Hash {
4    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
5        state.write(&self.inner);
6    }
7}
8
9#[cfg(test)]
10#[allow(clippy::expect_used)]
11mod tests {
12    use std::collections::{HashMap, HashSet};
13    use std::hash::{DefaultHasher, Hash as StdHash, Hasher};
14
15    use crate::Hash;
16
17    fn compute_hash<T: StdHash>(t: &T) -> u64 {
18        let mut hasher = DefaultHasher::new();
19        t.hash(&mut hasher);
20        hasher.finish()
21    }
22
23    #[test]
24    fn hash_deterministic() {
25        let h = Hash::hash(b"deterministic").expect("hashing should succeed");
26        let hash1 = compute_hash(&h);
27        let hash2 = compute_hash(&h);
28        assert_eq!(hash1, hash2);
29    }
30
31    #[test]
32    fn hash_same_for_equal_hashes() {
33        let h1 = Hash::hash(b"same").expect("hashing should succeed");
34        let h2 = Hash::hash(b"same").expect("hashing should succeed");
35        assert_eq!(compute_hash(&h1), compute_hash(&h2));
36    }
37
38    #[test]
39    fn hash_different_for_different_hashes() {
40        let h1 = Hash::hash(b"diff1").expect("hashing should succeed");
41        let h2 = Hash::hash(b"diff2").expect("hashing should succeed");
42        assert_ne!(compute_hash(&h1), compute_hash(&h2));
43    }
44
45    #[test]
46    fn hash_enables_hashset() {
47        let mut set = HashSet::new();
48        set.insert(Hash::hash(b"a").expect("hashing should succeed"));
49        set.insert(Hash::hash(b"b").expect("hashing should succeed"));
50        set.insert(Hash::hash(b"a").expect("hashing should succeed"));
51        assert_eq!(set.len(), 2);
52    }
53
54    #[test]
55    fn hash_enables_hashmap_key() {
56        let mut map = HashMap::new();
57        let h1 = Hash::hash(b"key1").expect("hashing should succeed");
58        let h2 = Hash::hash(b"key2").expect("hashing should succeed");
59        map.insert(h1, "value1");
60        map.insert(h2, "value2");
61        assert_eq!(map.get(&h1), Some(&"value1"));
62        assert_eq!(map.get(&h2), Some(&"value2"));
63    }
64
65    #[test]
66    fn hash_lookup_works() {
67        let mut set = HashSet::new();
68        let original = Hash::hash(b"lookup").expect("hashing should succeed");
69        set.insert(original);
70
71        let same = Hash::hash(b"lookup").expect("hashing should succeed");
72        assert!(set.contains(&same));
73    }
74
75    #[test]
76    fn hash_lookup_after_validation() {
77        let mut set = HashSet::new();
78        let original = Hash::hash(b"validated").expect("hashing should succeed");
79        set.insert(original);
80
81        let validated = Hash::validate(original.to_string())
82            .expect("validation of an uncorrupted hash should succeed");
83        assert!(set.contains(&validated));
84    }
85
86    #[test]
87    fn hash_consistent_with_eq() {
88        let h1 = Hash::hash(b"consistent").expect("hashing should succeed");
89        let h2 = Hash::hash(b"consistent").expect("hashing should succeed");
90
91        if h1 == h2 {
92            assert_eq!(compute_hash(&h1), compute_hash(&h2));
93        }
94    }
95
96    #[test]
97    fn hash_trait_bound() {
98        fn assert_hash<T: StdHash>() {}
99        assert_hash::<Hash>();
100    }
101
102    #[test]
103    fn hash_after_corruption_recovery() {
104        let mut set = HashSet::new();
105        let original = Hash::hash(b"recovery").expect("hashing should succeed");
106        set.insert(original);
107
108        let mut corrupted = original.to_string().into_bytes();
109        // Replace with a character that is valid in both alphabets, so that
110        // the corruption stays inside the encoded character set.
111        corrupted[5] = if corrupted[5] == b'A' { b'B' } else { b'A' };
112        let recovered = Hash::validate(
113            String::from_utf8(corrupted).expect("corrupted bytes should be valid UTF-8"),
114        )
115        .expect("single-character corruption should be recovered");
116        assert!(set.contains(&recovered));
117    }
118
119    #[test]
120    fn hash_many_insertions() {
121        let mut set = HashSet::new();
122
123        for i in 0u32..100 {
124            let h = Hash::hash(i.to_le_bytes()).expect("hashing should succeed");
125            set.insert(h);
126        }
127
128        assert_eq!(set.len(), 100);
129    }
130}