1use crate::entry::{
2 AsyncServiceFactory, KeyedServiceFactory, ServiceDescriptor, ServiceFactory, ServiceLifetime,
3};
4use crate::key::ServiceKey;
5use crate::registration::ServiceRegistration;
6use std::any::Any;
7use std::future::Future;
8use std::pin::Pin;
9use std::sync::Arc;
10
11pub struct ServiceCollection {
12 descriptors: Vec<ServiceDescriptor>,
13}
14
15impl ServiceCollection {
16 pub fn new() -> Self {
17 Self {
18 descriptors: Vec::new(),
19 }
20 }
21
22 pub fn singleton<T: ?Sized + Send + Sync + 'static>(
23 mut self,
24 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
25 ) -> Self {
26 self.push(ServiceLifetime::Singleton, None, f);
27 self
28 }
29
30 pub fn transient<T: ?Sized + Send + Sync + 'static>(
31 mut self,
32 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
33 ) -> Self {
34 self.push(ServiceLifetime::Transient, None, f);
35 self
36 }
37
38 pub fn scoped<T: ?Sized + Send + Sync + 'static>(
39 mut self,
40 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
41 ) -> Self {
42 self.push(ServiceLifetime::Scoped, None, f);
43 self
44 }
45
46 pub fn keyed_singleton<T: ?Sized + Send + Sync + 'static>(
51 mut self,
52 k: impl Into<ServiceKey>,
53 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
54 ) -> Self {
55 self.push_keyed(ServiceLifetime::Singleton, k.into(), f);
56 self
57 }
58
59 pub fn keyed_transient<T: ?Sized + Send + Sync + 'static>(
61 mut self,
62 k: impl Into<ServiceKey>,
63 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
64 ) -> Self {
65 self.push_keyed(ServiceLifetime::Transient, k.into(), f);
66 self
67 }
68
69 pub fn keyed_scoped<T: ?Sized + Send + Sync + 'static>(
71 mut self,
72 k: impl Into<ServiceKey>,
73 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
74 ) -> Self {
75 self.push_keyed(ServiceLifetime::Scoped, k.into(), f);
76 self
77 }
78
79 pub fn keyed_any_singleton<T: ?Sized + Send + Sync + 'static>(
84 mut self,
85 f: impl Fn(&dyn crate::entry::IServiceResolver, &ServiceKey) -> Arc<T> + Send + Sync + 'static,
86 ) -> Self {
87 self.push_any_keyed(ServiceLifetime::Singleton, f);
88 self
89 }
90
91 pub fn keyed_any_scoped<T: ?Sized + Send + Sync + 'static>(
94 mut self,
95 f: impl Fn(&dyn crate::entry::IServiceResolver, &ServiceKey) -> Arc<T> + Send + Sync + 'static,
96 ) -> Self {
97 self.push_any_keyed(ServiceLifetime::Scoped, f);
98 self
99 }
100
101 pub fn keyed_any_transient<T: ?Sized + Send + Sync + 'static>(
104 mut self,
105 f: impl Fn(&dyn crate::entry::IServiceResolver, &ServiceKey) -> Arc<T> + Send + Sync + 'static,
106 ) -> Self {
107 self.push_any_keyed(ServiceLifetime::Transient, f);
108 self
109 }
110
111 pub fn async_singleton<T: ?Sized + Send + Sync + 'static>(
118 mut self,
119 f: impl Fn(
120 Arc<crate::provider::ServiceProvider>,
121 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
122 + Send
123 + Sync
124 + 'static,
125 ) -> Self {
126 self.push_async(ServiceLifetime::Singleton, None, f);
127 self
128 }
129
130 pub fn async_transient<T: ?Sized + Send + Sync + 'static>(
132 mut self,
133 f: impl Fn(
134 Arc<crate::provider::ServiceProvider>,
135 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
136 + Send
137 + Sync
138 + 'static,
139 ) -> Self {
140 self.push_async(ServiceLifetime::Transient, None, f);
141 self
142 }
143
144 pub fn async_scoped<T: ?Sized + Send + Sync + 'static>(
146 mut self,
147 f: impl Fn(
148 Arc<crate::provider::ServiceProvider>,
149 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
150 + Send
151 + Sync
152 + 'static,
153 ) -> Self {
154 self.push_async(ServiceLifetime::Scoped, None, f);
155 self
156 }
157
158 pub fn async_keyed_singleton<T: ?Sized + Send + Sync + 'static>(
160 mut self,
161 k: impl Into<ServiceKey>,
162 f: impl Fn(
163 Arc<crate::provider::ServiceProvider>,
164 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
165 + Send
166 + Sync
167 + 'static,
168 ) -> Self {
169 self.push_async(ServiceLifetime::Singleton, Some(k.into()), f);
170 self
171 }
172
173 pub fn async_keyed_transient<T: ?Sized + Send + Sync + 'static>(
175 mut self,
176 k: impl Into<ServiceKey>,
177 f: impl Fn(
178 Arc<crate::provider::ServiceProvider>,
179 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
180 + Send
181 + Sync
182 + 'static,
183 ) -> Self {
184 self.push_async(ServiceLifetime::Transient, Some(k.into()), f);
185 self
186 }
187
188 pub fn async_keyed_scoped<T: ?Sized + Send + Sync + 'static>(
190 mut self,
191 k: impl Into<ServiceKey>,
192 f: impl Fn(
193 Arc<crate::provider::ServiceProvider>,
194 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
195 + Send
196 + Sync
197 + 'static,
198 ) -> Self {
199 self.push_async(ServiceLifetime::Scoped, Some(k.into()), f);
200 self
201 }
202
203 pub fn try_add<T: ?Sized + Send + Sync + 'static>(
204 self,
205 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
206 ) -> Self {
207 self.try_add_with_lifetime(ServiceLifetime::Singleton, f)
208 }
209
210 pub fn try_add_singleton<T: ?Sized + Send + Sync + 'static>(
212 self,
213 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
214 ) -> Self {
215 self.try_add_with_lifetime(ServiceLifetime::Singleton, f)
216 }
217
218 pub fn try_add_scoped<T: ?Sized + Send + Sync + 'static>(
220 self,
221 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
222 ) -> Self {
223 self.try_add_with_lifetime(ServiceLifetime::Scoped, f)
224 }
225
226 pub fn try_add_transient<T: ?Sized + Send + Sync + 'static>(
228 self,
229 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
230 ) -> Self {
231 self.try_add_with_lifetime(ServiceLifetime::Transient, f)
232 }
233
234 fn try_add_with_lifetime<T: ?Sized + Send + Sync + 'static>(
235 mut self,
236 lt: ServiceLifetime,
237 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
238 ) -> Self {
239 let tid = std::any::TypeId::of::<T>();
240 if self
241 .descriptors
242 .iter()
243 .any(|d| d.type_id == tid && d.key.is_none())
244 {
245 return self;
246 }
247 self.push(lt, None, f);
248 self
249 }
250
251 pub fn add<T: ?Sized + Send + Sync + 'static>(
252 mut self,
253 lt: ServiceLifetime,
254 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
255 ) -> Self {
256 self.push(lt, None, f);
257 self
258 }
259
260 pub fn instance<T: Send + Sync + 'static>(mut self, v: Arc<T>) -> Self {
261 let ff: ServiceFactory = Arc::new(move |_| Arc::new(v.clone()));
262 self.descriptors.push(ServiceDescriptor {
263 type_id: std::any::TypeId::of::<T>(),
264 type_name: std::any::type_name::<T>(),
265 key: None,
266 factory: ff,
267 keyed_factory: None,
268 async_factory: None,
269 lifetime: ServiceLifetime::Singleton,
270 });
271 self
272 }
273
274 pub fn singleton_value<T: Send + Sync + 'static>(self, v: T) -> Self {
275 self.instance(Arc::new(v))
276 }
277
278 pub fn build(self) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
279 self.build_with(crate::provider::ServiceProviderOptions::default())
280 }
281
282 pub fn build_with(
289 self,
290 options: crate::provider::ServiceProviderOptions,
291 ) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
292 crate::provider::ServiceProvider::new_with(self.into_store(), options)
293 }
294
295 pub async fn build_async(
304 self,
305 ) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
306 self.build_async_with(crate::provider::ServiceProviderOptions::default())
307 .await
308 }
309
310 pub async fn build_async_with(
312 self,
313 options: crate::provider::ServiceProviderOptions,
314 ) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
315 crate::provider::ServiceProvider::new_async_with(self.into_store(), options).await
316 }
317
318 fn into_store(self) -> crate::entry::ServiceStore {
323 let mut s = crate::entry::ServiceStore::new();
324 for (n, d) in self.descriptors.into_iter().enumerate() {
325 let e = crate::entry::ServiceEntry {
326 cache_key: n,
327 key: d.key,
328 type_name: d.type_name,
329 factory: d.factory,
330 keyed_factory: d.keyed_factory,
331 async_factory: d.async_factory,
332 lifetime: d.lifetime,
333 };
334 s.entry(d.type_id).or_default().push(e);
335 }
336 s
337 }
338
339 #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
342 pub fn from_injected() -> Self {
343 let mut descriptors = Vec::new();
344 for reg in inventory::iter::<ServiceRegistration> {
345 let factory: ServiceFactory = Arc::new(move |r| (reg.factory)(r));
346 descriptors.push(ServiceDescriptor {
347 type_id: reg.type_id,
348 type_name: (reg.type_name_fn)(),
349 key: None,
350 factory,
351 keyed_factory: None,
352 async_factory: None,
353 lifetime: reg.lifetime,
354 });
355 }
356 Self { descriptors }
357 }
358
359 fn push<T: ?Sized + Send + Sync + 'static>(
361 &mut self,
362 lt: ServiceLifetime,
363 key: Option<ServiceKey>,
364 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
365 ) {
366 let sf: ServiceFactory = Arc::new(move |r| {
367 let val: Arc<T> = (f)(r);
368 Arc::new(val) as Arc<dyn Any + Send + Sync>
369 });
370 self.descriptors.push(ServiceDescriptor {
371 type_id: std::any::TypeId::of::<T>(),
372 type_name: std::any::type_name::<T>(),
373 key,
374 factory: sf,
375 keyed_factory: None,
376 async_factory: None,
377 lifetime: lt,
378 });
379 }
380
381 fn push_keyed<T: ?Sized + Send + Sync + 'static>(
383 &mut self,
384 lt: ServiceLifetime,
385 key: ServiceKey,
386 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
387 ) {
388 self.push(lt, Some(key), f);
389 }
390
391 fn push_any_keyed<T: ?Sized + Send + Sync + 'static>(
393 &mut self,
394 lt: ServiceLifetime,
395 f: impl Fn(&dyn crate::entry::IServiceResolver, &ServiceKey) -> Arc<T> + Send + Sync + 'static,
396 ) {
397 let keyed: KeyedServiceFactory = Arc::new(move |r, key| {
398 let val: Arc<T> = (f)(r, key);
399 Arc::new(val) as Arc<dyn Any + Send + Sync>
400 });
401 let stub: ServiceFactory = Arc::new(|_| {
405 std::panic::panic_any(crate::error::RdiError::FactoryPanic {
406 service: "AnyKey registration".into(),
407 payload: "AnyKey registrations require a requested key and cannot be \
408 resolved without one"
409 .into(),
410 })
411 });
412 self.descriptors.push(ServiceDescriptor {
413 type_id: std::any::TypeId::of::<T>(),
414 type_name: std::any::type_name::<T>(),
415 key: Some(ServiceKey::any_key()),
416 factory: stub,
417 keyed_factory: Some(keyed),
418 async_factory: None,
419 lifetime: lt,
420 });
421 }
422
423 fn push_async<T: ?Sized + Send + Sync + 'static>(
425 &mut self,
426 lt: ServiceLifetime,
427 key: Option<ServiceKey>,
428 f: impl Fn(
429 Arc<crate::provider::ServiceProvider>,
430 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
431 + Send
432 + Sync
433 + 'static,
434 ) {
435 let af: AsyncServiceFactory = Arc::new(move |sp: Arc<crate::provider::ServiceProvider>| {
436 let fut = (f)(sp);
437 Box::pin(async move {
438 let val: Arc<T> = fut.await;
439 Arc::new(val) as Arc<dyn Any + Send + Sync>
440 }) as Pin<Box<dyn Future<Output = Arc<dyn Any + Send + Sync>> + Send>>
441 });
442 let type_name = std::any::type_name::<T>();
444 let sf: ServiceFactory = Arc::new(move |_| {
445 std::panic::panic_any(crate::error::RdiError::AsyncServiceRequiresGetAsync {
446 service: type_name.to_string(),
447 })
448 });
449 self.descriptors.push(ServiceDescriptor {
450 type_id: std::any::TypeId::of::<T>(),
451 type_name,
452 key,
453 factory: sf,
454 keyed_factory: None,
455 async_factory: Some(af),
456 lifetime: lt,
457 });
458 }
459}
460
461impl Default for ServiceCollection {
462 fn default() -> Self {
463 Self::new()
464 }
465}