1use crate::Error;
2use crate::resolver::Services;
3use crate::runtime::TypeMeta;
4
5pub trait FromDi: Sized {
7 fn depends_on() -> &'static [TypeMeta];
8 fn produce(services: &Services) -> Result<Self, Error>;
9}
10
11pub trait DiFactory<T, Args>: DiFactoryOnce<T, Args> {
13 fn produce(&self, services: &Services) -> Result<T, Error>;
14}
15
16pub trait DiFactoryOnce<T, Args>: 'static {
18 fn depends_on() -> &'static [TypeMeta];
19 fn produce(self, services: &Services) -> Result<T, Error>;
20}
21
22macro_rules! impl_factory_once {
23 ($($args:ident),*) => {
24 impl<F, O, $($args),*> DiFactoryOnce<O, ($($args),*,)> for F
25 where
26 $($args: $crate::FromDi,)*
27 F: FnOnce($($args),*) -> O + 'static,
28 O: 'static,
29 $($args: 'static),*
30 {
31 fn depends_on() -> &'static [$crate::runtime::TypeMeta] {
32 const {
33 &[
34 $($crate::runtime::TypeMeta::of::<$args>()),*
35 ]
36 }
37 }
38
39 fn produce(self, services: &$crate::Services) -> Result<O, $crate::Error> {
40 Ok((self)(
41 $($args::produce(services)?),*
42 ))
43 }
44 }
45 };
46}
47
48macro_rules! impl_factory {
49 ($($args:ident),*) => {
50 impl<F, O, $($args),*> DiFactory<O, ($($args),*,)> for F
51 where
52 $($args: $crate::FromDi,)*
53 F: Fn($($args),*) -> O + 'static,
54 O: 'static,
55 $($args: 'static),*
56 {
57 fn produce(&self, services: &$crate::Services) -> Result<O, $crate::Error> {
58 Ok((&self)(
59 $($args::produce(services)?),*
60 ))
61 }
62 }
63 };
64}
65
66macro_rules! impl_all_for {
67 ($macro:ident) => {
68 $macro!(T1);
69 $macro!(T1, T2);
70 $macro!(T1, T2, T3);
71 $macro!(T1, T2, T3, T4);
72 $macro!(T1, T2, T3, T4, T5);
73 $macro!(T1, T2, T3, T4, T5, T6);
74 $macro!(T1, T2, T3, T4, T5, T6, T7);
75 $macro!(T1, T2, T3, T4, T5, T6, T7, T8);
76 $macro!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
77 };
78}
79
80impl_all_for!(impl_factory_once);
81impl_all_for!(impl_factory);
82
83impl<F, O> DiFactoryOnce<O, ()> for F
84where
85 F: FnOnce() -> O + 'static,
86 O: 'static,
87{
88 fn depends_on() -> &'static [TypeMeta] {
89 &[]
90 }
91
92 fn produce(self, _: &Services) -> Result<O, Error> {
93 Ok(self())
94 }
95}
96
97impl<F, O> DiFactory<O, ()> for F
98where
99 F: Fn() -> O + 'static,
100 O: 'static,
101{
102 fn produce(&self, _: &Services) -> Result<O, Error> {
103 Ok(self())
104 }
105}