mod graph;
use std::{any::Any, future::Future, pin::Pin};
use crate::{Container, Result};
pub use graph::ModuleGraph;
pub trait Module {
fn definition() -> ModuleDefinition;
}
pub trait ProviderRegistrant {
fn register_provider(container: &mut Container) -> Result<()>;
}
pub trait ControllerRegistrant {
fn controller_name() -> &'static str;
fn controller_prefix() -> &'static str;
fn build_router(container: &Container) -> Result<Box<dyn Any + Send + Sync>>;
fn route_metadata() -> Box<dyn Any + Send + Sync>;
}
pub type ProviderRegistrar = fn(&mut Container) -> Result<()>;
pub type ModuleDefinitionFactory = fn() -> ModuleDefinition;
pub type AsyncProviderInitializer =
for<'a> fn(&'a mut Container) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
#[derive(Clone, Copy)]
pub struct ControllerDescriptor {
name: &'static str,
prefix: fn() -> &'static str,
build_router: fn(&Container) -> Result<Box<dyn Any + Send + Sync>>,
route_metadata: fn() -> Box<dyn Any + Send + Sync>,
}
impl ControllerDescriptor {
pub fn new<C>() -> Self
where
C: ControllerRegistrant,
{
Self {
name: C::controller_name(),
prefix: C::controller_prefix,
build_router: C::build_router,
route_metadata: C::route_metadata,
}
}
pub fn name(&self) -> &'static str {
self.name
}
pub fn prefix(&self) -> &'static str {
(self.prefix)()
}
pub fn build_router(&self, container: &Container) -> Result<Box<dyn Any + Send + Sync>> {
(self.build_router)(container)
}
pub fn route_metadata(&self) -> Box<dyn Any + Send + Sync> {
(self.route_metadata)()
}
}
#[derive(Clone)]
pub struct ModuleDefinition {
name: String,
imports: Vec<String>,
providers: Vec<String>,
controllers: Vec<String>,
exports: Vec<String>,
import_factories: Vec<ModuleDefinitionFactory>,
provider_registrars: Vec<ProviderRegistrar>,
controller_descriptors: Vec<ControllerDescriptor>,
async_initializers: Vec<AsyncProviderInitializer>,
}
impl ModuleDefinition {
pub fn name(&self) -> &str {
&self.name
}
pub fn imports(&self) -> &[String] {
&self.imports
}
pub fn providers(&self) -> &[String] {
&self.providers
}
pub fn controllers(&self) -> &[String] {
&self.controllers
}
pub fn exports(&self) -> &[String] {
&self.exports
}
pub fn import_factories(&self) -> &[ModuleDefinitionFactory] {
&self.import_factories
}
pub fn provider_registrars(&self) -> &[ProviderRegistrar] {
&self.provider_registrars
}
pub fn controller_descriptors(&self) -> &[ControllerDescriptor] {
&self.controller_descriptors
}
pub fn async_initializers(&self) -> &[AsyncProviderInitializer] {
&self.async_initializers
}
}
impl std::fmt::Debug for ModuleDefinition {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("ModuleDefinition")
.field("name", &self.name)
.field("imports", &self.imports)
.field("providers", &self.providers)
.field("controllers", &self.controllers)
.field("exports", &self.exports)
.finish_non_exhaustive()
}
}
impl PartialEq for ModuleDefinition {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& self.imports == other.imports
&& self.providers == other.providers
&& self.controllers == other.controllers
&& self.exports == other.exports
}
}
impl Eq for ModuleDefinition {}
#[derive(Debug)]
pub struct ModuleBuilder {
definition: ModuleDefinition,
}
impl ModuleBuilder {
pub fn new(name: impl Into<String>) -> Self {
Self {
definition: ModuleDefinition {
name: name.into(),
imports: Vec::new(),
providers: Vec::new(),
controllers: Vec::new(),
exports: Vec::new(),
import_factories: Vec::new(),
provider_registrars: Vec::new(),
controller_descriptors: Vec::new(),
async_initializers: Vec::new(),
},
}
}
pub fn import(mut self, name: impl Into<String>) -> Self {
self.definition.imports.push(name.into());
self
}
pub fn import_typed<M>(mut self) -> Self
where
M: Module,
{
let definition = M::definition();
self.definition.imports.push(definition.name().to_owned());
self.definition.import_factories.push(M::definition);
self
}
pub fn provider(mut self, name: impl Into<String>) -> Self {
self.definition.providers.push(name.into());
self
}
pub fn provider_typed<P>(mut self) -> Self
where
P: ProviderRegistrant,
{
self.definition.providers.push(
std::any::type_name::<P>()
.rsplit("::")
.next()
.unwrap()
.to_owned(),
);
self.definition
.provider_registrars
.push(P::register_provider);
self
}
pub fn controller(mut self, name: impl Into<String>) -> Self {
self.definition.controllers.push(name.into());
self
}
pub fn controller_typed<C>(mut self) -> Self
where
C: ControllerRegistrant,
{
self.definition
.controllers
.push(C::controller_name().to_owned());
self.definition
.controller_descriptors
.push(ControllerDescriptor::new::<C>());
self
}
pub fn export(mut self, name: impl Into<String>) -> Self {
self.definition.exports.push(name.into());
self
}
pub fn export_typed<P>(mut self) -> Self {
self.definition.exports.push(
std::any::type_name::<P>()
.rsplit("::")
.next()
.unwrap()
.to_owned(),
);
self
}
pub fn async_initializer(mut self, initializer: AsyncProviderInitializer) -> Self {
self.definition.async_initializers.push(initializer);
self
}
pub fn build(self) -> ModuleDefinition {
self.definition
}
}