use std::any;
use std::cmp::Ordering;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData;
use std::ops::Deref;
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Key {
hash: u64,
s: &'static str,
}
impl PartialOrd for Key {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Key {
fn cmp(&self, other: &Self) -> Ordering {
self.s.cmp(other.s)
}
}
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for Key {
fn hash<H: Hasher>(&self, state: &mut H) {
self.hash.hash(state);
}
}
impl Deref for Key {
type Target = str;
fn deref(&self) -> &str {
self.s
}
}
impl Key {
const fn hash(s: &str) -> u64 {
let mut hash = 0xcbf29ce484222325;
let mut i = 0;
while i < s.as_bytes().len() {
let b = s.as_bytes()[i];
hash ^= b as u64;
hash = hash.wrapping_mul(0x100000001b3);
i += 1;
}
hash
}
pub const fn new(s: &'static str) -> Key {
let hash = Self::hash(s);
Key::new_unchecked(hash, s)
}
pub const fn new_unchecked(hash: u64, s: &'static str) -> Key {
Key { hash, s }
}
pub const fn for_type_name<T>() -> Key {
Key {
hash: MeasureKeyForType::<T>::KEY.hash,
s: MeasureKeyForType::<T>::KEY.s,
}
}
}
struct MeasureKeyForType<T>(PhantomData<T>);
impl<T> MeasureKeyForType<T> {
pub const KEY: Key = Key::new(any::type_name::<T>());
}