use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::{Arc, RwLock, OnceLock};
use std::marker::PhantomData;
use crate::error::{ZiporaError, Result};
pub type Creator<T> = Box<dyn Fn() -> Result<T> + Send + Sync>;
pub struct FactoryRegistry<T> {
creators: RwLock<HashMap<String, Creator<T>>>,
type_map: RwLock<HashMap<TypeId, String>>,
_phantom: PhantomData<T>,
}
impl<T> Default for FactoryRegistry<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> FactoryRegistry<T> {
pub fn new() -> Self {
Self {
creators: RwLock::new(HashMap::new()),
type_map: RwLock::new(HashMap::new()),
_phantom: PhantomData,
}
}
pub fn register<F>(&self, name: &str, creator: F) -> Result<()>
where
F: Fn() -> Result<T> + Send + Sync + 'static,
{
let mut creators = self.creators.write()
.map_err(|_| ZiporaError::io_error("Failed to acquire write lock on creators"))?;
if creators.contains_key(name) {
return Err(ZiporaError::invalid_data(&format!("Creator '{}' already registered", name)));
}
creators.insert(name.to_string(), Box::new(creator));
Ok(())
}
pub fn register_type<U, F>(&self, creator: F) -> Result<()>
where
U: 'static,
F: Fn() -> Result<T> + Send + Sync + 'static,
{
let type_name = std::any::type_name::<U>();
let type_id = TypeId::of::<U>();
{
let mut type_map = self.type_map.write()
.map_err(|_| ZiporaError::io_error("Failed to acquire write lock on type_map"))?;
type_map.insert(type_id, type_name.to_string());
}
self.register(type_name, creator)
}
pub fn create(&self, name: &str) -> Result<T> {
let creators = self.creators.read()
.map_err(|_| ZiporaError::io_error("Failed to acquire read lock on creators"))?;
let creator = creators.get(name)
.ok_or_else(|| ZiporaError::not_found(&format!("Creator '{}' not found", name)))?;
creator()
}
pub fn create_by_type<U: 'static>(&self) -> Result<T> {
let type_id = TypeId::of::<U>();
let type_map = self.type_map.read()
.map_err(|_| ZiporaError::io_error("Failed to acquire read lock on type_map"))?;
let type_name = type_map.get(&type_id)
.ok_or_else(|| ZiporaError::not_found(&format!("Type '{}' not registered", std::any::type_name::<U>())))?.clone();
drop(type_map); self.create(&type_name)
}
pub fn list_creators(&self) -> Result<Vec<String>> {
let creators = self.creators.read()
.map_err(|_| ZiporaError::io_error("Failed to acquire read lock on creators"))?;
Ok(creators.keys().cloned().collect())
}
pub fn creator_count(&self) -> Result<usize> {
let creators = self.creators.read()
.map_err(|_| ZiporaError::io_error("Failed to acquire read lock on creators"))?;
Ok(creators.len())
}
#[inline]
pub fn contains(&self, name: &str) -> Result<bool> {
let creators = self.creators.read()
.map_err(|_| ZiporaError::io_error("Failed to acquire read lock on creators"))?;
Ok(creators.contains_key(name))
}
}
pub struct GlobalFactory<T> {
registry: OnceLock<FactoryRegistry<T>>,
_phantom: PhantomData<T>,
}
impl<T> Default for GlobalFactory<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> GlobalFactory<T> {
pub const fn new() -> Self {
Self {
registry: OnceLock::new(),
_phantom: PhantomData,
}
}
fn registry(&self) -> &FactoryRegistry<T> {
self.registry.get_or_init(|| FactoryRegistry::new())
}
pub fn register<F>(&self, name: &str, creator: F) -> Result<()>
where
F: Fn() -> Result<T> + Send + Sync + 'static,
{
self.registry().register(name, creator)
}
pub fn register_type<U, F>(&self, creator: F) -> Result<()>
where
U: 'static,
F: Fn() -> Result<T> + Send + Sync + 'static,
{
self.registry().register_type::<U, F>(creator)
}
pub fn create(&self, name: &str) -> Result<T> {
self.registry().create(name)
}
pub fn create_by_type<U: 'static>(&self) -> Result<T> {
self.registry().create_by_type::<U>()
}
pub fn list_creators(&self) -> Result<Vec<String>> {
self.registry().list_creators()
}
pub fn creator_count(&self) -> Result<usize> {
self.registry().creator_count()
}
#[inline]
pub fn contains(&self, name: &str) -> Result<bool> {
self.registry().contains(name)
}
}
pub struct AutoRegister<T> {
_phantom: PhantomData<T>,
}
impl<T: Send + Sync + 'static> AutoRegister<T> {
pub fn new<F>(name: &str, creator: F) -> Self
where
F: Fn() -> Result<T> + Send + Sync + 'static,
{
global_factory::<T>().register(name, creator)
.expect(&format!("Failed to register creator '{}'", name));
Self {
_phantom: PhantomData,
}
}
pub fn new_type<U, F>(creator: F) -> Self
where
U: 'static,
F: Fn() -> Result<T> + Send + Sync + 'static,
{
global_factory::<T>().register_type::<U, F>(creator)
.expect(&format!("Failed to register creator for type '{}'", std::any::type_name::<U>()));
Self {
_phantom: PhantomData,
}
}
}
pub fn global_factory<T: Send + Sync + 'static>() -> &'static GlobalFactory<T> {
use std::sync::Mutex;
static FACTORIES: std::sync::LazyLock<Mutex<HashMap<TypeId, Box<dyn Any + Send + Sync>>>> =
std::sync::LazyLock::new(|| Mutex::new(HashMap::new()));
let type_id = TypeId::of::<T>();
{
let factories = FACTORIES.lock().unwrap_or_else(|e| e.into_inner());
if let Some(factory_any) = factories.get(&type_id) {
let factory_ref = factory_any.downcast_ref::<&'static GlobalFactory<T>>()
.expect("registered factory type");
return *factory_ref;
}
}
{
let mut factories = FACTORIES.lock().unwrap_or_else(|e| e.into_inner());
if let Some(factory_any) = factories.get(&type_id) {
let factory_ref = factory_any.downcast_ref::<&'static GlobalFactory<T>>()
.expect("registered factory type");
return *factory_ref;
}
let leaked: &'static GlobalFactory<T> = Box::leak(Box::new(GlobalFactory::<T>::new()));
factories.insert(type_id, Box::new(leaked) as Box<dyn Any + Send + Sync>);
leaked
}
}
pub trait Factoryable: Sized {
fn create(name: &str) -> Result<Self>;
fn list_creators() -> Result<Vec<String>>;
fn has_creator(name: &str) -> Result<bool>;
}
impl<T: Send + Sync + 'static> Factoryable for T {
fn create(name: &str) -> Result<Self> {
global_factory::<T>().create(name)
}
fn list_creators() -> Result<Vec<String>> {
global_factory::<T>().list_creators()
}
fn has_creator(name: &str) -> Result<bool> {
global_factory::<T>().contains(name)
}
}
#[macro_export]
macro_rules! register_factory {
($type:ty, $name:expr, $creator:expr) => {
static _FACTORY_REG: $crate::dev_infrastructure::factory::AutoRegister<$type> =
$crate::dev_infrastructure::factory::AutoRegister::new($name, $creator);
};
}
#[macro_export]
macro_rules! register_factory_type {
($impl_type:ty, $trait_type:ty, $creator:expr) => {
static _FACTORY_REG: $crate::dev_infrastructure::factory::AutoRegister<$trait_type> =
$crate::dev_infrastructure::factory::AutoRegister::new_type::<$impl_type, _>($creator);
};
}
pub struct FactoryBuilder<T> {
name: String,
registry: Arc<FactoryRegistry<T>>,
}
impl<T> FactoryBuilder<T> {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
registry: Arc::new(FactoryRegistry::new()),
}
}
pub fn with_creator<F>(self, name: &str, creator: F) -> Result<Self>
where
F: Fn() -> Result<T> + Send + Sync + 'static,
{
self.registry.register(name, creator)?;
Ok(self)
}
pub fn build(self) -> Arc<FactoryRegistry<T>> {
self.registry
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestObject {
value: i32,
}
impl TestObject {
fn new(value: i32) -> Self {
Self { value }
}
}
trait TestTrait {
fn get_value(&self) -> i32;
}
impl TestTrait for TestObject {
fn get_value(&self) -> i32 {
self.value
}
}
#[test]
fn test_factory_registry_basic() {
let registry = FactoryRegistry::new();
registry.register("test", || Ok(TestObject::new(42))).unwrap();
let obj = registry.create("test").unwrap();
assert_eq!(obj.value, 42);
assert_eq!(registry.creator_count().unwrap(), 1);
assert!(registry.contains("test").unwrap());
assert!(!registry.contains("nonexistent").unwrap());
let creators = registry.list_creators().unwrap();
assert_eq!(creators.len(), 1);
assert!(creators.contains(&"test".to_string()));
}
#[test]
fn test_factory_registry_type_registration() {
let registry = FactoryRegistry::new();
registry.register_type::<TestObject, _>(|| Ok(TestObject::new(99))).unwrap();
let obj = registry.create_by_type::<TestObject>().unwrap();
assert_eq!(obj.value, 99);
}
#[test]
fn test_global_factory() {
let factory = global_factory::<TestObject>();
factory.register("global_test", || Ok(TestObject::new(123))).unwrap();
let obj = factory.create("global_test").unwrap();
assert_eq!(obj.value, 123);
TestObject::create("global_test").unwrap();
assert!(TestObject::has_creator("global_test").unwrap());
}
#[test]
fn test_factory_builder() {
let factory = FactoryBuilder::new("test_factory")
.with_creator("builder_test", || Ok(TestObject::new(456))).unwrap()
.build();
let obj = factory.create("builder_test").unwrap();
assert_eq!(obj.value, 456);
}
#[test]
fn test_factory_errors() {
let registry = FactoryRegistry::new();
assert!(registry.create("nonexistent").is_err());
registry.register("duplicate", || Ok(TestObject::new(1))).unwrap();
assert!(registry.register("duplicate", || Ok(TestObject::new(2))).is_err());
}
#[test]
fn test_trait_objects() {
let registry = FactoryRegistry::<Box<dyn TestTrait>>::new();
registry.register("trait_obj", || {
Ok(Box::new(TestObject::new(789)) as Box<dyn TestTrait>)
}).unwrap();
let obj = registry.create("trait_obj").unwrap();
assert_eq!(obj.get_value(), 789);
}
}