Skip to main content

deorbit_core/
from_di.rs

1use crate::Error;
2use crate::resolver::Services;
3use crate::runtime::TypeMeta;
4
5/// Represents an object that's capable of building itself from a DI instance.
6pub trait FromDi: Sized {
7    fn depends_on() -> &'static [TypeMeta];
8    fn produce(services: &Services) -> Result<Self, Error>;
9}
10
11/// Represents an object that's capable of building T from a DI instance.
12pub trait DiFactory<T, Args>: DiFactoryOnce<T, Args> {
13    fn produce(&self, services: &Services) -> Result<T, Error>;
14}
15
16/// Represents an object that's capable of building T from a DI instance.
17pub 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}