use rand::Rng;
#[cfg(feature = "serde")]
use serde_crate::{Deserialize, Serialize};
use siphasher::sip::SipHasher;
use std::borrow::Borrow;
use std::hash::BuildHasher;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::{cmp, fmt};
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(crate = "serde_crate")
)]
#[derive(Clone, Copy)]
pub struct SipHasherBuilder {
k0: u64,
k1: u64,
hasher: SipHasher,
}
impl SipHasherBuilder {
pub fn from_entropy() -> Self {
let mut rng = rand::thread_rng();
Self::from_seed(rng.gen(), rng.gen())
}
pub fn from_seed(k0: u64, k1: u64) -> Self {
SipHasherBuilder {
k0,
k1,
hasher: SipHasher::new_with_keys(k0, k1),
}
}
}
impl fmt::Debug for SipHasherBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SipHasherBuilder")
.field("k0", &self.k0)
.field("k1", &self.k1)
.finish()
}
}
impl cmp::PartialEq for SipHasherBuilder {
fn eq(&self, other: &SipHasherBuilder) -> bool {
self.k0 == other.k0 && self.k1 == other.k1
}
}
impl BuildHasher for SipHasherBuilder {
type Hasher = SipHasher;
#[inline]
fn build_hasher(&self) -> SipHasher {
self.hasher
}
}
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(crate = "serde_crate")
)]
#[derive(Debug, PartialEq)]
pub struct DoubleHasher<T, B = SipHasherBuilder> {
hash_builders: [B; 2],
_marker: PhantomData<T>,
}
impl<T> DoubleHasher<T> {
pub fn new() -> Self {
Self::with_hashers([
SipHasherBuilder::from_entropy(),
SipHasherBuilder::from_entropy(),
])
}
}
impl<T, B> DoubleHasher<T, B>
where
B: BuildHasher,
{
pub fn with_hashers(hash_builders: [B; 2]) -> Self {
DoubleHasher {
hash_builders,
_marker: PhantomData,
}
}
pub fn hash<U>(&self, item: &U) -> HashIter
where
T: Borrow<U>,
U: Hash + ?Sized,
{
let mut hasher_1 = self.hash_builders[0].build_hasher();
let mut hasher_2 = self.hash_builders[1].build_hasher();
item.hash(&mut hasher_1);
item.hash(&mut hasher_2);
HashIter {
a: hasher_1.finish(),
b: hasher_2.finish(),
c: 0,
}
}
pub fn hashers(&self) -> &[B; 2] {
&self.hash_builders
}
}
#[derive(Clone, Copy)]
pub struct HashIter {
a: u64,
b: u64,
c: u64,
}
impl Iterator for HashIter {
type Item = u64;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let ret = self.a;
self.a = self.a.wrapping_add(self.b);
self.b = self.b.wrapping_add(self.c);
self.c += 1;
Some(ret)
}
}
#[cfg(test)]
pub mod tests {
use super::SipHasherBuilder;
use siphasher::sip::SipHasher;
pub fn hash_builder_1() -> SipHasherBuilder {
SipHasherBuilder {
k0: 0,
k1: 0,
hasher: SipHasher::new_with_keys(0, 0),
}
}
pub fn hash_builder_2() -> SipHasherBuilder {
SipHasherBuilder {
k0: 1,
k1: 1,
hasher: SipHasher::new_with_keys(1, 1),
}
}
}