1use crate::Container;
4use crate::error::Error;
5
6pub trait Inject: Sized + Send + Sync {
46 fn inject(container: &Container) -> Result<Self, Error>;
48}
49
50impl Inject for Container {
51 #[inline]
52 fn inject(container: &Container) -> Result<Self, Error> {
53 Ok(container.clone())
54 }
55}
56
57impl Inject for () {
58 #[inline]
59 fn inject(_: &Container) -> Result<Self, Error> {
60 Ok(())
61 }
62}
63
64macro_rules! define_inject {
65 ($($T: ident),*) => {
66 impl<$($T: Inject),+> Inject for ($($T,)+) {
67 #[inline]
68 #[allow(non_snake_case)]
69 fn inject(container: &Container) -> Result<Self, Error> {
70 let tuple = (
71 $(
72 $T::inject(container)?,
73 )*
74 );
75 Ok(tuple)
76 }
77 }
78 }
79}
80
81define_inject! { T1 }
82define_inject! { T1, T2 }
83define_inject! { T1, T2, T3 }
84define_inject! { T1, T2, T3, T4 }
85define_inject! { T1, T2, T3, T4, T5 }
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use crate::container::ContainerBuilder;
91 use std::sync::{Arc, Mutex};
92
93 #[derive(Default, Clone)]
94 struct SimpleService {
95 value: i32,
96 }
97
98 impl Inject for SimpleService {
99 fn inject(_: &Container) -> Result<Self, Error> {
100 Ok(Default::default())
101 }
102 }
103
104 #[derive(Clone)]
105 struct ServiceWithDependency {
106 service: SimpleService,
107 multiplier: i32,
108 }
109
110 impl Inject for ServiceWithDependency {
111 fn inject(container: &Container) -> Result<Self, Error> {
112 let service = container.resolve::<SimpleService>()?;
113 Ok(Self {
114 service,
115 multiplier: 2,
116 })
117 }
118 }
119
120 #[derive(Clone)]
121 struct ComplexService {
122 dependency: ServiceWithDependency,
123 data: Arc<Mutex<Vec<String>>>,
124 }
125
126 impl Inject for ComplexService {
127 fn inject(container: &Container) -> Result<Self, Error> {
128 let dependency = container.resolve::<ServiceWithDependency>()?;
129 Ok(Self {
130 dependency,
131 data: Arc::new(Mutex::new(vec!["test".to_string()])),
132 })
133 }
134 }
135
136 #[derive(Debug)]
137 struct FailingService;
138
139 impl Inject for FailingService {
140 fn inject(_: &Container) -> Result<Self, Error> {
141 Err(Error::Other("Injection failed"))
142 }
143 }
144
145 #[test]
146 fn it_injects_default_service() {
147 let container = ContainerBuilder::new().build();
148
149 let result = SimpleService::inject(&container);
150
151 assert!(result.is_ok());
152 let service = result.unwrap();
153 assert_eq!(service.value, 0);
154 }
155
156 #[test]
157 #[allow(clippy::redundant_closure)]
158 fn it_injects_service_with_dependencies() {
159 let mut builder = ContainerBuilder::new();
160 builder.register_scoped_factory(|c: Container| SimpleService::inject(&c));
161 let container = builder.build().create_scope();
162
163 let result = ServiceWithDependency::inject(&container);
164
165 assert!(result.is_ok());
166 let service = result.unwrap();
167 assert_eq!(service.service.value, 0);
168 assert_eq!(service.multiplier, 2);
169 }
170
171 #[test]
172 fn it_injects_complex_service_with_nested_dependencies() {
173 let mut builder = ContainerBuilder::new();
174 builder.register_scoped::<SimpleService>();
175 builder.register_scoped::<ServiceWithDependency>();
176 let container = builder.build().create_scope();
177
178 let result = ComplexService::inject(&container);
179
180 assert!(result.is_ok());
181 let service = result.unwrap();
182 assert_eq!(service.dependency.service.value, 0);
183 assert_eq!(service.dependency.multiplier, 2);
184 let data = service.data.lock().unwrap();
185 assert_eq!(data[0], "test");
186 }
187
188 #[test]
189 fn it_fails_when_dependency_not_registered() {
190 let container = ContainerBuilder::new().build();
191
192 let result = ServiceWithDependency::inject(&container);
193
194 assert!(result.is_err());
195 }
196
197 #[test]
198 fn it_handles_injection_errors() {
199 let container = ContainerBuilder::new().build();
200
201 let result = FailingService::inject(&container);
202
203 assert!(result.is_err());
204 match result.unwrap_err() {
205 Error::Other(msg) => assert_eq!(msg, "Injection failed"),
206 _ => panic!("Expected Other error"),
207 }
208 }
209
210 #[test]
211 fn it_uses_default_trait_implementation_for_inject() {
212 let container = ContainerBuilder::new().build();
213
214 let result = <SimpleService as Inject>::inject(&container);
216
217 assert!(result.is_ok());
218 let service = result.unwrap();
219 assert_eq!(service.value, 0);
220 }
221
222 #[test]
223 fn it_resolves_same_dependency_multiple_times() {
224 let mut builder = ContainerBuilder::new();
225 builder.register_scoped::<SimpleService>();
226 let container = builder.build().create_scope();
227
228 let result1 = ServiceWithDependency::inject(&container);
229 let result2 = ServiceWithDependency::inject(&container);
230
231 assert!(result1.is_ok());
232 assert!(result2.is_ok());
233
234 let service1 = result1.unwrap();
235 let service2 = result2.unwrap();
236
237 assert_eq!(service1.service.value, service2.service.value);
239 assert_eq!(service1.multiplier, service2.multiplier);
240 }
241
242 #[test]
243 fn it_works_with_different_service_lifetimes() {
244 let mut builder = ContainerBuilder::new();
245 builder.register_singleton(SimpleService { value: 100 });
246 builder.register_transient::<ServiceWithDependency>();
247 let container = builder.build();
248
249 let result1 = ServiceWithDependency::inject(&container);
250 let result2 = ServiceWithDependency::inject(&container);
251
252 assert!(result1.is_ok());
253 assert!(result2.is_ok());
254
255 let service1 = result1.unwrap();
256 let service2 = result2.unwrap();
257
258 assert_eq!(service1.service.value, 100);
260 assert_eq!(service2.service.value, 100);
261 }
262
263 #[test]
264 fn it_tests_send_sync_requirements() {
265 fn assert_send_sync<T: Send + Sync>() {}
266
267 assert_send_sync::<SimpleService>();
269 assert_send_sync::<ServiceWithDependency>();
270 assert_send_sync::<ComplexService>();
271 }
272}
273