1mod container;
76mod inject;
77mod provider;
78mod types;
79
80use cfg_block::cfg_block;
81pub use container::{Container, ContainerBuilder};
82pub use inject::Injectable;
83pub use provider::{CloneProvider, CopyProvider, Provider, cloned, copied};
84pub use types::SyncBounds;
85
86#[macro_export]
102macro_rules! container {
103 (@replace_expr $_expr:expr, $sub:expr) => {
104 $sub
105 };
106 (@count_exprs $( $expr:expr ),* $(,)?) => {
107 <[()]>::len(&[$($crate::container!(@replace_expr $expr, ())),*])
108 };
109 (providers: [$( $provider:expr ),* $(,)?] $(,)?) => {{
110 $crate::Container::builder_with_capacity(
111 $crate::container!(@count_exprs $($provider),*),
112 )
113 $(.provider($provider))*
114 .build()
115 }};
116}
117
118cfg_block! {
119 if #[cfg(feature = "validation")] {
120 pub use container::DeclaredDependency;
121 pub use inventory;
122
123 #[macro_export]
139 macro_rules! declare_dependency {
140 ($ty:ty) => {
141 $crate::inventory::submit! {
142 $crate::DeclaredDependency {
143 type_id: ::std::any::TypeId::of::<$ty>,
144 type_name: ::std::stringify!($ty),
145 }
146 }
147 };
148 }
149 } else {
150 #[macro_export]
152 macro_rules! declare_dependency {
153 ($ty:ty) => {};
154 }
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use std::sync::Arc;
161
162 use crate::{Container, cloned, copied};
163
164 #[test]
165 fn empty_providers() {
166 let c = container! {
167 providers: []
168 };
169 assert_eq!(c.provider_count(), 0);
170 }
171
172 #[test]
173 fn only_closure_providers() {
174 let c = container! {
175 providers: [|_c: &Container| 1_u32, |_c: &Container| 2_u64]
176 };
177 assert_eq!(c.provider_count(), 2);
178 }
179
180 #[test]
181 fn cloned_and_closure_providers() {
182 let c = container! {
183 providers: [
184 cloned(41_u16),
185 |_c: &Container| 42_u32,
186 |_c: &Container| "hello",
187 ]
188 };
189 assert_eq!(c.provider_count(), 3);
190 }
191
192 #[test]
193 fn providers_with_trailing_comma() {
194 let c = container! {
195 providers: [Arc::new(1_u32), |_c: &Container| 2_u64,]
196 };
197 assert_eq!(c.provider_count(), 2);
198 }
199
200 #[test]
201 fn only_providers_empty() {
202 let c = container! {
203 providers: []
204 };
205 assert_eq!(c.provider_count(), 0);
206 }
207
208 #[test]
209 fn get_from_arc_and_closure_providers() {
210 let c = container! {
211 providers: [Arc::new(1_u32), |_c: &Container| 99_u64]
212 };
213 assert_eq!(c.provider_count(), 2);
214 assert_eq!(*c.get::<Arc<u32>>(), 1);
215 assert_eq!(c.get::<u64>(), 99);
216 }
217
218 #[test]
219 fn with_capacity_builder() {
220 let c = Container::builder_with_capacity(3)
221 .provider(Arc::new(1_u32))
222 .provider(|_c: &Container| 2_u64)
223 .provider(|_c: &Container| 3_u8)
224 .build();
225
226 assert_eq!(c.provider_count(), 3);
227 assert_eq!(c.get::<u8>(), 3);
228 }
229
230 #[test]
231 fn get_clones_explicit_clone_providers() {
232 let c = container! { providers: [cloned(String::from("shared"))] };
233
234 assert_eq!(c.get::<String>(), "shared");
235 }
236
237 #[test]
238 fn get_copies_explicit_copy_providers() {
239 let c = container! { providers: [copied(7_u32)] };
240
241 assert_eq!(c.get::<u32>(), 7);
242 }
243
244 #[test]
245 fn get_executes_closure_providers() {
246 let c = container! {
247 providers: [|_c: &Container| String::from("factory")]
248 };
249
250 assert_eq!(c.get::<String>(), "factory");
251 }
252
253 #[test]
254 fn builder_contains_registered_output_type() {
255 let builder = Container::builder().provider(Arc::new(String::from("shared")));
256
257 assert!(builder.contains::<Arc<String>>());
258 assert!(builder.contains_provider::<Arc<String>>());
259 assert!(!builder.contains::<u32>());
260 }
261
262 #[test]
263 #[should_panic(
264 expected = "provider already registered for `alloc::sync::Arc<alloc::string::String>`"
265 )]
266 fn duplicate_arc_provider_panics() {
267 let _ = Container::builder()
268 .provider(Arc::new(String::from("first")))
269 .provider(Arc::new(String::from("second")));
270 }
271
272 #[test]
273 #[should_panic(
274 expected = "provider already registered for `alloc::sync::Arc<alloc::string::String>`"
275 )]
276 fn closure_and_arc_provider_conflict_panics() {
277 let _ = Container::builder()
278 .provider(Arc::new(String::from("shared")))
279 .provider(|_c: &Container| Arc::new(String::from("factory")));
280 }
281
282 #[test]
283 #[should_panic(expected = "provider already registered for `alloc::string::String`")]
284 fn duplicate_closure_provider_panics() {
285 let _ = Container::builder()
286 .provider(|_c: &Container| String::from("first"))
287 .provider(|_c: &Container| String::from("second"));
288 }
289}