ruwebframe 0.1.8

a simple webframe for rust actix-web, based on rudi and rbatis.
Documentation
use std::any::Any;
use std::collections::HashMap;
use std::sync::{Arc, Mutex };

/// 存储的条目:可以是工厂函数,也可以是已创建的单例实例
pub enum Entry {
    /// 工厂:每次 get 都调用,创建新实例
    Factory(Box<dyn Fn() -> Box<dyn Any> + Send + Sync>),
    /// 单例:首次 get 时创建,之后复用
    Singleton {
        factory: Box<dyn Fn() -> Box<dyn Any> + Send + Sync>,
        instance: Mutex<Option<Arc<dyn Any + Send + Sync>>>,
    },
}

pub struct Container {
    pub items: HashMap<String, Entry>,
}

impl Container {
    pub fn new() -> Self {
        Self {
            items: HashMap::new(),

        }
    }

    /// 注册一个工厂函数(每次 get 都创建新实例)
    pub fn register<F, T>(&mut self, key: &str, factory: F)
    where
        F: Fn() -> T + Send + Sync + 'static,
        T: Any + Send + Sync + 'static,
    {
        self.items.insert(
            key.to_string(),
            Entry::Factory(Box::new(move || Box::new(factory()) as Box<dyn Any>)),
        );
    }

    /// 注册一个单例工厂(首次 get 时创建,之后复用)
    pub fn register_singleton<F, T>(&mut self, key: &str, factory: F)
    where
        F: Fn() -> T + Send + Sync + 'static,
        T: Any + Send + Sync + 'static,
    {
        self.items.insert(
            key.to_string(),
            Entry::Singleton {
                factory: Box::new(move || Box::new(factory()) as Box<dyn Any>),
                instance: Mutex::new(None),
            },
        );
    }

    /// 获取实例(多例模式:每次调用都 new)
    pub fn get<T: Any + Clone>(&self, key: &str) -> Option<T> {
        let entry = self.items.get(key)?;
        match entry {
            Entry::Factory(factory) => {
                let boxed = factory();
                boxed.downcast_ref::<T>().cloned()
            }
            Entry::Singleton { .. } => {
                // 单例用 get_singleton
                None
            }
        }
    }

    /// 返回 Arc<T>:零拷贝,多持有者共享同一实例
    pub fn get_singleton<T: Any + Send + Sync>(&self, key: &str) -> Option<Arc<T>> {
        let entry = self.items.get(key)?;
        match entry {
            Entry::Singleton { factory, instance } => {
                let mut guard = instance.lock().ok()?;

                // 懒加载:首次访问时才 new
                if guard.is_none() {
                    let boxed = factory();
                    let val = *boxed.downcast::<T>()
                        .expect("类型不匹配:注册和解析的类型不一致");
                    *guard = Some(Arc::new(val) as Arc<dyn Any + Send + Sync>);
                }

                // Arc<dyn Any> -> Arc<T>,只增加引用计数
                guard.as_ref().map(|arc_any| {
                    arc_any.clone().downcast::<T>()
                        .expect("单例内部类型转换失败")
                })
            }
            Entry::Factory { .. } => None,
        }
    }
    /// ✅ 统一入口:自动判断 key 是单例还是工厂
    pub fn get_bean<T: Any + Send + Sync>(&self, key: &str) -> Option<Arc<T>> {
        let entry = self.items.get(key)?;
        match entry {
            // 工厂模式:每次调用都 new,包成 Arc 返回
            Entry::Factory(factory) => {
                let boxed = factory();
                let val = *boxed.downcast::<T>().ok()?;
                Some(Arc::new(val))
            }
            // 单例模式:首次 new 并缓存,之后复用
            Entry::Singleton { factory, instance } => {
                let mut guard = instance.lock().ok()?;
                if guard.is_none() {
                    let val = *factory().downcast::<T>().ok()?;
                    *guard = Some(Arc::new(val) as Arc<dyn Any + Send + Sync>);
                }
                guard.as_ref()?.clone().downcast::<T>().ok()
            }
        }
    }


    /// 如果你想在外部提前知道某个 key 是什么类型
    pub fn is_singleton(&self, key: &str) -> bool {
        matches!(self.items.get(key), Some(Entry::Singleton { .. }))
    }
}


/// 注册项:每个类型提交一个,启动时统一收集
pub struct Reg {
    pub name: &'static str,
    pub apply: fn(&mut  crate::rudi::dicontainer::container::Container),
}

// 声明收集池
inventory::collect!(Reg);
// 自动收集所有 inventory::submit! 的注册项
/// 启动时一次性扫描所有注册项
pub fn bootstrap(container: &mut crate::rudi::dicontainer::container::Container) {
    for reg in inventory::iter::<Reg> {
        (reg.apply)(container);
    }

}

/// 简化宏:一行完成注册
#[macro_export]
macro_rules! register_singleton {
    ($key:expr, $type:ty, $factory:expr) => {
        inventory::submit! {
            $crate::rudi::dicontainer::container::Reg {
                name: $key,
                apply: |c: &mut $crate::rudi::dicontainer::container::Container| {
                    c.register_singleton($key, $factory);
                },
            }
        }
    };
}

#[macro_export]
macro_rules! register_transient {
    ($key:expr, $type:ty, $factory:expr) => {
        inventory::submit! {
            $crate::rudi::dicontainer::container::Reg {
                name: $key,
                apply: |c: &mut $crate::rudi::dicontainer::container::Container| {
                    c.register($key, $factory);
                },
            }
        }
    };
}