use std::marker::PhantomData; use std::rc::Rc; use crate::errors::injectable::InjectableError; use crate::interfaces::injectable::Injectable; use crate::ptr::{SingletonPtr, TransientPtr}; use crate::DIContainer; #[derive(strum_macros::Display, Debug)] pub enum Providable { Transient(TransientPtr), Singleton(SingletonPtr), #[cfg(feature = "factory")] Factory(crate::ptr::FactoryPtr), #[cfg(feature = "factory")] DefaultFactory( crate::ptr::FactoryPtr, ), } pub trait IProvider { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, ) -> Result; } pub struct TransientTypeProvider where InjectableType: Injectable, { injectable_phantom: PhantomData, } impl TransientTypeProvider where InjectableType: Injectable, { pub fn new() -> Self { Self { injectable_phantom: PhantomData, } } } impl IProvider for TransientTypeProvider where InjectableType: Injectable, { fn provide( &self, di_container: &Rc, dependency_history: Vec<&'static str>, ) -> Result { Ok(Providable::Transient(InjectableType::resolve( di_container, dependency_history, )?)) } } pub struct SingletonProvider where InjectableType: Injectable, { singleton: SingletonPtr, } impl SingletonProvider where InjectableType: Injectable, { pub fn new(singleton: SingletonPtr) -> Self { Self { singleton } } } impl IProvider for SingletonProvider where InjectableType: Injectable, { fn provide( &self, _di_container: &Rc, _dependency_history: Vec<&'static str>, ) -> Result { Ok(Providable::Singleton(self.singleton.clone())) } } #[cfg(feature = "factory")] pub struct FactoryProvider { factory: crate::ptr::FactoryPtr, is_default_factory: bool, } #[cfg(feature = "factory")] impl FactoryProvider { pub fn new( factory: crate::ptr::FactoryPtr, is_default_factory: bool, ) -> Self { Self { factory, is_default_factory, } } } #[cfg(feature = "factory")] impl IProvider for FactoryProvider { fn provide( &self, _di_container: &Rc, _dependency_history: Vec<&'static str>, ) -> Result { Ok(if self.is_default_factory { Providable::DefaultFactory(self.factory.clone()) } else { Providable::Factory(self.factory.clone()) }) } }