#![no_std]
#![cfg_attr(feature = "nightly", feature(doc_auto_cfg))]
#![cfg_attr(feature = "nightly", feature(hasher_prefixfree_extras))]
#![deny(missing_docs)]
#![doc = include_str!("../README.md")]
extern crate self as anyhash;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
use core::{any::type_name, fmt, fmt::Debug, marker::PhantomData};
pub use anyhash_macros::Hash;
pub use anyhash_macros::impl_core_hash;
pub use anyhash_macros::impl_core_hasher;
pub use anyhash_macros::impl_core_build_hasher;
pub use anyhash_macros::impl_hash;
macro_rules! define_writes_for_hasher {
(native endian) => {
define_writes_for_hasher!("hasher.": to_ne_bytes);
};
(little endian) => {
define_writes_for_hasher!("hasher in little endian byte order.": to_le_bytes);
};
(big endian) => {
define_writes_for_hasher!("hasher in big endian byte order.": to_be_bytes);
};
($desc:literal: $c:ident) => {
#[inline]
fn write_u8(&mut self, i: u8) {
self.write(&[i]);
}
define_writes_for_hasher! {
$desc: $c,
u16: write_u16,
u32: write_u32,
u64: write_u64,
u128: write_u128,
usize: write_usize,
}
#[inline]
fn write_i8(&mut self, i: i8) {
self.write(&[i as u8]);
}
define_writes_for_hasher! {
$desc: $c,
i16: write_i16,
i32: write_i32,
i64: write_i64,
i128: write_i128,
isize: write_isize,
}
#[doc = $desc]
#[inline]
fn write_length_prefix(&mut self, len: usize) {
self.write_usize(len);
}
#[doc = $desc]
#[inline]
fn write_str(&mut self, s: &str) {
self.write(s.as_bytes());
self.write_u8(0xff);
}
};
($desc:literal: $c:ident, $($t:ty: $fn:ident),* $(,)*) => {
$(
#[doc = stringify!($t)]
#[doc = $desc]
#[inline]
fn $fn(&mut self, i: $t) {
self.write(&i.$c())
}
)*
};
}
#[cfg(all(test, any(feature = "fnv", feature = "xxh64")))]
macro_rules! test_bytes_hash {
($([$hashfn:ident] $($bs:ident: $hash:expr),* $(,)?)*) => { $(
mod $hashfn {
use super::*;
#[test]
fn test() {
$(
assert_eq!($hashfn($crate::tests::RawBytes(stringify!($bs).as_bytes())), $hash);
)*
}
}
)* };
}
#[cfg(feature = "fnv")]
pub mod fnv;
#[cfg(feature = "spooky")]
pub mod spooky;
#[cfg(feature = "xxh64")]
pub mod xxh64;
#[doc(hidden)]
pub mod internal;
mod impls;
pub trait Hash {
fn hash<H: HasherWrite>(&self, state: &mut H);
#[inline]
fn hash_slice<H: HasherWrite>(data: &[Self], state: &mut H)
where
Self: Sized,
{
for data in data {
data.hash(state);
}
}
}
pub trait Hasher<T>: HasherWrite {
fn finish(&self) -> T;
}
pub trait HasherWrite {
fn write(&mut self, bytes: &[u8]);
define_writes_for_hasher!(native endian);
}
pub trait BuildHasher<T> {
type Hasher: Hasher<T>;
fn build_hasher(&self) -> Self::Hasher;
#[inline]
fn hash_one<U: Hash>(&self, x: U) -> T {
let mut hasher = self.build_hasher();
x.hash(&mut hasher);
hasher.finish()
}
}
pub struct BuildHasherDefault<H>(PhantomData<fn() -> H>);
impl_core_build_hasher!(impl<H> BuildHasherDefault<H>);
impl<H> BuildHasherDefault<H> {
pub const fn new() -> Self {
Self(PhantomData)
}
}
impl<T, H: Hasher<T> + Default> BuildHasher<T> for BuildHasherDefault<H> {
type Hasher = H;
#[inline]
fn build_hasher(&self) -> Self::Hasher {
Self::Hasher::default()
}
}
impl<H> Clone for BuildHasherDefault<H> {
#[inline]
fn clone(&self) -> Self {
Self::new()
}
}
impl<H> Default for BuildHasherDefault<H> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<H> Debug for BuildHasherDefault<H> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BuildHasherDefault<{}>", type_name::<H>())
}
}
pub trait EndianIndependentAlgorithm {}
pub trait EndianIndependentWrites {}
pub trait EndianIndependentHasher<T>:
Hasher<T> + EndianIndependentAlgorithm + EndianIndependentWrites
{
}
impl<T, H> EndianIndependentHasher<T> for H where
H: ?Sized + Hasher<T> + EndianIndependentAlgorithm + EndianIndependentWrites
{
}
pub struct HasherLe<T, H: Hasher<T>>(H, PhantomData<fn() -> T>);
impl_core_hasher!(impl<T, H: Hasher<T>> HasherLe<T, H>);
impl<T, H: Hasher<T> + EndianIndependentAlgorithm> EndianIndependentAlgorithm for HasherLe<T, H> {}
impl<T, H: Hasher<T>> EndianIndependentWrites for HasherLe<T, H> {}
impl<T, H: Hasher<T>> HasherLe<T, H> {
#[inline]
pub const fn new(hasher: H) -> Self {
Self(hasher, PhantomData)
}
}
impl<T, H: Hasher<T>> Hasher<T> for HasherLe<T, H> {
#[inline]
fn finish(&self) -> T {
self.0.finish()
}
}
impl<T, H: Hasher<T>> HasherWrite for HasherLe<T, H> {
#[inline]
fn write(&mut self, bytes: &[u8]) {
self.0.write(bytes);
}
define_writes_for_hasher!(little endian);
}
impl<T, H: Hasher<T> + Debug> Debug for HasherLe<T, H> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<T, H: Hasher<T> + Clone> Clone for HasherLe<T, H> {
#[inline]
fn clone(&self) -> Self {
Self::new(self.0.clone())
}
}
impl<T, H: Hasher<T> + Default> Default for HasherLe<T, H> {
#[inline]
fn default() -> Self {
Self::new(H::default())
}
}
pub struct HasherBe<T, H: Hasher<T>>(H, PhantomData<fn() -> T>);
impl_core_hasher!(impl<T, H: Hasher<T>> HasherBe<T, H>);
impl<T, H: Hasher<T> + EndianIndependentAlgorithm> EndianIndependentAlgorithm for HasherBe<T, H> {}
impl<T, H: Hasher<T>> EndianIndependentWrites for HasherBe<T, H> {}
impl<T, H: Hasher<T>> HasherBe<T, H> {
#[inline]
pub const fn new(hasher: H) -> Self {
Self(hasher, PhantomData)
}
}
impl<T, H: Hasher<T>> Hasher<T> for HasherBe<T, H> {
#[inline]
fn finish(&self) -> T {
self.0.finish()
}
}
impl<T, H: Hasher<T>> HasherWrite for HasherBe<T, H> {
#[inline]
fn write(&mut self, bytes: &[u8]) {
self.0.write(bytes);
}
define_writes_for_hasher!(big endian);
}
impl<T, H: Hasher<T> + Debug> Debug for HasherBe<T, H> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<T, H: Hasher<T> + Clone> Clone for HasherBe<T, H> {
#[inline]
fn clone(&self) -> Self {
Self::new(self.0.clone())
}
}
impl<T, H: Hasher<T> + Default> Default for HasherBe<T, H> {
#[inline]
fn default() -> Self {
Self::new(H::default())
}
}
pub struct HasherLeBuildHasher<BH>(BH);
impl_core_build_hasher!(impl<BH> HasherLeBuildHasher<BH>);
impl<BH> HasherLeBuildHasher<BH> {
#[inline]
pub const fn new(build_hasher: BH) -> Self {
Self(build_hasher)
}
}
impl<T, BH: BuildHasher<T>> BuildHasher<T> for HasherLeBuildHasher<BH> {
type Hasher = HasherLe<T, BH::Hasher>;
#[inline]
fn build_hasher(&self) -> Self::Hasher {
HasherLe::<T, BH::Hasher>::new(self.0.build_hasher())
}
}
impl<BH: Debug> Debug for HasherLeBuildHasher<BH> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<BH: Clone> Clone for HasherLeBuildHasher<BH> {
#[inline]
fn clone(&self) -> Self {
Self::new(self.0.clone())
}
}
impl<BH: Default> Default for HasherLeBuildHasher<BH> {
#[inline]
fn default() -> Self {
Self::new(BH::default())
}
}
pub struct HasherBeBuildHasher<BH>(BH);
impl_core_build_hasher!(impl<BH> HasherBeBuildHasher<BH>);
impl<BH> HasherBeBuildHasher<BH> {
#[inline]
pub const fn new(build_hasher: BH) -> Self {
Self(build_hasher)
}
}
impl<T, BH: BuildHasher<T>> BuildHasher<T> for HasherBeBuildHasher<BH> {
type Hasher = HasherBe<T, BH::Hasher>;
#[inline]
fn build_hasher(&self) -> Self::Hasher {
HasherBe::<T, BH::Hasher>::new(self.0.build_hasher())
}
}
impl<BH: Debug> Debug for HasherBeBuildHasher<BH> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<BH: Clone> Clone for HasherBeBuildHasher<BH> {
#[inline]
fn clone(&self) -> Self {
Self::new(self.0.clone())
}
}
impl<BH: Default> Default for HasherBeBuildHasher<BH> {
#[inline]
fn default() -> Self {
Self::new(BH::default())
}
}
#[cfg(test)]
mod tests {
use super::*;
pub struct RawBytes<'a>(pub &'a [u8]);
impl Hash for RawBytes<'_> {
#[inline]
fn hash<H: HasherWrite>(&self, state: &mut H) {
Hash::hash_slice(self.0, state)
}
}
}