anyhash 0.1.3

Traits and utilities for making hashes of any type
Documentation
use crate::{Hasher, HasherWrite};

macro_rules! impl_hasher_core_fwd_writes {
    ([] $($t:ty: $fn:ident),* $(,)?) => { $(
        #[inline(always)]
        fn $fn(&mut self, i: $t) { H::$fn(self.0, i); }
    )* };
    ([&mut] $($t:ty: $fn:ident),* $(,)?) => { $(
        #[inline(always)]
        fn $fn(&mut self, i: $t) { H::$fn(&mut self.0, i); }
    )* };
}

macro_rules! impl_hasher_core_fwd {
    ($($ref:tt)*) => {
        #[inline(always)]
        fn write(&mut self, bytes: &[u8]) {
            H::write($($ref)* self.0, bytes)
        }

        #[inline(always)]
        fn write_u8(&mut self, i: u8) {
            H::write_u8($($ref)* self.0, i)
        }

        #[inline(always)]
        fn write_i8(&mut self, i: i8) {
            H::write_i8($($ref)* self.0, i)
        }

        impl_hasher_core_fwd_writes! {
            [$($ref)*]
            u16: write_u16,
            u32: write_u32,
            u64: write_u64,
            u128: write_u128,
            usize: write_usize,
            i16: write_i16,
            i32: write_i32,
            i64: write_i64,
            i128: write_i128,
            isize: write_isize
        }

        #[cfg(feature = "nightly")]
        #[inline(always)]
        fn write_length_prefix(&mut self, len: usize) {
            H::write_length_prefix($($ref)* self.0, len)
        }

        #[cfg(feature = "nightly")]
        #[inline(always)]
        fn write_str(&mut self, s: &str) {
            H::write_str($($ref)* self.0, s)
        }
    };
}

#[repr(transparent)]
pub struct WrapHasherWriteForCore<'a, H: HasherWrite>(&'a mut H);

impl<'a, H: HasherWrite> WrapHasherWriteForCore<'a, H> {
    #[inline(always)]
    pub fn new(hasher: &'a mut H) -> Self {
        Self(hasher)
    }
}

impl<H: HasherWrite> core::hash::Hasher for WrapHasherWriteForCore<'_, H> {
    #[inline(always)]
    fn finish(&self) -> u64 {
        panic!("`core::hash::Hasher::finish` called while calculating generic hash");
    }

    impl_hasher_core_fwd!();
}

#[repr(transparent)]
pub struct WrapHasherU64ForCore<H: Hasher<u64>>(H);

impl<H: Hasher<u64>> WrapHasherU64ForCore<H> {
    #[inline(always)]
    pub const fn new(hasher: H) -> Self {
        Self(hasher)
    }
}

impl<H: Hasher<u64>> ::core::hash::Hasher for WrapHasherU64ForCore<H> {
    #[inline(always)]
    fn finish(&self) -> u64 {
        H::finish(&self.0)
    }

    impl_hasher_core_fwd!(&mut);
}

#[repr(transparent)]
pub struct WrapCoreForHasherU64<'a, H: core::hash::Hasher>(&'a mut H);

impl<'a, H: core::hash::Hasher> WrapCoreForHasherU64<'a, H> {
    #[inline(always)]
    pub fn new(hasher: &'a mut H) -> Self {
        Self(hasher)
    }
}

impl<H: ::core::hash::Hasher> Hasher<u64> for WrapCoreForHasherU64<'_, H> {
    #[inline(always)]
    fn finish(&self) -> u64 {
        H::finish(self.0)
    }
}

impl<H: ::core::hash::Hasher> HasherWrite for WrapCoreForHasherU64<'_, H> {
    impl_hasher_core_fwd!();
}

#[cfg(feature = "bytemuck")]
pub(crate) use bm::*;

#[cfg(feature = "bytemuck")]
pub(crate) mod bm {
    use bytemuck::{cast_mut, cast_ref, Pod};

    pub(crate) trait ConstValue: Copy + Default {
        const VALUE: usize;
        type ArrayU64: Pod + Default;
        type Array2xU32: Pod;
        type Array4xU16: Pod;
        type Array8xU8: Pod;
    }

    macro_rules! define_const_values {
        ($($name:ident = $value:expr),* $(,)?) => { $(
            #[derive(Clone, Copy, Default)]
            pub(crate) struct $name;

            impl ConstValue for $name {
                const VALUE: usize = $value;
                type ArrayU64 = [u64; $value];
                type Array2xU32 = [u32; 2 * $value];
                type Array4xU16 = [u16; 4 * $value];
                type Array8xU8 = [u8; 8 * $value];
            }

            impl From<$name> for usize {
                #[inline]
                fn from(_: $name) -> Self {
                    $name::VALUE
                }
            }
        )* };
    }

    define_const_values! {
        N4 = 4,
        N24 = 24,
    }

    #[derive(Clone, Copy, Default)]
    #[repr(transparent)]
    pub(crate) struct Buffer<N: ConstValue>(N::ArrayU64);

    #[allow(dead_code)]
    impl<N: ConstValue> Buffer<N> {
        #[inline]
        pub fn new() -> Self {
            Self(N::ArrayU64::default())
        }

        #[inline]
        pub fn as_bytes(&self) -> &N::Array8xU8 {
            cast_ref(&self.0)
        }

        #[inline]
        pub fn as_bytes_mut(&mut self) -> &mut N::Array8xU8 {
            cast_mut(&mut self.0)
        }

        #[inline]
        pub fn as_u16s(&self) -> &N::Array4xU16 {
            cast_ref(&self.0)
        }

        #[inline]
        pub fn as_u16s_mut(&mut self) -> &mut N::Array4xU16 {
            cast_mut(&mut self.0)
        }

        #[inline]
        pub fn as_u32s(&self) -> &N::Array2xU32 {
            cast_ref(&self.0)
        }

        #[inline]
        pub fn as_u32s_mut(&mut self) -> &mut N::Array2xU32 {
            cast_mut(&mut self.0)
        }

        #[inline]
        pub fn as_u64s(&self) -> &N::ArrayU64 {
            &self.0
        }

        #[inline]
        pub fn as_u64s_mut(&mut self) -> &mut N::ArrayU64 {
            &mut self.0
        }
    }
}