1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
//! turbo-prehash
//!
//! A small wrapper around `std::hash::Hasher` that allows you to pre-hash a
//! value before hashing it.
//!
//! This is useful for when you want to hash a value that is expensive to
//! compute (e.g. a large string) but you want to avoid re-hashing it every
//! time.
//!
//! # Example
//!
//! ```
//! use turbo_prehash::{BuildHasherExt, PreHashed};
//! use std::collections::HashMap;
//! use std::hash::{BuildHasherDefault, RandomState, Hash};
//!
//! /// hash a key, returning a prehashed value
//! fn hash_key<T: Hash>(key: T) -> PreHashed<T> {
//! RandomState::new().prehash(key)
//! }
//!
//! // create hashmap to hold pre-hashed values
//! let mut map: HashMap<PreHashed<String>, String> = Default::default();
//!
//! // insert a prehashed value
//! let hashed_key = hash_key("hello".to_string());
//! map.insert(hashed_key.clone(), "world".to_string());
//!
//! // get the value
//! assert_eq!(map.get(&hashed_key), Some(&"world".to_string()));
//! ```
use std::{
fmt,
hash::{BuildHasher, Hash, Hasher},
ops::Deref,
};
/// A wrapper type that hashes some `inner` on creation, implementing [Hash]
/// by simply returning the pre-computed hash.
#[derive(Copy, Debug, Clone)]
pub struct PreHashed<I, H = u64> {
hash: H,
inner: I,
}
impl<I, H> PreHashed<I, H> {
/// Create a new [PreHashed] value with the given hash and inner value.
///
/// SAFETY: The hash must be a valid hash of the inner value.
pub fn new(hash: H, inner: I) -> Self {
Self { hash, inner }
}
/// Split the [PreHashed] value into its hash and inner value.
pub fn into_parts(self) -> (H, I) {
(self.hash, self.inner)
}
fn inner(&self) -> &I {
&self.inner
}
}
impl<I: Hash> PreHashed<I, u64> {
/// Create a new [PreHashed] value from a [BuildHasher].
fn new_from_builder<B: BuildHasher>(hasher: &B, inner: I) -> Self {
Self::new(hasher.hash_one(&inner), inner)
}
}
impl<I> Deref for PreHashed<I> {
type Target = I;
fn deref(&self) -> &Self::Target {
self.inner()
}
}
impl<I, H> AsRef<I> for PreHashed<I, H> {
fn as_ref(&self) -> &I {
self.inner()
}
}
impl<I, H: Hash> Hash for PreHashed<I, H> {
fn hash<S: Hasher>(&self, state: &mut S) {
self.hash.hash(state)
}
}
impl<I: Eq, H> Eq for PreHashed<I, H> {}
impl<I: PartialEq, H> PartialEq for PreHashed<I, H> {
// note: we compare the values, not the hashes
fn eq(&self, other: &Self) -> bool {
self.inner.eq(&other.inner)
}
}
impl<I: fmt::Display, H> fmt::Display for PreHashed<I, H> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(f)
}
}
/// An implementer of [Hash] that simply returns the pre-computed hash.
#[derive(Copy, Clone, Debug, Default)]
pub struct PassThroughHash(u64);
impl PassThroughHash {
pub fn new() -> Self {
Default::default()
}
}
impl Hasher for PassThroughHash {
fn write(&mut self, _bytes: &[u8]) {
unimplemented!("do not use")
}
fn write_u64(&mut self, i: u64) {
self.0 = i;
}
fn finish(&self) -> u64 {
self.0
}
}
/// An extension trait for [BuildHasher] that provides the
/// [BuildHasherExt::prehash] method.
pub trait BuildHasherExt: BuildHasher {
type Hash;
fn prehash<T: Hash>(&self, value: T) -> PreHashed<T, Self::Hash>;
}
impl<B: BuildHasher> BuildHasherExt for B {
type Hash = u64;
fn prehash<T: Hash>(&self, value: T) -> PreHashed<T, Self::Hash> {
PreHashed::new_from_builder(self, value)
}
}