use core::{
any::{Any, TypeId},
fmt,
};
use crate::alloc::Box;
pub trait ModuleId: Any + fmt::Display + Send + Sync {
fn clone_boxed(&self) -> Box<dyn ModuleId>;
}
impl dyn ModuleId {
#[inline]
pub fn is<T: ModuleId>(&self) -> bool {
let t = TypeId::of::<T>();
let concrete = self.type_id();
t == concrete
}
pub fn downcast_ref<T: ModuleId>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe { Some(&*(self as *const dyn ModuleId).cast::<T>()) }
} else {
None
}
}
}
impl fmt::Debug for dyn ModuleId {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "ModuleId({})", self)
}
}
impl ModuleId for &'static str {
fn clone_boxed(&self) -> Box<dyn ModuleId> {
Box::new(*self)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WildcardId;
impl ModuleId for WildcardId {
fn clone_boxed(&self) -> Box<dyn ModuleId> {
Box::new(*self)
}
}
impl fmt::Display for WildcardId {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("*")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct IndexedId {
pub prefix: &'static str,
pub index: usize,
}
impl IndexedId {
pub const fn new(prefix: &'static str, index: usize) -> Self {
Self { prefix, index }
}
}
impl fmt::Display for IndexedId {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "{} #{}", self.prefix, self.index + 1)
}
}
impl ModuleId for IndexedId {
fn clone_boxed(&self) -> Box<dyn ModuleId> {
Box::new(*self)
}
}