#[cfg(feature = "gxhash")]
use gxhash::GxBuildHasher;
use crate::KeyT;
use std::fmt::Debug;
pub trait Hash: Copy + Debug + Default + Send + Sync + Eq + rdst::RadixKey {
fn low(&self) -> u64;
fn high(&self) -> u64;
}
impl Hash for u64 {
fn low(&self) -> u64 {
*self
}
fn high(&self) -> u64 {
*self
}
}
impl Hash for u128 {
fn low(&self) -> u64 {
*self as u64
}
fn high(&self) -> u64 {
(*self >> 64) as u64
}
}
pub trait KeyHasher<Key: ?Sized>: Clone + Sync {
type H: Hash;
fn hash(x: &Key, seed: u64) -> Self::H;
}
impl<Key: KeyT + ?Sized, H: core::hash::Hasher + Default + Clone + Sync> KeyHasher<Key> for H {
type H = u64;
#[inline(always)]
fn hash(x: &Key, seed: u64) -> u64 {
let mut hasher = H::default();
Key::hash(x, &mut hasher);
hasher.finish() ^ seed
}
}
pub type FastIntHash = fxhash::FxHasher64;
pub type FxHash = fxhash::FxHasher64;
pub type Xxh3 = xxhash_rust::xxh3::Xxh3Default;
#[cfg(feature = "gxhash")]
pub type Gx = gxhash::GxHasher;
#[cfg(feature = "gxhash")]
pub type StringHash = Gx;
#[cfg(feature = "gxhash")]
pub type StringHash128 = Gx128;
#[cfg_attr(feature = "epserde", derive(epserde::prelude::Epserde))]
#[derive(Clone)]
pub struct Xxh3_128;
impl<Key: KeyT + ?Sized> KeyHasher<Key> for Xxh3_128 {
type H = u128;
#[inline(always)]
fn hash(x: &Key, seed: u64) -> u128 {
let mut hasher = xxhash_rust::xxh3::Xxh3Default::default();
x.hash(&mut hasher);
hasher.digest128() ^ (seed as u128 | (seed as u128) << 64)
}
}
#[cfg(feature = "gxhash")]
#[cfg_attr(feature = "epserde", derive(epserde::prelude::Epserde))]
#[derive(Clone)]
pub struct Gx128;
#[cfg(feature = "gxhash")]
impl<Key: KeyT + ?Sized> KeyHasher<Key> for Gx128 {
type H = u128;
#[inline(always)]
fn hash(x: &Key, seed: u64) -> u128 {
use std::hash::BuildHasher;
let mut hasher = GxBuildHasher::with_seed(seed as i64).build_hasher();
x.hash(&mut hasher);
hasher.finish_u128()
}
}
#[cfg_attr(feature = "epserde", derive(epserde::prelude::Epserde))]
#[derive(Clone)]
pub struct StrongerIntHash;
pub const C: u64 = 0x517cc1b727220a95;
#[cfg_attr(feature = "epserde", derive(epserde::prelude::Epserde))]
#[derive(Clone)]
pub struct NoHash;
#[cfg_attr(feature = "epserde", derive(epserde::prelude::Epserde))]
#[derive(Clone)]
pub struct Xxh3Int;
#[cfg(feature = "gxhash")]
#[cfg_attr(feature = "epserde", derive(epserde::prelude::Epserde))]
#[derive(Clone)]
pub struct GxInt;
macro_rules! int_hashers {
($($t:ty),*) => {
$(
impl KeyHasher<$t> for NoHash {
type H = u64;
#[inline(always)]
fn hash(x: &$t, seed: u64) -> u64 {
*x as u64 ^ seed
}
}
impl KeyHasher<$t> for StrongerIntHash {
type H = u64;
#[inline(always)]
fn hash(x: &$t, seed: u64) -> u64 {
let r = (*x as u64 ^ seed) as u128 * C as u128;
let low = r as u64;
let high = (r >> 64) as u64;
(low ^ high).wrapping_mul(C)
}
}
impl KeyHasher<$t> for Xxh3Int {
type H = u64;
#[inline(always)]
fn hash(x: &$t, seed: u64) -> u64 {
xxhash_rust::xxh3::xxh3_64_with_seed(&(*x as u64).to_le_bytes(), seed)
}
}
#[cfg(feature = "gxhash")]
impl KeyHasher<$t> for GxInt {
type H = u64;
#[inline(always)]
fn hash(x: &$t, seed: u64) -> u64 {
gxhash::gxhash64(&(*x as u64).to_le_bytes(), seed as i64)
}
}
)*
};
}
int_hashers!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);