deorbit-core 0.1.4

A dependency injection framework for Rust
Documentation
use crate::from_di::{DiFactory, FromDi};
use crate::resolver::Error;
use crate::runtime::ErasedArc;
use crate::{DiFactoryOnce, Services};
use std::fmt::{Debug, Formatter};
use std::sync::Arc;

pub type ServiceFactory = Factory<Arc<dyn Fn(&Services) -> Result<ErasedArc, Error> + Send + Sync>>;
pub type ServiceFactoryOnce = Factory<Box<dyn FnOnce(&Services) -> Result<ErasedArc, Error> + Send + Sync>>;

#[derive(Clone)]
pub struct Factory<F> {
    alloc: ServiceAllocator<F>,
}

#[derive(Clone)]
enum ServiceAllocator<F> {
    Static {
        fun: fn(&Services) -> Result<ErasedArc, Error>,
    },
    Fn {
        fun: F,
    },
}

impl<T> Debug for Factory<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let stringified = match self.alloc {
            ServiceAllocator::Static { .. } => "Static",
            ServiceAllocator::Fn { .. } => "Closure",
        };

        write!(f, "{}", stringified)
    }
}

impl<F> Factory<F> {
    pub fn from_container<T>() -> Self
    where
        T: Send + Sync + FromDi + 'static,
    {
        let wrapper = move |x: &_| {
            let instance = T::produce(x)?;
            let erased = ErasedArc::from_instance(instance);

            Ok(erased)
        };

        Self {
            alloc: ServiceAllocator::Static { fun: wrapper },
        }
    }

    pub fn from_default<T>() -> Self
    where
        T: Send + Sync + Default + 'static,
    {
        Self {
            alloc: ServiceAllocator::Static {
                fun: |_| Ok(ErasedArc::from_instance(T::default())),
            },
        }
    }
}

impl ServiceFactory {
    pub fn from_fn<F, T, Args>(allocator: F) -> Self
    where
        F: DiFactory<T, Args> + Send + Sync,
        T: Send + Sync + 'static,
    {
        let wrapper = move |x: &_| {
            let instance = DiFactory::<T, Args>::produce(&allocator, x)?;
            let erased = ErasedArc::from_instance(instance);

            Ok(erased)
        };

        Self {
            alloc: ServiceAllocator::Fn {
                fun: Arc::new(wrapper),
            },
        }
    }

    pub fn produce(&self, services: &Services) -> Result<ErasedArc, Error> {
        match &self.alloc {
            ServiceAllocator::Static { fun } => fun(services),
            ServiceAllocator::Fn { fun } => fun(services),
        }
    }
}

impl ServiceFactoryOnce {
    pub fn from_fn_once<F, T, Args>(allocator: F) -> Self
    where
        F: DiFactoryOnce<T, Args> + Send + Sync,
        T: Send + Sync + 'static,
    {
        let wrapper = move |x: &_| {
            let instance = DiFactoryOnce::<T, Args>::produce(allocator, x)?;
            let erased = ErasedArc::from_instance(instance);

            Ok(erased)
        };

        Self {
            alloc: ServiceAllocator::Fn {
                fun: Box::new(wrapper),
            },
        }
    }

    pub fn produce(self, services: &Services) -> Result<ErasedArc, Error> {
        match self.alloc {
            ServiceAllocator::Static { fun } => fun(services),
            ServiceAllocator::Fn { fun } => fun(services),
        }
    }
}