1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4#[cfg(feature = "axum")]
5#[cfg_attr(docsrs, doc(cfg(feature = "axum")))]
6pub mod axum;
7
8#[cfg(feature = "async")]
9#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
10pub mod async_dependency;
11
12#[cfg(feature = "async")]
13#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
14pub use async_dependency::*;
15
16#[cfg(feature = "async")]
17#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
18pub use async_trait::async_trait;
19
20pub trait FromWorld {
44 type World<'a>;
45 type Error;
46
47 fn from_world(world: &Self::World<'_>) -> Result<Self, Self::Error>
48 where
49 Self: std::marker::Sized;
50}
51
52pub trait FromDependency {
78 type Error;
79 type World<'a>;
80 type Dependency: for<'a> FromWorld<World<'a> = Self::World<'a>, Error = Self::Error>;
81
82 fn from_dependency(
83 world: &Self::World<'_>,
84 dependency: &Self::Dependency,
85 ) -> Result<Self, Self::Error>
86 where
87 Self: std::marker::Sized;
88}
89
90impl<T> FromWorld for T
91where
92 T: FromDependency,
93 T::Dependency: FromWorld,
94{
95 type Error = T::Error;
96 type World<'a> = T::World<'a>;
97
98 fn from_world(world: &Self::World<'_>) -> Result<Self, T::Error> {
99 let dependency = <T::Dependency as FromWorld>::from_world(world)?;
100
101 Self::from_dependency(world, &dependency)
102 }
103}
104
105macro_rules! impl_tuple {
106 ($first_n:tt:$first_name:ident, $($n:tt:$name:ident),+) => {
107 impl<$first_name, $($name),*> FromWorld for ($first_name, $($name),+)
108 where
109 $first_name: FromWorld,
110 $($name: for<'a> FromWorld<World<'a> = $first_name::World<'a>, Error = $first_name::Error>),*
111 {
112 type Error = $first_name::Error;
113 type World<'a> = $first_name::World<'a>;
114
115 fn from_world(world: &Self::World<'_>) -> Result<Self, Self::Error> {
116 Ok((
117 $first_name::from_world(world)?,
118 $($name::from_world(world)?),+
119 ))
120 }
121 }
122 };
123}
124
125impl_tuple!(0:Dep0, 1:Dep1, 2:Dep2, 3:Dep3, 4:Dep4, 5:Dep5, 6:Dep6, 7:Dep7, 8:Dep8);
126impl_tuple!(0:Dep0, 1:Dep1, 2:Dep2, 3:Dep3, 4:Dep4, 5:Dep5, 6:Dep6, 7:Dep7);
127impl_tuple!(0:Dep0, 1:Dep1, 2:Dep2, 3:Dep3, 4:Dep4, 5:Dep5, 6:Dep6);
128impl_tuple!(0:Dep0, 1:Dep1, 2:Dep2, 3:Dep3, 4:Dep4, 5:Dep5);
129impl_tuple!(0:Dep0, 1:Dep1, 2:Dep2, 3:Dep3, 4:Dep4);
130impl_tuple!(0:Dep0, 1:Dep1, 2:Dep2, 3:Dep3);
131impl_tuple!(0:Dep0, 1:Dep1, 2:Dep2);
132impl_tuple!(0:Dep0, 1:Dep1);
133
134pub struct DIContainer<World> {
135 world: World,
136}
137
138impl<World> DIContainer<World> {
139 pub fn new(world: World) -> Self {
140 Self { world }
141 }
142
143 pub fn extract<T: for<'a> FromWorld<World<'a> = World>>(
144 &self,
145 ) -> Result<T, <T as FromWorld>::Error> {
146 T::from_world(&self.world)
147 }
148}
149
150#[cfg(feature = "async")]
151#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
152impl<World> DIContainer<World> {
153 pub async fn extract_async<
154 T: for<'a> crate::async_dependency::FromAsyncWorld<World<'a> = World>,
155 >(
156 &self,
157 ) -> Result<T, <T as crate::async_dependency::FromAsyncWorld>::Error> {
158 T::from_world(&self.world).await
159 }
160}