sinan 0.1.0

A Boilerplate for Rapid Axum Web Service Deployment.
Documentation
use std::any::{Any, TypeId};
use std::collections::HashMap;

use once_cell::sync::OnceCell;

use crate::contracts::Facade;

pub struct Container(HashMap<TypeId, Box<dyn Any + Send + Sync>>);

// 只要实现了 facade trait 都可以被注册到容器中成为全局实例
// 初始化一些全局实例,使用时 copy 出一份,就不需要处理引用了或者可变借用...
// 拷贝出来的实例随作用域释放,占内存的仅全局的实例...
impl Default for Container {
    fn default() -> Self {
        Self::new()
    }
}

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

    pub fn register<T: Facade>(&mut self) {
        self.0.insert(TypeId::of::<T>(), Box::new(T::new(self)));
    }

    pub fn get<T: Facade>(&self) -> Option<&T> {
        self.0
            .get(&TypeId::of::<T>())
            .and_then(|boxed| boxed.downcast_ref::<T>())
    }

    pub fn get_mut<T: Facade>(&mut self) -> Option<&mut T> {
        self.0
            .get_mut(&TypeId::of::<T>())
            .and_then(|boxed| boxed.downcast_mut::<T>())
    }

    pub fn into_static(self) -> &'static Container {
        CONTAINER.get_or_init(|| self)
    }
}

static CONTAINER: OnceCell<Container> = OnceCell::new();

pub fn container() -> &'static Container {
    CONTAINER.get().expect("Container not initialized")
}