blueprint_strong_hash/
lib.rs1use std::collections::BTreeMap;
12use std::collections::HashMap;
13use std::hash::Hash;
14use std::hash::Hasher;
15use std::marker::PhantomData;
16use std::sync::Arc;
17
18use ref_cast::RefCast;
19pub use blueprint_strong_hash_derive::StrongHash;
20
21use crate as strong_hash;
22
23mod impls;
24
25pub trait StrongHash {
62 fn strong_hash<H: Hasher>(&self, state: &mut H);
63}
64
65#[macro_export]
66macro_rules! impl_strong_hash_for_impl_hash {
67 ($($t:ty)*) => {
68 $(
69 impl strong_hash::StrongHash for $t {
70 fn strong_hash<H: std::hash::Hasher>(&self, state: &mut H) {
71 std::hash::Hash::hash(self, state);
72 }
73 }
74 )*
75 };
76}
77
78impl_strong_hash_for_impl_hash!(bool u8 i8 u16 i16 u32 i32 u64 i64 usize str &str String);
79
80impl<T: StrongHash> StrongHash for [T] {
81 fn strong_hash<H: Hasher>(&self, state: &mut H) {
82 self.len().strong_hash(state);
83 for item in self.iter() {
84 item.strong_hash(state);
85 }
86 }
87}
88
89impl<T: StrongHash> StrongHash for &[T] {
90 fn strong_hash<H: Hasher>(&self, state: &mut H) {
91 <[T] as StrongHash>::strong_hash(*self, state);
92 }
93}
94
95impl<T: StrongHash> StrongHash for Vec<T> {
96 fn strong_hash<H: Hasher>(&self, state: &mut H) {
97 self.len().strong_hash(state);
98 (&self[..]).strong_hash(state);
99 }
100}
101
102impl<T: StrongHash> StrongHash for Option<T> {
103 fn strong_hash<H: Hasher>(&self, state: &mut H) {
104 self.is_some().strong_hash(state);
105 if let Some(t) = self.as_ref() {
106 t.strong_hash(state);
107 }
108 }
109}
110
111impl StrongHash for () {
112 fn strong_hash<H: Hasher>(&self, _state: &mut H) {}
113}
114
115impl<A: StrongHash> StrongHash for (A,) {
116 fn strong_hash<H: Hasher>(&self, state: &mut H) {
117 1.strong_hash(state);
118 self.0.strong_hash(state);
119 }
120}
121
122impl<A: StrongHash, B: StrongHash> StrongHash for (A, B) {
123 fn strong_hash<H: Hasher>(&self, state: &mut H) {
124 2.strong_hash(state);
125 self.0.strong_hash(state);
126 self.1.strong_hash(state);
127 }
128}
129
130impl<A: StrongHash, B: StrongHash, C: StrongHash> StrongHash for (A, B, C) {
131 fn strong_hash<H: Hasher>(&self, state: &mut H) {
132 3.strong_hash(state);
133 self.0.strong_hash(state);
134 self.1.strong_hash(state);
135 self.2.strong_hash(state);
136 }
137}
138
139impl<T: StrongHash + ?Sized> StrongHash for Box<T> {
140 fn strong_hash<H: Hasher>(&self, state: &mut H) {
141 self.as_ref().strong_hash(state);
142 }
143}
144
145impl<T: StrongHash + ?Sized> StrongHash for Arc<T> {
146 fn strong_hash<H: Hasher>(&self, state: &mut H) {
147 self.as_ref().strong_hash(state);
148 }
149}
150
151impl<K: StrongHash, V: StrongHash> StrongHash for BTreeMap<K, V> {
152 fn strong_hash<H: Hasher>(&self, state: &mut H) {
153 self.len().strong_hash(state);
154 for (k, v) in self.iter() {
155 k.strong_hash(state);
156 v.strong_hash(state);
157 }
158 }
159}
160
161impl<K: StrongHash, V: StrongHash> StrongHash for HashMap<K, V> {
162 fn strong_hash<H: Hasher>(&self, state: &mut H) {
163 self.len().strong_hash(state);
164 for (k, v) in self.iter() {
165 k.strong_hash(state);
166 v.strong_hash(state);
167 }
168 }
169}
170
171impl StrongHash for *const () {
172 fn strong_hash<H: Hasher>(&self, state: &mut H) {
173 (*self as usize).strong_hash(state);
174 }
175}
176
177impl<T: ?Sized> StrongHash for PhantomData<T> {
178 fn strong_hash<H: Hasher>(&self, state: &mut H) {
179 self.hash(state);
180 }
181}
182
183#[derive(RefCast)]
185#[repr(transparent)]
186pub struct UseStrongHashing<T: ?Sized>(pub T);
187
188impl<T> Hash for UseStrongHashing<T>
189where
190 T: ?Sized + StrongHash,
191{
192 fn hash<H: Hasher>(&self, state: &mut H) {
193 self.0.strong_hash(state);
194 }
195}
196
197#[cfg(test)]
198mod test {
199 use super::*;
200
201 struct TestHashable {
202 hash: u64,
203 strong_hash: u64,
204 }
205
206 impl Hash for TestHashable {
207 fn hash<H: Hasher>(&self, state: &mut H) {
208 self.hash.hash(state);
209 }
210 }
211
212 impl StrongHash for TestHashable {
213 fn strong_hash<H: Hasher>(&self, state: &mut H) {
214 self.strong_hash.strong_hash(state);
215 }
216 }
217
218 fn hash<T: Hash>(t: &T) -> u64 {
219 let mut hasher = std::collections::hash_map::DefaultHasher::new();
220 t.hash(&mut hasher);
221 hasher.finish()
222 }
223
224 fn strong_hash<T: StrongHash>(t: &T) -> u64 {
225 let mut hasher = std::collections::hash_map::DefaultHasher::new();
226 t.strong_hash(&mut hasher);
227 hasher.finish()
228 }
229
230 #[test]
231 fn test_use_strong_hashing() {
232 let x = TestHashable {
233 hash: 1,
234 strong_hash: 2,
235 };
236
237 let y = TestHashable {
238 hash: 1,
239 strong_hash: 3,
240 };
241
242 assert_eq!(hash(&x), hash(&y));
243
244 assert_eq!(strong_hash(&x), hash(UseStrongHashing::ref_cast(&x)));
245
246 assert_ne!(
247 hash(UseStrongHashing::ref_cast(&x)),
248 hash(UseStrongHashing::ref_cast(&y))
249 );
250 }
251}