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: ?Sized + Send + Sync + 'static>(mut self, v: Arc<T>) -> Self {
266 let ff: ServiceFactory = Arc::new(move |_| Arc::new(v.clone()));
267 self.descriptors.push(ServiceDescriptor {
268 type_id: std::any::TypeId::of::<T>(),
269 type_name: std::any::type_name::<T>(),
270 key: None,
271 factory: ff,
272 keyed_factory: None,
273 async_factory: None,
274 lifetime: ServiceLifetime::Singleton,
275 });
276 self
277 }
278
279 pub fn singleton_value<T: Send + Sync + 'static>(self, v: T) -> Self {
280 self.instance(Arc::new(v))
281 }
282
283 pub fn build(self) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
284 self.build_with(crate::provider::ServiceProviderOptions::default())
285 }
286
287 pub fn build_with(
294 self,
295 options: crate::provider::ServiceProviderOptions,
296 ) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
297 crate::provider::ServiceProvider::new_with(self.into_store(), options)
298 }
299
300 pub async fn build_async(
309 self,
310 ) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
311 self.build_async_with(crate::provider::ServiceProviderOptions::default())
312 .await
313 }
314
315 pub async fn build_async_with(
317 self,
318 options: crate::provider::ServiceProviderOptions,
319 ) -> Result<Arc<crate::provider::ServiceProvider>, crate::error::RdiError> {
320 crate::provider::ServiceProvider::new_async_with(self.into_store(), options).await
321 }
322
323 fn into_store(self) -> crate::entry::ServiceStore {
328 let mut s = crate::entry::ServiceStore::new();
329 for (n, d) in self.descriptors.into_iter().enumerate() {
330 let e = crate::entry::ServiceEntry {
331 cache_key: n,
332 key: d.key,
333 type_name: d.type_name,
334 factory: d.factory,
335 keyed_factory: d.keyed_factory,
336 async_factory: d.async_factory,
337 lifetime: d.lifetime,
338 };
339 s.entry(d.type_id).or_default().push(e);
340 }
341 s
342 }
343
344 #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
347 pub fn from_injected() -> Self {
348 let mut descriptors = Vec::new();
349 for reg in inventory::iter::<ServiceRegistration> {
350 let factory: ServiceFactory = Arc::new(move |r| (reg.factory)(r));
351 descriptors.push(ServiceDescriptor {
352 type_id: reg.type_id,
353 type_name: (reg.type_name_fn)(),
354 key: None,
355 factory,
356 keyed_factory: None,
357 async_factory: None,
358 lifetime: reg.lifetime,
359 });
360 }
361 Self { descriptors }
362 }
363
364 fn push<T: ?Sized + Send + Sync + 'static>(
366 &mut self,
367 lt: ServiceLifetime,
368 key: Option<ServiceKey>,
369 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
370 ) {
371 let sf: ServiceFactory = Arc::new(move |r| {
372 let val: Arc<T> = (f)(r);
373 Arc::new(val) as Arc<dyn Any + Send + Sync>
374 });
375 self.descriptors.push(ServiceDescriptor {
376 type_id: std::any::TypeId::of::<T>(),
377 type_name: std::any::type_name::<T>(),
378 key,
379 factory: sf,
380 keyed_factory: None,
381 async_factory: None,
382 lifetime: lt,
383 });
384 }
385
386 fn push_keyed<T: ?Sized + Send + Sync + 'static>(
388 &mut self,
389 lt: ServiceLifetime,
390 key: ServiceKey,
391 f: impl Fn(&dyn crate::entry::IServiceResolver) -> Arc<T> + Send + Sync + 'static,
392 ) {
393 self.push(lt, Some(key), f);
394 }
395
396 fn push_any_keyed<T: ?Sized + Send + Sync + 'static>(
398 &mut self,
399 lt: ServiceLifetime,
400 f: impl Fn(&dyn crate::entry::IServiceResolver, &ServiceKey) -> Arc<T> + Send + Sync + 'static,
401 ) {
402 let keyed: KeyedServiceFactory = Arc::new(move |r, key| {
403 let val: Arc<T> = (f)(r, key);
404 Arc::new(val) as Arc<dyn Any + Send + Sync>
405 });
406 let stub: ServiceFactory = Arc::new(|_| {
410 std::panic::panic_any(crate::error::RdiError::FactoryPanic {
411 service: "AnyKey registration".into(),
412 payload: "AnyKey registrations require a requested key and cannot be \
413 resolved without one"
414 .into(),
415 })
416 });
417 self.descriptors.push(ServiceDescriptor {
418 type_id: std::any::TypeId::of::<T>(),
419 type_name: std::any::type_name::<T>(),
420 key: Some(ServiceKey::any_key()),
421 factory: stub,
422 keyed_factory: Some(keyed),
423 async_factory: None,
424 lifetime: lt,
425 });
426 }
427
428 fn push_async<T: ?Sized + Send + Sync + 'static>(
430 &mut self,
431 lt: ServiceLifetime,
432 key: Option<ServiceKey>,
433 f: impl Fn(
434 Arc<crate::provider::ServiceProvider>,
435 ) -> Pin<Box<dyn Future<Output = Arc<T>> + Send>>
436 + Send
437 + Sync
438 + 'static,
439 ) {
440 let af: AsyncServiceFactory = Arc::new(move |sp: Arc<crate::provider::ServiceProvider>| {
441 let fut = (f)(sp);
442 Box::pin(async move {
443 let val: Arc<T> = fut.await;
444 Arc::new(val) as Arc<dyn Any + Send + Sync>
445 }) as Pin<Box<dyn Future<Output = Arc<dyn Any + Send + Sync>> + Send>>
446 });
447 let type_name = std::any::type_name::<T>();
449 let sf: ServiceFactory = Arc::new(move |_| {
450 std::panic::panic_any(crate::error::RdiError::AsyncServiceRequiresGetAsync {
451 service: type_name.to_string(),
452 })
453 });
454 self.descriptors.push(ServiceDescriptor {
455 type_id: std::any::TypeId::of::<T>(),
456 type_name,
457 key,
458 factory: sf,
459 keyed_factory: None,
460 async_factory: Some(af),
461 lifetime: lt,
462 });
463 }
464}
465
466impl Default for ServiceCollection {
467 fn default() -> Self {
468 Self::new()
469 }
470}