use std::hash::Hasher;
macro_rules! write_impl {
(($self:ident, $i:ident) $body:block; $($name:ident($type:ty),)+) => {
$(
#[inline(always)]
fn $name(&mut $self, $i: $type) $body
)*
}
}
#[derive(Default)]
pub struct DummyHasher {
hash: u64,
}
impl Hasher for DummyHasher {
#[inline]
fn finish(&self) -> u64 {
self.hash
}
#[inline(always)]
fn write(&mut self, bytes: &[u8]) {
self.hash = u64::from_ne_bytes(bytes.try_into().unwrap());
}
write_impl!(
(self, i) {
self.hash = self.hash | i as u64;
};
write_u8(u8),
write_u16(u16),
write_u32(u32),
write_u64(u64),
write_u128(u128),
write_usize(usize),
);
}
#[derive(Default)]
pub struct InterleaveHasher {
hash: u64,
}
impl Hasher for InterleaveHasher {
#[inline]
fn finish(&self) -> u64 {
self.hash
}
#[inline(always)]
fn write(&mut self, _bytes: &[u8]) {
panic!("No implementation");
}
write_impl!(
(self, i) {
self.hash = self.hash << 32 | i as u64;
};
write_u8(u8),
write_u16(u16),
write_u32(u32),
write_u64(u64),
write_u128(u128),
write_usize(usize),
);
}
#[cfg(feature = "morton")]
pub use morton::*;
#[cfg(feature = "morton")]
mod morton {
use super::*;
#[derive(Default)]
pub struct MortonHasher {
hash: [u32; 2],
i: usize,
}
impl Hasher for MortonHasher {
#[inline]
fn finish(&self) -> u64 {
morton_encoding::morton_encode(self.hash)
}
#[inline(always)]
fn write(&mut self, _bytes: &[u8]) {
panic!("No implementation");
}
write_impl!(
(self, i) {
self.hash[self.i] = i as u32;
self.i += 1;
};
write_u8(u8),
write_u16(u16),
write_u32(u32),
write_u64(u64),
write_u128(u128),
write_usize(usize),
);
}
}