#[macro_export]
macro_rules! dependency {
($lifecycle:ident, $type:ty) => {
$crate::__dependency!($lifecycle, concrete, $type);
};
}
#[macro_export]
macro_rules! dependency_as {
($lifecycle:ident, $trait:path: $impl:ty) => {
$crate::__dependency!($lifecycle, r#as, dyn $trait + Send + Sync, $impl);
};
}
#[macro_export]
macro_rules! dependency_as_many {
($trait:path: [ $( ($lifecycle:ident, $impl:ty) ),* $(,)? ]) => {
$crate::__many_batch_mixed!(@emit dyn $trait + Send + Sync, [ $( ($lifecycle, $impl) ),* ]);
};
}
#[macro_export]
macro_rules! dependency_keyed_as {
($key:ty, $trait:path: [ $( ($key_expr:expr, $lifecycle:ident, $impl:ty) ),* $(,)? ]) => {
$crate::__keyed_batch_mixed!(@emit $key, dyn $trait + Send + Sync, [ $( ($key_expr, $lifecycle, $impl) ),* ]);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __resolve_entry {
(singleton, $trait:ty, $impl:ty) => {{
use std::sync::{Arc, LazyLock};
use $crate::core::{Container, Injectable};
static CACHED: LazyLock<Arc<$trait>> = LazyLock::new(|| {
Arc::new(<$impl as Injectable<Container>>::inject(&Container)) as Arc<$trait>
});
CACHED.clone()
}};
(transient, $trait:ty, $impl:ty) => {{
use std::sync::Arc;
use $crate::core::{Container, Injectable};
Arc::new(<$impl as Injectable<Container>>::inject(&Container)) as Arc<$trait>
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __many_batch_mixed {
(@emit $trait:ty, [ $( ($lifecycle:ident, $impl:ty) ),* $(,)? ]) => {
const _: () = {
use $crate::core::Container;
use $crate::di::ManyResolver;
use std::sync::Arc;
impl ManyResolver<$trait> for Container {
fn resolve_many() -> Arc<[Arc<$trait>]> {
Arc::from([
$( $crate::__resolve_entry!($lifecycle, $trait, $impl), )*
])
}
}
};
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __keyed_batch_mixed {
(@emit $key:ty, $trait:ty, [ $( ($key_expr:expr, $lifecycle:ident, $impl:ty) ),* $(,)? ]) => {
const _: () = {
use $crate::core::Container;
use $crate::di::KeyedResolver;
use std::sync::Arc;
impl KeyedResolver<$key, $trait> for Container {
fn resolve_keyed(key: $key) -> Option<Arc<$trait>> {
$(
if key == $key_expr {
return Some($crate::__resolve_entry!($lifecycle, $trait, $impl));
}
)*
None
}
}
};
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __dependency {
($lifecycle:ident, concrete, $type:ty) => {
const _: () = {
use std::sync::Arc;
use $crate::core::{Container, Injectable, Resolver};
$crate::__dependency!(@lifecycle $lifecycle, {
use std::sync::LazyLock;
impl Resolver<$type> for Container {
fn resolve() -> Arc<$type> {
static INSTANCE: LazyLock<Arc<$type>> = LazyLock::new(|| {
Arc::new(<$type as Injectable<Container>>::inject(&Container))
});
INSTANCE.clone()
}
}
}, {
impl Resolver<$type> for Container {
fn resolve() -> Arc<$type> {
Arc::new(<$type as Injectable<Container>>::inject(&Container))
}
}
});
};
};
($lifecycle:ident, r#as, $trait:ty, $impl:ty) => {
const _: () = {
use std::sync::Arc;
use $crate::core::{Container, Injectable, Resolver};
$crate::__dependency!(@lifecycle $lifecycle, {
use std::sync::LazyLock;
impl Resolver<$trait> for Container {
fn resolve() -> Arc<$trait> {
static INSTANCE: LazyLock<Arc<$trait>> = LazyLock::new(|| {
Arc::new(<$impl as Injectable<Container>>::inject(&Container))
as Arc<$trait>
});
INSTANCE.clone()
}
}
}, {
impl Resolver<$trait> for Container {
fn resolve() -> Arc<$trait> {
Arc::new(<$impl as Injectable<Container>>::inject(&Container))
as Arc<$trait>
}
}
});
};
};
(@lifecycle singleton, $singleton:expr, $transient:expr) => {
$singleton
};
(@lifecycle transient, $singleton:expr, $transient:expr) => {
$transient
};
}