#![forbid(missing_docs)]
pub use traitreg_macros::{register, registry};
static __TRAITREG_REGISTRY: std::sync::Mutex<Vec<RegisteredImplWrapper<Box<u32>>>> =
std::sync::Mutex::new(vec![]);
#[doc(hidden)]
pub trait RegisteredImpl<Trait> {
const INSTANCIATE: fn() -> Option<Trait>;
const HAS_CONSTRUCTOR: bool;
const NAME: &'static str;
const PATH: &'static str;
const FILE: &'static str;
const MODULE_PATH: &'static str;
const TRAIT_NAME: &'static str;
}
#[doc(hidden)]
pub fn __register_impl<Trait, Type: RegisteredImpl<Trait>>() {
let wrapper = RegisteredImplWrapper::<Trait> {
instanciate: Type::INSTANCIATE,
has_constructor: Type::HAS_CONSTRUCTOR,
name: Type::NAME,
path: Type::PATH,
file: Type::FILE,
module_path: Type::MODULE_PATH,
trait_name: Type::TRAIT_NAME,
};
let wrapper: RegisteredImplWrapper<Box<u32>> = unsafe { core::mem::transmute(wrapper) };
let mut registry_ref = __TRAITREG_REGISTRY
.lock()
.expect("Traitreg internal mutex poisoned");
registry_ref.push(wrapper);
}
pub struct TraitRegStorage<Trait> {
impls: Vec<RegisteredImplWrapper<Trait>>,
}
impl<Trait> TraitRegStorage<Trait> {
#[doc(hidden)]
pub fn __new(trait_: &'static str) -> Self {
let registry_ref = __TRAITREG_REGISTRY
.lock()
.expect("Traitreg internal mutex poisoned");
let impls = registry_ref
.iter()
.filter(|item| item.trait_name == trait_)
.cloned()
.map(|item| {
let item: RegisteredImplWrapper<Trait> = unsafe { core::mem::transmute(item) };
item
})
.collect();
Self { impls }
}
pub fn iter(&self) -> core::slice::Iter<'_, RegisteredImplWrapper<Trait>> {
self.impls.iter()
}
pub fn instanciate_all(&self) -> impl Iterator<Item = Trait> + '_ {
self.impls.iter().filter_map(|item| item.instanciate())
}
}
#[derive(Clone)]
pub struct RegisteredImplWrapper<Trait> {
instanciate: fn() -> Option<Trait>,
has_constructor: bool,
name: &'static str,
path: &'static str,
file: &'static str,
module_path: &'static str,
trait_name: &'static str,
}
impl<Trait> RegisteredImplWrapper<Trait> {
pub fn instanciate(&self) -> Option<Trait> {
(self.instanciate)()
}
pub fn has_constructor(&self) -> bool {
self.has_constructor
}
pub fn name(&self) -> &'static str {
self.name
}
pub fn path(&self) -> &'static str {
self.path
}
pub fn file(&self) -> &'static str {
self.file
}
pub fn module_path(&self) -> &'static str {
self.module_path
}
pub fn trait_name(&self) -> &'static str {
self.trait_name
}
}
impl<Trait> core::fmt::Debug for RegisteredImplWrapper<Trait> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
f.debug_struct("RegisteredImpl")
.field("Type Name", &self.name)
.field("Type Path", &self.path)
.field("Trait Name", &self.trait_name)
.field("Has Constructor", &self.has_constructor)
.field("Module Path", &self.module_path)
.field("File", &self.file)
.finish()
}
}