use core::any::Any;
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::{boxed::Box, rc::Rc, sync::Arc};
use once_cell::sync::Lazy;
#[doc(hidden)]
pub use linkme;
use crate::{Entry, Registry};
#[doc(hidden)]
#[linkme::distributed_slice]
pub static REGISTRY_KV: [Entry<'static>];
#[macro_export]
macro_rules! register {
( $ty:ty => $tr:ty $(, $flag:ident)? ) => {
$crate::register! { $crate::REGISTRY_KV: $ty => $tr $(, $flag)? }
};
( $reg:path: $ty:ty => $tr:ty $(, $flag:ident)? ) => {
$crate::gensym! { $crate::register!{ $reg: $ty => $tr $(, $flag)? } }
};
( $name:ident, $reg:path: $ty:ty => $tr:ty $(, $flag:ident)? ) => {
#[$crate::linkme::distributed_slice($reg)]
#[linkme(crate=$crate::linkme)]
static $name: $crate::Entry<'static> = $crate::entry!( $ty => $tr $(, $flag)? );
};
}
pub static REGISTRY: Lazy<Registry<'static>> = Lazy::new(|| Registry::new(REGISTRY_KV));
pub trait CastableRef {
fn castable<T: ?Sized + 'static>(self) -> bool;
}
impl CastableRef for &dyn Any {
fn castable<T: ?Sized + 'static>(self) -> bool {
REGISTRY.castable_ref::<T>(self)
}
}
pub trait Castable {
fn castable<T: ?Sized + 'static>() -> bool;
}
impl<U: ?Sized + 'static> Castable for U {
fn castable<T: ?Sized + 'static>() -> bool {
REGISTRY.castable::<T, U>()
}
}
pub trait Cast<T> {
fn cast(self) -> Option<T>;
}
impl<'b, T: ?Sized + 'static> Cast<&'b T> for &'b dyn Any {
fn cast(self) -> Option<&'b T> {
REGISTRY.cast_ref(self)
}
}
impl<'b, T: ?Sized + 'static> Cast<&'b mut T> for &'b mut dyn Any {
fn cast(self) -> Option<&'b mut T> {
REGISTRY.cast_mut(self)
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized + 'static> Cast<Box<T>> for Box<dyn Any> {
fn cast(self) -> Option<Box<T>> {
REGISTRY.cast_box(self).ok()
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized + 'static> Cast<Rc<T>> for Rc<dyn Any> {
fn cast(self) -> Option<Rc<T>> {
REGISTRY.cast_rc(self).ok()
}
}
#[cfg(feature = "alloc")]
impl<T: ?Sized + 'static> Cast<Arc<T>> for Arc<dyn Any + Sync + Send> {
fn cast(self) -> Option<Arc<T>> {
REGISTRY.cast_arc(self).ok()
}
}