use crate::hasher::FastHash;
pub mod t1ha2 {
use std::hash::Hasher;
use std::mem;
use std::ptr;
use crate::hasher::{FastHash, FastHasher, HasherExt, StreamHasher};
#[derive(Clone, Default)]
pub struct Hash64AtOnce;
impl FastHash for Hash64AtOnce {
type Hash = u64;
type Seed = u64;
#[inline(always)]
fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u64) -> u64 {
unsafe {
ffi::t1ha2_atonce(
bytes.as_ref().as_ptr() as *const _,
bytes.as_ref().len(),
seed,
)
}
}
}
#[derive(Clone, Default)]
pub struct Hash128AtOnce;
impl FastHash for Hash128AtOnce {
type Hash = u128;
type Seed = u64;
#[inline(always)]
fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u64) -> u128 {
let mut hi = 0;
let lo = unsafe {
ffi::t1ha2_atonce128(
&mut hi,
bytes.as_ref().as_ptr() as *const _,
bytes.as_ref().len(),
seed,
)
};
u128::from(hi).wrapping_shl(64) + u128::from(lo)
}
}
#[derive(Clone)]
pub struct Hasher128(ptr::NonNull<ffi::t1ha_context_t>);
impl Default for Hasher128 {
fn default() -> Self {
Self::new()
}
}
impl Drop for Hasher128 {
fn drop(&mut self) {
unsafe { mem::drop(Box::from_raw(self.0.as_ptr())) }
}
}
impl Hasher for Hasher128 {
#[inline(always)]
fn write(&mut self, bytes: &[u8]) {
unsafe {
ffi::t1ha2_update(self.0.as_ptr(), bytes.as_ptr() as *const _, bytes.len());
}
}
#[inline(always)]
fn finish(&self) -> u64 {
unsafe { ffi::t1ha2_final(self.0.as_ptr(), ptr::null_mut()) }
}
}
impl HasherExt for Hasher128 {
fn finish_ext(&self) -> u128 {
let mut hi = 0;
let lo = unsafe { ffi::t1ha2_final(self.0.as_ptr(), &mut hi) };
(u128::from(hi) << 64) + u128::from(lo)
}
}
impl FastHasher for Hasher128 {
type Seed = (u64, u64);
type Output = u128;
#[inline(always)]
fn with_seed(seed: (u64, u64)) -> Self {
unsafe {
let ctx: ptr::NonNull<ffi::t1ha_context_t> =
ptr::NonNull::new_unchecked(Box::into_raw(Box::new(mem::zeroed())));
ffi::t1ha2_init(ctx.as_ptr(), seed.0, seed.1);
Hasher128(ctx)
}
}
}
impl StreamHasher for Hasher128 {}
impl_build_hasher!(Hasher128, Hash64AtOnce);
impl_build_hasher!(Hasher128, Hash128AtOnce);
}
pub mod t1ha1 {
use crate::hasher::FastHash;
cfg_if! {
if #[cfg(target_endian = "little")] {
pub use self::{Hasher64Le as Hasher64, Hash64Le as Hash64};
} else {
pub use self::{Hasher64Be as Hasher64, Hash64Be as Hash64};
}
}
#[derive(Clone, Default)]
pub struct Hash64Le;
impl FastHash for Hash64Le {
type Hash = u64;
type Seed = u64;
#[inline(always)]
fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u64) -> u64 {
unsafe {
ffi::t1ha1_le(
bytes.as_ref().as_ptr() as *const _,
bytes.as_ref().len(),
seed,
)
}
}
}
trivial_hasher! {
Hasher64Le(Hash64Le) -> u64
}
#[derive(Clone, Default)]
pub struct Hash64Be;
impl FastHash for Hash64Be {
type Hash = u64;
type Seed = u64;
#[inline(always)]
fn hash_with_seed<T: AsRef<[u8]>>(bytes: T, seed: u64) -> u64 {
unsafe {
ffi::t1ha1_be(
bytes.as_ref().as_ptr() as *const _,
bytes.as_ref().len(),
seed,
)
}
}
}
trivial_hasher! {
Hasher64Be(Hash64Be) -> u64
}
}
pub mod t1ha0 {
use crate::hasher::FastHash;
lazy_static::lazy_static! {
static ref T1HA0: ffi::t1ha0_function_t = unsafe { ffi::t1ha0_resolve() };
}
#[derive(Clone, Default)]
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 {
unsafe {
T1HA0.unwrap_or(ffi::t1ha0_64)(
bytes.as_ref().as_ptr() as *const _,
bytes.as_ref().len(),
seed,
)
}
}
}
trivial_hasher! {
Hasher64(Hash64) -> u64
}
}
#[inline(always)]
pub fn hash64<T: AsRef<[u8]>>(v: T) -> u64 {
t1ha2::Hash64AtOnce::hash(v)
}
#[inline(always)]
pub fn hash64_with_seed<T: AsRef<[u8]>>(v: T, seed: u64) -> u64 {
t1ha2::Hash64AtOnce::hash_with_seed(v, seed)
}