use std::any::Any;
use std::cmp::{Ord, PartialOrd};
use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use siphasher::sip128::{Hasher128, SipHasher13};
#[inline]
pub fn hash<T: Hash>(value: &T) -> u128 {
let mut state = SipHasher13::new();
value.hash(&mut state);
state.finish128().as_u128()
}
#[inline]
pub fn hash_any<T: Hash + 'static>(item: &T) -> u128 {
let mut state = SipHasher13::new();
item.type_id().hash(&mut state);
item.hash(&mut state);
state.finish128().as_u128()
}
#[derive(Copy, Clone)]
pub struct Prehashed<T: ?Sized> {
hash: u128,
item: T,
}
impl<T: Hash + 'static> Prehashed<T> {
#[inline]
pub fn new(item: T) -> Self {
Self { hash: hash_any(&item), item }
}
#[inline]
pub fn into_inner(self) -> T {
self.item
}
#[inline]
pub fn update<F, U>(&mut self, f: F) -> U
where
F: FnOnce(&mut T) -> U,
{
let output = f(&mut self.item);
self.hash = hash_any(&self.item);
output
}
}
impl<T: ?Sized> Deref for Prehashed<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.item
}
}
impl<T: Hash + 'static> From<T> for Prehashed<T> {
#[inline]
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: ?Sized> Hash for Prehashed<T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u128(self.hash);
}
}
impl<T: Debug + ?Sized> Debug for Prehashed<T> {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.item.fmt(f)
}
}
impl<T: Default + Hash + 'static> Default for Prehashed<T> {
#[inline]
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: ?Sized> Eq for Prehashed<T> {}
impl<T: ?Sized> PartialEq for Prehashed<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.hash == other.hash
}
}
impl<T: Ord + ?Sized> Ord for Prehashed<T> {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.item.cmp(&other.item)
}
}
impl<T: PartialOrd + ?Sized> PartialOrd for Prehashed<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.item.partial_cmp(&other.item)
}
}