use std::fmt;
use std::hash::Hasher;
#[cfg(test)]
mod tests;
pub trait ExtendedHasher: Hasher {
type Hash;
fn short_write<const LEN: usize>(&mut self, bytes: [u8; LEN]) {
self.write(&bytes);
}
fn finish(self) -> Self::Hash;
}
#[must_use]
#[derive(Clone)]
pub struct StableHasher<H: ExtendedHasher> {
state: H,
}
pub trait FromStableHash: Sized {
type Hash;
fn from(hash: Self::Hash) -> Self;
}
impl<H: ExtendedHasher + Default> StableHasher<H> {
#[inline]
pub fn new() -> Self {
Default::default()
}
}
impl<H: ExtendedHasher + Default> Default for StableHasher<H> {
#[inline]
fn default() -> Self {
StableHasher {
state: Default::default(),
}
}
}
impl<H: ExtendedHasher> StableHasher<H> {
#[inline]
pub fn with_hasher(state: H) -> Self {
StableHasher { state }
}
#[inline]
#[must_use]
pub fn finish<W: FromStableHash<Hash = H::Hash>>(self) -> W {
W::from(self.state.finish())
}
}
impl<H: ExtendedHasher + fmt::Debug> fmt::Debug for StableHasher<H> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.state)
}
}
impl<H: ExtendedHasher> Hasher for StableHasher<H> {
fn finish(&self) -> u64 {
Hasher::finish(&self.state)
}
#[inline]
fn write(&mut self, bytes: &[u8]) {
self.state.write(bytes);
}
#[cfg(feature = "nightly")]
#[inline]
fn write_str(&mut self, s: &str) {
self.state.write_str(s);
}
#[cfg(feature = "nightly")]
#[inline]
fn write_length_prefix(&mut self, len: usize) {
self.write_usize(len);
}
#[inline]
fn write_u8(&mut self, i: u8) {
self.state.write_u8(i);
}
#[inline]
fn write_u16(&mut self, i: u16) {
self.state.short_write(i.to_le_bytes());
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.state.short_write(i.to_le_bytes());
}
#[inline]
fn write_u64(&mut self, i: u64) {
self.state.short_write(i.to_le_bytes());
}
#[inline]
fn write_u128(&mut self, i: u128) {
self.write_u64(i as u64);
self.write_u64((i >> 64) as u64);
}
#[inline]
fn write_usize(&mut self, i: usize) {
self.state.short_write((i as u64).to_le_bytes());
}
#[inline]
fn write_i8(&mut self, i: i8) {
self.state.write_i8(i);
}
#[inline]
fn write_i16(&mut self, i: i16) {
self.state.short_write((i as u16).to_le_bytes());
}
#[inline]
fn write_i32(&mut self, i: i32) {
self.state.short_write((i as u32).to_le_bytes());
}
#[inline]
fn write_i64(&mut self, i: i64) {
self.state.short_write((i as u64).to_le_bytes());
}
#[inline]
fn write_i128(&mut self, i: i128) {
self.state.write(&(i as u128).to_le_bytes());
}
#[inline]
fn write_isize(&mut self, i: isize) {
let value = i as u64;
#[cold]
#[inline(never)]
fn hash_value<H: ExtendedHasher>(state: &mut H, value: u64) {
state.write_u8(0xFF);
state.short_write(value.to_le_bytes());
}
if value < 0xFF {
self.state.write_u8(value as u8);
} else {
hash_value(&mut self.state, value);
}
}
}