modi 0.1.1

An out-of-the-box modular dependency injection web application framework.
Documentation
use crate::dyn_mod::component::Interface;
use crate::dyn_mod::module::{ ComponentMap, ParameterMap };
use crate::dyn_mod::parameters::ComponentParameters;
use crate::dyn_mod::provider::ProviderFn;
use crate::dyn_mod::{
    DmRouter,
    Component,
    ComponentFn,
    HasComponent,
    HasProvider,
    Module,
    ModuleBuildContext,
};
use std::marker::PhantomData;
use std::path::PathBuf;
use std::sync::Arc;

/// Builds a [`Module`]. Component parameters can be set, and both components and providers
/// implementations can be overridden.
///
/// [`Module`]: trait.Module.html
pub struct ModuleBuilder<M: Module> {
    parameters: ParameterMap,
    submodules: M::Submodules,
    component_overrides: ComponentMap,
    component_fn_overrides: ComponentMap,
    provider_overrides: ComponentMap,
    router: Option<DmRouter>,
    manifest_dir: PathBuf,
    _module: PhantomData<M>,
}

#[allow(dead_code)]
impl<M: Module> ModuleBuilder<M> {
    /// Create a ModuleBuilder by providing the module's submodules.
    pub fn with_submodules(submodules: M::Submodules) -> Self {
        ModuleBuilder {
            parameters: ParameterMap::new(),
            submodules,
            component_overrides: ComponentMap::new(),
            component_fn_overrides: ComponentMap::new(),
            provider_overrides: ComponentMap::new(),
            router: None,
            manifest_dir: PathBuf::new(),
            _module: PhantomData,
        }
    }

    /// Set up a router for automatically registering routes.
    pub(crate) fn with_router(mut self, router: DmRouter) -> Self {
        self.router = Some(router);
        self
    }

    /// Set up a manifest dir for output manifest file.
    pub(crate) fn with_manifest_dir(mut self, manifest_dir: PathBuf) -> Self {
        self.manifest_dir = manifest_dir;
        self
    }

    /// Set the parameters of the specified component. If the parameters are not
    /// manually set, the defaults will be used.
    pub fn with_component_parameters<C: Component<M>>(mut self, params: C::Parameters) -> Self
        where M: HasComponent<C::Interface>
    {
        self.parameters.insert(ComponentParameters::<C, C::Parameters>::new(params));
        self
    }

    /// Override a component implementation. This method is best used when the
    /// overriding component has no injected dependencies.
    pub fn with_component_override<I: Interface + ?Sized>(mut self, component: Box<I>) -> Self
        where M: HasComponent<I>
    {
        self.component_overrides.insert::<Arc<I>>(Arc::from(component));
        self
    }

    /// Override a component implementation. This method is best used when the
    /// overriding component has injected dependencies.
    pub fn with_component_override_fn<I: Interface + ?Sized>(
        mut self,
        component_fn: ComponentFn<M, I>
    ) -> Self
        where M: HasComponent<I>
    {
        self.component_fn_overrides.insert(component_fn);
        self
    }

    /// Override a provider implementation.
    pub(crate) fn with_provider_override<I: 'static + ?Sized>(
        mut self,
        provider_fn: ProviderFn<M, I>
    ) -> Self
        where M: HasProvider<I>
    {
        self.provider_overrides.insert(Arc::new(provider_fn));
        self
    }

    /// Build the module
    pub(crate) fn build(self) -> M {
        M::build(
            ModuleBuildContext::new(
                self.parameters,
                self.component_overrides,
                self.component_fn_overrides,
                self.provider_overrides,
                self.submodules,
                self.router,
                self.manifest_dir
            )
        )
    }
}