Skip to content

Commit d48b37c

Browse files
krallinfacebook-github-bot
authored andcommitted
strong_hash: allow requesting that Hash use the StrongHash through a type wrapper
Summary: The goal of this is to allow you to take something that implements `StrongHash`, pass it to something that expects `Hash` and yet have it use the `StrongHash` implementation (but not the `StrongHasher::finish`: since your callee wants to `Hash` it'll have to accept it only gets 64 bits worth of hash). Reviewed By: cjhopman, scottcao Differential Revision: D73095295 fbshipit-source-id: 238f0c9b8d6b26bec9a0bc4ef8df86e8163406e2
1 parent ecec737 commit d48b37c

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ indenter = "0.3.3"
4343
memchr = "2.4.1"
4444
proc-macro2 = "1.0"
4545
quote = "1.0.3"
46+
ref-cast = "1.0.0"
4647
syn = "2"

gazebo/strong_hash/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ repository = { workspace = true }
77
version = "0.1.0"
88

99
[dependencies]
10+
ref-cast = { workspace = true }
1011
strong_hash_derive = { workspace = true }

gazebo/strong_hash/src/lib.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::hash::Hash;
1313
use std::hash::Hasher;
1414
use std::sync::Arc;
1515

16+
use ref_cast::RefCast;
1617
pub use strong_hash_derive::StrongHash;
1718

1819
/// `StrongHasher` is a trait for hashing functions that return more than 64
@@ -200,3 +201,73 @@ impl StrongHash for *const () {
200201
(*self as usize).strong_hash(state);
201202
}
202203
}
204+
205+
/// A wrapper can be used to implement `Hash` using the inner type's `StrongHash`.
206+
#[derive(RefCast)]
207+
#[repr(transparent)]
208+
pub struct UseStrongHashing<T: ?Sized>(pub T);
209+
210+
impl<T> Hash for UseStrongHashing<T>
211+
where
212+
T: ?Sized + StrongHash,
213+
{
214+
fn hash<H: Hasher>(&self, state: &mut H) {
215+
self.0.strong_hash(state);
216+
}
217+
}
218+
219+
#[cfg(test)]
220+
mod test {
221+
use super::*;
222+
223+
struct TestHashable {
224+
hash: u64,
225+
strong_hash: u64,
226+
}
227+
228+
impl Hash for TestHashable {
229+
fn hash<H: Hasher>(&self, state: &mut H) {
230+
self.hash.hash(state);
231+
}
232+
}
233+
234+
impl StrongHash for TestHashable {
235+
fn strong_hash<H: Hasher>(&self, state: &mut H) {
236+
self.strong_hash.strong_hash(state);
237+
}
238+
}
239+
240+
fn hash<T: Hash>(t: &T) -> u64 {
241+
let mut hasher = std::collections::hash_map::DefaultHasher::new();
242+
t.hash(&mut hasher);
243+
hasher.finish()
244+
}
245+
246+
fn strong_hash<T: StrongHash>(t: &T) -> u64 {
247+
let mut hasher = std::collections::hash_map::DefaultHasher::new();
248+
t.strong_hash(&mut hasher);
249+
hasher.finish()
250+
}
251+
252+
#[test]
253+
fn test_use_strong_hashing() {
254+
let x = TestHashable {
255+
hash: 1,
256+
strong_hash: 2,
257+
};
258+
259+
let y = TestHashable {
260+
hash: 1,
261+
strong_hash: 3,
262+
};
263+
264+
assert_eq!(hash(&x), hash(&y));
265+
266+
assert_eq!(strong_hash(&x), hash(UseStrongHashing::ref_cast(&x)));
267+
268+
assert_ne!(
269+
hash(UseStrongHashing::ref_cast(&x)),
270+
hash(UseStrongHashing::ref_cast(&y))
271+
);
272+
}
273+
}

0 commit comments

Comments
 (0)