use std::any::TypeId;
use std::marker::PhantomData;
use std::sync::Arc;
#[derive(Clone)]
pub(crate) enum Qualifier {
Static(&'static str),
Dynamic(Arc<str>),
}
impl Qualifier {
fn as_str(&self) -> &str {
match self {
Qualifier::Static(s) => s,
Qualifier::Dynamic(s) => s,
}
}
}
impl std::fmt::Debug for Qualifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self.as_str(), f)
}
}
impl PartialEq for Qualifier {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl Eq for Qualifier {}
impl std::hash::Hash for Qualifier {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypeKey {
type_id: TypeId,
qualifier: Option<Qualifier>,
}
impl TypeKey {
pub fn of<T: ?Sized + 'static>() -> Self {
Self {
type_id: TypeId::of::<T>(),
qualifier: None,
}
}
pub fn keyed<T: ?Sized + 'static>(qualifier: &'static str) -> Self {
Self {
type_id: TypeId::of::<T>(),
qualifier: Some(Qualifier::Static(qualifier)),
}
}
pub fn keyed_dynamic<T: ?Sized + 'static>(name: impl Into<Arc<str>>) -> Self {
Self {
type_id: TypeId::of::<T>(),
qualifier: Some(Qualifier::Dynamic(name.into())),
}
}
pub fn describe(&self) -> String {
match &self.qualifier {
Some(q) => format!("{}#{}", self.type_id_debug(), q.as_str()),
None => self.type_id_debug(),
}
}
fn type_id_debug(&self) -> String {
format!("{:?}", self.type_id)
}
}
pub type ServiceKey = TypeKey;
pub struct Key<T: ?Sized + 'static> {
name: &'static str,
_marker: PhantomData<fn() -> T>,
}
impl<T: ?Sized + 'static> Key<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_marker: PhantomData,
}
}
}
impl<T: ?Sized + 'static> From<Key<T>> for TypeKey {
fn from(k: Key<T>) -> Self {
TypeKey::keyed::<T>(k.name)
}
}
pub(crate) type ScopeId = std::sync::Arc<str>;