use std::hash::Hasher;
use std::os::raw::c_void;
use ffi;
use hasher::{FastHash, FastHasher, HasherExt, StreamHasher};
pub struct Hash32;
impl FastHash for Hash32 {
type Hash = u32;
type Seed = u32;
#[inline(always)]
fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u32) -> u32 {
let mut hash1 = u64::from(seed);
let mut hash2 = u64::from(seed);
unsafe {
ffi::SpookyHasherHash(
bytes.as_ref().as_ptr() as *const c_void,
bytes.as_ref().len(),
&mut hash1,
&mut hash2,
);
}
hash1 as u32
}
}
impl_hasher!(
#[doc = r#"
# Example
```
use std::hash::Hasher;
use fasthash::{spooky::Hasher32, FastHasher};
let mut h = Hasher32::new();
h.write(b"hello");
assert_eq!(h.finish(), 3907268544);
h.write(b"world");
assert_eq!(h.finish(), 3874077464);
```
"#]
Hasher32,
Hash32
);
pub struct Hash64;
impl FastHash for Hash64 {
type Hash = u64;
type Seed = u64;
#[inline(always)]
fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u64) -> u64 {
let mut hash1 = seed;
let mut hash2 = seed;
unsafe {
ffi::SpookyHasherHash(
bytes.as_ref().as_ptr() as *const c_void,
bytes.as_ref().len(),
&mut hash1,
&mut hash2,
);
}
hash1
}
}
impl_hasher!(
#[doc = r#"
# Example
```
use std::hash::Hasher;
use fasthash::{spooky::Hasher64, FastHasher};
let mut h = Hasher64::new();
h.write(b"hello");
assert_eq!(h.finish(), 6105954949053820864);
h.write(b"world");
assert_eq!(h.finish(), 18412934266828208920);
```
"#]
Hasher64,
Hash64
);
pub struct Hash128;
impl FastHash for Hash128 {
type Hash = u128;
type Seed = u128;
#[inline(always)]
fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u128) -> u128 {
let mut hi = (seed >> 64) as u64;
let mut lo = seed as u64;
unsafe {
ffi::SpookyHasherHash(
bytes.as_ref().as_ptr() as *const c_void,
bytes.as_ref().len(),
&mut hi,
&mut lo,
);
}
u128::from(hi).wrapping_shl(64) + u128::from(lo)
}
}
pub struct Hasher128(*mut c_void);
impl Default for Hasher128 {
fn default() -> Self {
Self::new()
}
}
impl Drop for Hasher128 {
#[inline(always)]
fn drop(&mut self) {
unsafe { ffi::SpookyHasherFree(self.0) }
}
}
impl Hasher for Hasher128 {
#[inline(always)]
fn finish(&self) -> u64 {
self.finish_ext() as u64
}
#[inline(always)]
fn write(&mut self, bytes: &[u8]) {
unsafe { ffi::SpookyHasherUpdate(self.0, bytes.as_ptr() as *const c_void, bytes.len()) }
}
}
impl HasherExt for Hasher128 {
#[inline(always)]
fn finish_ext(&self) -> u128 {
let mut hi = 0_u64;
let mut lo = 0_u64;
unsafe {
ffi::SpookyHasherFinal(self.0, &mut hi, &mut lo);
}
u128::from(hi).wrapping_shl(64) + u128::from(lo)
}
}
impl FastHasher for Hasher128 {
type Seed = (u64, u64);
#[inline(always)]
fn with_seed(seed: Self::Seed) -> Hasher128 {
let h = unsafe { ffi::SpookyHasherNew() };
unsafe {
ffi::SpookyHasherInit(h, seed.0, seed.1);
}
Hasher128(h)
}
}
impl StreamHasher for Hasher128 {}
impl_fasthash!(Hasher128, Hash128);
#[inline(always)]
pub fn hash32<T: AsRef<[u8]>>(v: T) -> u32 {
Hash32::hash(v)
}
#[inline(always)]
pub fn hash32_with_seed<T: AsRef<[u8]>>(v: T, seed: u32) -> u32 {
Hash32::hash_with_seed(v, seed)
}
#[inline(always)]
pub fn hash64<T: AsRef<[u8]>>(v: T) -> u64 {
Hash64::hash(v)
}
#[inline(always)]
pub fn hash64_with_seed<T: AsRef<[u8]>>(v: T, seed: u64) -> u64 {
Hash64::hash_with_seed(v, seed)
}
#[inline(always)]
pub fn hash128<T: AsRef<[u8]>>(v: T) -> u128 {
Hash128::hash(v)
}
#[inline(always)]
pub fn hash128_with_seed<T: AsRef<[u8]>>(v: T, seed: u128) -> u128 {
Hash128::hash_with_seed(v, seed)
}