use core::hash::{BuildHasher, Hash};
use core::marker::PhantomData;
pub trait HashKey<Q: ?Sized> {
fn hash_key(&self, key: &Q) -> usize;
}
pub trait EqKey<A: ?Sized, B: ?Sized> {
fn eq_key(&self, a: &A, b: &B) -> bool;
}
#[derive(Clone, Default)]
pub struct StdHash<B = std::collections::hash_map::RandomState> {
build: B,
}
impl<B: BuildHasher> StdHash<B> {
pub fn with_hasher(build: B) -> Self {
Self { build }
}
}
impl<B: BuildHasher, Q: Hash + ?Sized> HashKey<Q> for StdHash<B> {
#[inline]
fn hash_key(&self, key: &Q) -> usize {
self.build.hash_one(key) as usize
}
}
#[derive(Clone, Default)]
pub struct StdEq;
impl<A, B> EqKey<A, B> for StdEq
where
A: PartialEq<B> + ?Sized,
B: ?Sized,
{
#[inline]
fn eq_key(&self, a: &A, b: &B) -> bool {
a == b
}
}
#[derive(Clone)]
pub struct FnHash<F> {
f: F,
_marker: PhantomData<fn()>,
}
impl<F> FnHash<F> {
pub fn new(f: F) -> Self {
Self {
f,
_marker: PhantomData,
}
}
}
impl<F, Q> HashKey<Q> for FnHash<F>
where
F: Fn(&Q) -> usize,
Q: ?Sized,
{
#[inline]
fn hash_key(&self, key: &Q) -> usize {
(self.f)(key)
}
}