use std::any::{TypeId, type_name};
use std::collections::HashMap;
use std::hash::{BuildHasherDefault, Hash, Hasher};
#[derive(Clone, Copy, Debug)]
pub(crate) struct Key {
pub(crate) id: TypeId,
pub(crate) name: &'static str,
}
impl Key {
pub(crate) fn of<T: ?Sized + 'static>() -> Self {
Self {
id: TypeId::of::<T>(),
name: type_name::<T>(),
}
}
}
impl PartialEq for Key {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for Key {}
impl Hash for Key {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
pub(crate) struct TypeIdHasher(u64);
impl Default for TypeIdHasher {
fn default() -> Self {
Self(0xcbf2_9ce4_8422_2325)
}
}
impl Hasher for TypeIdHasher {
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, bytes: &[u8]) {
for &byte in bytes {
self.0 ^= u64::from(byte);
self.0 = self.0.wrapping_mul(0x0100_0000_01b3);
}
}
fn write_u64(&mut self, n: u64) {
self.0 = n;
}
}
pub(crate) type KeyMap<V> = HashMap<Key, V, BuildHasherDefault<TypeIdHasher>>;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Dependency {
key: Key,
all: bool,
}
impl Dependency {
pub fn on<T: ?Sized + 'static>() -> Self {
Self {
key: Key::of::<T>(),
all: false,
}
}
pub fn all<T: ?Sized + 'static>() -> Self {
Self {
key: Key::of::<T>(),
all: true,
}
}
pub fn type_name(&self) -> &'static str {
self.key.name
}
pub(crate) fn key(&self) -> Key {
self.key
}
pub(crate) fn is_all(&self) -> bool {
self.all
}
}