use crate::Component;
use std::any::{Any, TypeId};
use std::pin::Pin;
use tokio::sync::OnceCell;
pub type InjectionInstance = &'static (dyn Any + Send + Sync);
pub type BeanFuture = Pin<Box<dyn Future<Output = InjectionInstance> + Send>>;
pub type InitFn = fn() -> BeanFuture;
#[derive(Clone)]
pub struct InjectionBean {
pub(crate) initial: InitFn,
pub(crate) instance: OnceCell<InjectionInstance>,
}
impl InjectionBean {
pub(crate) fn new(factory: InitFn) -> Self {
Self {
initial: factory,
instance: OnceCell::new(),
}
}
pub async fn get(&self) -> InjectionInstance {
let instance = self
.instance
.get_or_init(self.initial)
.await;
*instance
}
pub fn get_inner(&self) -> &InjectionInstance {
self.instance.get().expect("bean not initialized")
}
}
pub struct InjectionBeanDefinition {
pub type_id: TypeId,
pub name: &'static str,
pub init_fn: InitFn,
}
impl InjectionBeanDefinition {
pub const fn new<T: Component>(name: &'static str, init_fn: InitFn) -> Self {
Self {
type_id: TypeId::of::<T>(),
name,
init_fn,
}
}
}
inventory::collect!(InjectionBeanDefinition);