1use super::{AnyProvider, ModuleRef, ProviderToken};
2use crate::pipeline::ProviderEnhancerMarker;
3use crate::{
4 BootError, BoxFuture, ExceptionFilter, Guard, Interceptor, Pipe, Result,
5 TransportExceptionFilter, TransportGuard, TransportInterceptor, TransportPipe,
6 WebSocketExceptionFilter, WebSocketGuard, WebSocketInterceptor, WebSocketPipe,
7};
8use std::fmt;
9use std::future::Future;
10use std::sync::Arc;
11
12type ProviderFactory = dyn Fn(&ModuleRef) -> Result<Arc<AnyProvider>> + Send + Sync;
13type AsyncProviderFactory =
14 dyn Fn(ModuleRef) -> BoxFuture<'static, Result<Arc<AnyProvider>>> + Send + Sync;
15type ProviderModuleInitHook = dyn Fn(Arc<AnyProvider>, &ModuleRef) -> Result<()> + Send + Sync;
16type ProviderApplicationHook =
17 dyn Fn(Arc<AnyProvider>, ModuleRef) -> BoxFuture<'static, Result<()>> + Send + Sync;
18type ProviderShutdownHook = dyn Fn(Arc<AnyProvider>, ModuleRef, Option<String>) -> BoxFuture<'static, Result<()>>
19 + Send
20 + Sync;
21
22pub trait ProviderOnModuleInit: Send + Sync + 'static {
24 fn on_module_init(&self, _module_ref: &ModuleRef) -> Result<()> {
25 Ok(())
26 }
27}
28
29pub trait ProviderOnApplicationBootstrap: Send + Sync + 'static {
31 fn on_application_bootstrap(&self, _module_ref: ModuleRef) -> BoxFuture<'static, Result<()>> {
32 Box::pin(async { Ok(()) })
33 }
34}
35
36pub trait ProviderOnModuleDestroy: Send + Sync + 'static {
38 fn on_module_destroy(
39 &self,
40 _module_ref: ModuleRef,
41 _signal: Option<String>,
42 ) -> BoxFuture<'static, Result<()>> {
43 Box::pin(async { Ok(()) })
44 }
45}
46
47pub trait ProviderBeforeApplicationShutdown: Send + Sync + 'static {
49 fn before_application_shutdown(
50 &self,
51 _module_ref: ModuleRef,
52 _signal: Option<String>,
53 ) -> BoxFuture<'static, Result<()>> {
54 Box::pin(async { Ok(()) })
55 }
56}
57
58pub trait ProviderOnApplicationShutdown: Send + Sync + 'static {
60 fn on_application_shutdown(&self, _module_ref: ModuleRef) -> BoxFuture<'static, Result<()>> {
61 Box::pin(async { Ok(()) })
62 }
63
64 fn on_application_shutdown_with_signal(
65 &self,
66 module_ref: ModuleRef,
67 _signal: Option<String>,
68 ) -> BoxFuture<'static, Result<()>> {
69 self.on_application_shutdown(module_ref)
70 }
71}
72
73pub trait FromModuleRef: Sized + Send + Sync + 'static {
75 fn from_module_ref(module_ref: &ModuleRef) -> Result<Self>;
76
77 fn provider_dependencies() -> Option<Vec<ProviderDependency>> {
82 None
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum ProviderScope {
89 Singleton,
90 Request,
91 Transient,
92}
93
94#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct ProviderDependency {
97 token: ProviderToken,
98 optional: bool,
99 lazy: bool,
100}
101
102impl ProviderDependency {
103 pub fn typed<T>() -> Self
105 where
106 T: Send + Sync + 'static,
107 {
108 Self::named(ProviderToken::of::<T>().as_str())
109 }
110
111 pub fn named(token: impl Into<String>) -> Self {
113 Self {
114 token: ProviderToken::named(token),
115 optional: false,
116 lazy: false,
117 }
118 }
119
120 pub fn optional(mut self) -> Self {
122 self.optional = true;
123 self
124 }
125
126 pub fn lazy(mut self) -> Self {
128 self.lazy = true;
129 self
130 }
131
132 pub fn token(&self) -> &ProviderToken {
133 &self.token
134 }
135
136 pub fn is_optional(&self) -> bool {
137 self.optional
138 }
139
140 pub fn is_lazy(&self) -> bool {
141 self.lazy
142 }
143}
144
145#[derive(Clone)]
147pub struct ProviderDefinition {
148 token: ProviderToken,
149 factory: ProviderFactoryKind,
150 scope: ProviderScope,
151 lifecycle: ProviderLifecycleHooks,
152 alias_target: Option<ProviderToken>,
153 dependencies: Option<Arc<[ProviderDependency]>>,
154 enhancers: Arc<[ProviderEnhancerMarker]>,
155}
156
157#[derive(Clone)]
158enum ProviderFactoryKind {
159 Sync(Arc<ProviderFactory>),
160 Async(Arc<AsyncProviderFactory>),
161}
162
163#[derive(Clone, Default)]
164pub(super) struct ProviderLifecycleHooks {
165 on_module_init: Option<Arc<ProviderModuleInitHook>>,
166 on_application_bootstrap: Option<Arc<ProviderApplicationHook>>,
167 on_module_destroy: Option<Arc<ProviderShutdownHook>>,
168 before_application_shutdown: Option<Arc<ProviderShutdownHook>>,
169 on_application_shutdown: Option<Arc<ProviderShutdownHook>>,
170}
171
172impl ProviderLifecycleHooks {
173 pub(super) fn has_hooks(&self) -> bool {
174 self.on_module_init.is_some()
175 || self.on_application_bootstrap.is_some()
176 || self.on_module_destroy.is_some()
177 || self.before_application_shutdown.is_some()
178 || self.on_application_shutdown.is_some()
179 }
180
181 pub(super) fn on_module_init(&self) -> Option<&Arc<ProviderModuleInitHook>> {
182 self.on_module_init.as_ref()
183 }
184
185 pub(super) fn on_application_bootstrap(&self) -> Option<&Arc<ProviderApplicationHook>> {
186 self.on_application_bootstrap.as_ref()
187 }
188
189 pub(super) fn on_module_destroy(&self) -> Option<&Arc<ProviderShutdownHook>> {
190 self.on_module_destroy.as_ref()
191 }
192
193 pub(super) fn before_application_shutdown(&self) -> Option<&Arc<ProviderShutdownHook>> {
194 self.before_application_shutdown.as_ref()
195 }
196
197 pub(super) fn on_application_shutdown(&self) -> Option<&Arc<ProviderShutdownHook>> {
198 self.on_application_shutdown.as_ref()
199 }
200}
201
202impl fmt::Debug for ProviderDefinition {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 f.debug_struct("ProviderDefinition")
205 .field("token", &self.token)
206 .field("scope", &self.scope)
207 .field("async", &self.factory.is_async())
208 .field("alias_target", &self.alias_target)
209 .field("enhancers", &self.enhancers.len())
210 .field(
211 "dependencies",
212 &self
213 .dependencies
214 .as_ref()
215 .map(|dependencies| dependencies.len()),
216 )
217 .finish_non_exhaustive()
218 }
219}
220
221impl ProviderFactoryKind {
222 fn is_async(&self) -> bool {
223 matches!(self, Self::Async(_))
224 }
225}
226
227impl ProviderDefinition {
228 pub fn singleton<T>(value: T) -> Self
229 where
230 T: Send + Sync + 'static,
231 {
232 Self::from_arc(Arc::new(value))
233 }
234
235 pub fn named_singleton<T>(token: impl Into<String>, value: T) -> Self
236 where
237 T: Send + Sync + 'static,
238 {
239 Self::named_from_arc(token, Arc::new(value))
240 }
241
242 pub fn from_arc<T>(value: Arc<T>) -> Self
243 where
244 T: Send + Sync + 'static,
245 {
246 let token = ProviderToken::of::<T>();
247 Self::named_from_arc(token.as_str(), value)
248 }
249
250 pub fn named_from_arc<T>(token: impl Into<String>, value: Arc<T>) -> Self
251 where
252 T: Send + Sync + 'static,
253 {
254 let token = ProviderToken::named(token);
255 let factory_value = Arc::clone(&value);
256 Self {
257 token,
258 factory: ProviderFactoryKind::Sync(Arc::new(move |_| {
259 Ok(Arc::clone(&factory_value) as Arc<AnyProvider>)
260 })),
261 scope: ProviderScope::Singleton,
262 lifecycle: ProviderLifecycleHooks::default(),
263 alias_target: None,
264 dependencies: Some(Arc::from([])),
265 enhancers: Arc::from([]),
266 }
267 }
268
269 pub fn factory<T, F>(factory: F) -> Self
270 where
271 T: Send + Sync + 'static,
272 F: Fn(&ModuleRef) -> Result<T> + Send + Sync + 'static,
273 {
274 Self::named_factory(ProviderToken::of::<T>().as_str(), factory)
275 }
276
277 pub fn factory_arc<T, F>(factory: F) -> Self
278 where
279 T: Send + Sync + 'static,
280 F: Fn(&ModuleRef) -> Result<Arc<T>> + Send + Sync + 'static,
281 {
282 Self::named_factory_arc(ProviderToken::of::<T>().as_str(), factory)
283 }
284
285 pub fn named_factory<T, F>(token: impl Into<String>, factory: F) -> Self
286 where
287 T: Send + Sync + 'static,
288 F: Fn(&ModuleRef) -> Result<T> + Send + Sync + 'static,
289 {
290 Self {
291 token: ProviderToken::named(token),
292 factory: ProviderFactoryKind::Sync(Arc::new(move |module_ref| {
293 Ok(Arc::new(factory(module_ref)?) as Arc<AnyProvider>)
294 })),
295 scope: ProviderScope::Singleton,
296 lifecycle: ProviderLifecycleHooks::default(),
297 alias_target: None,
298 dependencies: None,
299 enhancers: Arc::from([]),
300 }
301 }
302
303 pub fn named_factory_arc<T, F>(token: impl Into<String>, factory: F) -> Self
304 where
305 T: Send + Sync + 'static,
306 F: Fn(&ModuleRef) -> Result<Arc<T>> + Send + Sync + 'static,
307 {
308 Self {
309 token: ProviderToken::named(token),
310 factory: ProviderFactoryKind::Sync(Arc::new(move |module_ref| {
311 Ok(factory(module_ref)? as Arc<AnyProvider>)
312 })),
313 scope: ProviderScope::Singleton,
314 lifecycle: ProviderLifecycleHooks::default(),
315 alias_target: None,
316 dependencies: None,
317 enhancers: Arc::from([]),
318 }
319 }
320
321 pub fn async_factory<T, F, Fut>(factory: F) -> Self
322 where
323 T: Send + Sync + 'static,
324 F: Fn(ModuleRef) -> Fut + Send + Sync + 'static,
325 Fut: Future<Output = Result<T>> + Send + 'static,
326 {
327 Self::named_async_factory(ProviderToken::of::<T>().as_str(), factory)
328 }
329
330 pub fn async_factory_arc<T, F, Fut>(factory: F) -> Self
331 where
332 T: Send + Sync + 'static,
333 F: Fn(ModuleRef) -> Fut + Send + Sync + 'static,
334 Fut: Future<Output = Result<Arc<T>>> + Send + 'static,
335 {
336 Self::named_async_factory_arc(ProviderToken::of::<T>().as_str(), factory)
337 }
338
339 pub fn named_async_factory<T, F, Fut>(token: impl Into<String>, factory: F) -> Self
340 where
341 T: Send + Sync + 'static,
342 F: Fn(ModuleRef) -> Fut + Send + Sync + 'static,
343 Fut: Future<Output = Result<T>> + Send + 'static,
344 {
345 Self {
346 token: ProviderToken::named(token),
347 factory: ProviderFactoryKind::Async(Arc::new(move |module_ref| {
348 let future = factory(module_ref);
349 Box::pin(async move { Ok(Arc::new(future.await?) as Arc<AnyProvider>) })
350 })),
351 scope: ProviderScope::Singleton,
352 lifecycle: ProviderLifecycleHooks::default(),
353 alias_target: None,
354 dependencies: None,
355 enhancers: Arc::from([]),
356 }
357 }
358
359 pub fn named_async_factory_arc<T, F, Fut>(token: impl Into<String>, factory: F) -> Self
360 where
361 T: Send + Sync + 'static,
362 F: Fn(ModuleRef) -> Fut + Send + Sync + 'static,
363 Fut: Future<Output = Result<Arc<T>>> + Send + 'static,
364 {
365 Self {
366 token: ProviderToken::named(token),
367 factory: ProviderFactoryKind::Async(Arc::new(move |module_ref| {
368 let future = factory(module_ref);
369 Box::pin(async move { Ok(future.await? as Arc<AnyProvider>) })
370 })),
371 scope: ProviderScope::Singleton,
372 lifecycle: ProviderLifecycleHooks::default(),
373 alias_target: None,
374 dependencies: None,
375 enhancers: Arc::from([]),
376 }
377 }
378
379 pub fn injectable<T>() -> Self
380 where
381 T: FromModuleRef,
382 {
383 let definition = Self::factory::<T, _>(T::from_module_ref);
384 match T::provider_dependencies() {
385 Some(dependencies) => definition.with_dependencies(dependencies),
386 None => definition,
387 }
388 }
389
390 pub fn named_injectable<T>(token: impl Into<String>) -> Self
391 where
392 T: FromModuleRef,
393 {
394 let definition = Self::named_factory::<T, _>(token, T::from_module_ref);
395 match T::provider_dependencies() {
396 Some(dependencies) => definition.with_dependencies(dependencies),
397 None => definition,
398 }
399 }
400
401 pub fn alias<T>(target: ProviderToken) -> Self
402 where
403 T: Send + Sync + 'static,
404 {
405 Self::named_alias(ProviderToken::of::<T>().as_str(), target)
406 }
407
408 pub fn named_alias(token: impl Into<String>, target: ProviderToken) -> Self {
409 Self {
410 token: ProviderToken::named(token),
411 factory: ProviderFactoryKind::Sync(Arc::new(|_| {
412 Err(BootError::Internal(
413 "provider aliases must be resolved through ModuleRef".to_string(),
414 ))
415 })),
416 scope: ProviderScope::Singleton,
417 lifecycle: ProviderLifecycleHooks::default(),
418 alias_target: Some(target.clone()),
419 dependencies: Some(Arc::from([ProviderDependency {
420 token: target,
421 optional: false,
422 lazy: false,
423 }])),
424 enhancers: Arc::from([]),
425 }
426 }
427
428 pub fn transient<T, F>(factory: F) -> Self
429 where
430 T: Send + Sync + 'static,
431 F: Fn(&ModuleRef) -> Result<T> + Send + Sync + 'static,
432 {
433 Self::factory::<T, _>(factory).with_scope(ProviderScope::Transient)
434 }
435
436 pub fn transient_arc<T, F>(factory: F) -> Self
437 where
438 T: Send + Sync + 'static,
439 F: Fn(&ModuleRef) -> Result<Arc<T>> + Send + Sync + 'static,
440 {
441 Self::factory_arc::<T, _>(factory).with_scope(ProviderScope::Transient)
442 }
443
444 pub fn named_transient<T, F>(token: impl Into<String>, factory: F) -> Self
445 where
446 T: Send + Sync + 'static,
447 F: Fn(&ModuleRef) -> Result<T> + Send + Sync + 'static,
448 {
449 Self::named_factory::<T, _>(token, factory).with_scope(ProviderScope::Transient)
450 }
451
452 pub fn named_transient_arc<T, F>(token: impl Into<String>, factory: F) -> Self
453 where
454 T: Send + Sync + 'static,
455 F: Fn(&ModuleRef) -> Result<Arc<T>> + Send + Sync + 'static,
456 {
457 Self::named_factory_arc::<T, _>(token, factory).with_scope(ProviderScope::Transient)
458 }
459
460 pub fn transient_injectable<T>() -> Self
461 where
462 T: FromModuleRef,
463 {
464 Self::injectable::<T>().with_scope(ProviderScope::Transient)
465 }
466
467 pub fn named_transient_injectable<T>(token: impl Into<String>) -> Self
468 where
469 T: FromModuleRef,
470 {
471 Self::named_injectable::<T>(token).with_scope(ProviderScope::Transient)
472 }
473
474 pub fn request_scoped<T, F>(factory: F) -> Self
475 where
476 T: Send + Sync + 'static,
477 F: Fn(&ModuleRef) -> Result<T> + Send + Sync + 'static,
478 {
479 Self::factory::<T, _>(factory).with_scope(ProviderScope::Request)
480 }
481
482 pub fn request_scoped_arc<T, F>(factory: F) -> Self
483 where
484 T: Send + Sync + 'static,
485 F: Fn(&ModuleRef) -> Result<Arc<T>> + Send + Sync + 'static,
486 {
487 Self::factory_arc::<T, _>(factory).with_scope(ProviderScope::Request)
488 }
489
490 pub fn named_request_scoped<T, F>(token: impl Into<String>, factory: F) -> Self
491 where
492 T: Send + Sync + 'static,
493 F: Fn(&ModuleRef) -> Result<T> + Send + Sync + 'static,
494 {
495 Self::named_factory::<T, _>(token, factory).with_scope(ProviderScope::Request)
496 }
497
498 pub fn named_request_scoped_arc<T, F>(token: impl Into<String>, factory: F) -> Self
499 where
500 T: Send + Sync + 'static,
501 F: Fn(&ModuleRef) -> Result<Arc<T>> + Send + Sync + 'static,
502 {
503 Self::named_factory_arc::<T, _>(token, factory).with_scope(ProviderScope::Request)
504 }
505
506 pub fn request_scoped_injectable<T>() -> Self
507 where
508 T: FromModuleRef,
509 {
510 Self::injectable::<T>().with_scope(ProviderScope::Request)
511 }
512
513 pub fn named_request_scoped_injectable<T>(token: impl Into<String>) -> Self
514 where
515 T: FromModuleRef,
516 {
517 Self::named_injectable::<T>(token).with_scope(ProviderScope::Request)
518 }
519
520 pub fn app_guard<T>() -> Self
522 where
523 T: FromModuleRef + Guard,
524 {
525 Self::injectable::<T>().with_app_guard::<T>()
526 }
527
528 pub fn app_pipe<T>() -> Self
530 where
531 T: FromModuleRef + Pipe,
532 {
533 Self::injectable::<T>().with_app_pipe::<T>()
534 }
535
536 pub fn app_interceptor<T>() -> Self
538 where
539 T: FromModuleRef + Interceptor,
540 {
541 Self::injectable::<T>().with_app_interceptor::<T>()
542 }
543
544 pub fn app_filter<T>() -> Self
546 where
547 T: FromModuleRef + ExceptionFilter,
548 {
549 Self::injectable::<T>().with_app_filter::<T>()
550 }
551
552 pub fn app_websocket_guard<T>() -> Self
554 where
555 T: FromModuleRef + WebSocketGuard,
556 {
557 Self::injectable::<T>().with_app_websocket_guard::<T>()
558 }
559
560 pub fn app_websocket_pipe<T>() -> Self
562 where
563 T: FromModuleRef + WebSocketPipe,
564 {
565 Self::injectable::<T>().with_app_websocket_pipe::<T>()
566 }
567
568 pub fn app_websocket_interceptor<T>() -> Self
570 where
571 T: FromModuleRef + WebSocketInterceptor,
572 {
573 Self::injectable::<T>().with_app_websocket_interceptor::<T>()
574 }
575
576 pub fn app_websocket_filter<T>() -> Self
578 where
579 T: FromModuleRef + WebSocketExceptionFilter,
580 {
581 Self::injectable::<T>().with_app_websocket_filter::<T>()
582 }
583
584 pub fn app_transport_guard<T>() -> Self
586 where
587 T: FromModuleRef + TransportGuard,
588 {
589 Self::injectable::<T>().with_app_transport_guard::<T>()
590 }
591
592 pub fn app_transport_pipe<T>() -> Self
594 where
595 T: FromModuleRef + TransportPipe,
596 {
597 Self::injectable::<T>().with_app_transport_pipe::<T>()
598 }
599
600 pub fn app_transport_interceptor<T>() -> Self
602 where
603 T: FromModuleRef + TransportInterceptor,
604 {
605 Self::injectable::<T>().with_app_transport_interceptor::<T>()
606 }
607
608 pub fn app_transport_filter<T>() -> Self
610 where
611 T: FromModuleRef + TransportExceptionFilter,
612 {
613 Self::injectable::<T>().with_app_transport_filter::<T>()
614 }
615
616 pub fn with_app_guard<T>(self) -> Self
618 where
619 T: Guard,
620 {
621 let token = self.token.clone();
622 self.with_enhancer(ProviderEnhancerMarker::guard::<T>(token))
623 }
624
625 pub fn with_app_pipe<T>(self) -> Self
627 where
628 T: Pipe,
629 {
630 let token = self.token.clone();
631 self.with_enhancer(ProviderEnhancerMarker::pipe::<T>(token))
632 }
633
634 pub fn with_app_interceptor<T>(self) -> Self
636 where
637 T: Interceptor,
638 {
639 let token = self.token.clone();
640 self.with_enhancer(ProviderEnhancerMarker::interceptor::<T>(token))
641 }
642
643 pub fn with_app_filter<T>(self) -> Self
645 where
646 T: ExceptionFilter,
647 {
648 let token = self.token.clone();
649 self.with_enhancer(ProviderEnhancerMarker::filter::<T>(token))
650 }
651
652 pub fn with_app_websocket_guard<T>(self) -> Self
654 where
655 T: WebSocketGuard,
656 {
657 let token = self.token.clone();
658 self.with_enhancer(ProviderEnhancerMarker::websocket_guard::<T>(token))
659 }
660
661 pub fn with_app_websocket_pipe<T>(self) -> Self
663 where
664 T: WebSocketPipe,
665 {
666 let token = self.token.clone();
667 self.with_enhancer(ProviderEnhancerMarker::websocket_pipe::<T>(token))
668 }
669
670 pub fn with_app_websocket_interceptor<T>(self) -> Self
672 where
673 T: WebSocketInterceptor,
674 {
675 let token = self.token.clone();
676 self.with_enhancer(ProviderEnhancerMarker::websocket_interceptor::<T>(token))
677 }
678
679 pub fn with_app_websocket_filter<T>(self) -> Self
681 where
682 T: WebSocketExceptionFilter,
683 {
684 let token = self.token.clone();
685 self.with_enhancer(ProviderEnhancerMarker::websocket_filter::<T>(token))
686 }
687
688 pub fn with_app_transport_guard<T>(self) -> Self
690 where
691 T: TransportGuard,
692 {
693 let token = self.token.clone();
694 self.with_enhancer(ProviderEnhancerMarker::transport_guard::<T>(token))
695 }
696
697 pub fn with_app_transport_pipe<T>(self) -> Self
699 where
700 T: TransportPipe,
701 {
702 let token = self.token.clone();
703 self.with_enhancer(ProviderEnhancerMarker::transport_pipe::<T>(token))
704 }
705
706 pub fn with_app_transport_interceptor<T>(self) -> Self
708 where
709 T: TransportInterceptor,
710 {
711 let token = self.token.clone();
712 self.with_enhancer(ProviderEnhancerMarker::transport_interceptor::<T>(token))
713 }
714
715 pub fn with_app_transport_filter<T>(self) -> Self
717 where
718 T: TransportExceptionFilter,
719 {
720 let token = self.token.clone();
721 self.with_enhancer(ProviderEnhancerMarker::transport_filter::<T>(token))
722 }
723
724 pub fn with_scope(mut self, scope: ProviderScope) -> Self {
725 self.scope = scope;
726 self
727 }
728
729 fn with_enhancer(mut self, enhancer: ProviderEnhancerMarker) -> Self {
730 let mut enhancers = self.enhancers.to_vec();
731 enhancers.push(enhancer);
732 self.enhancers = enhancers.into();
733 self
734 }
735
736 pub fn with_dependencies<I>(mut self, dependencies: I) -> Self
738 where
739 I: IntoIterator<Item = ProviderDependency>,
740 {
741 self.dependencies = Some(dependencies.into_iter().collect::<Vec<_>>().into());
742 self
743 }
744
745 pub fn depends_on<T>(self) -> Self
747 where
748 T: Send + Sync + 'static,
749 {
750 self.with_dependency(ProviderDependency::typed::<T>())
751 }
752
753 pub fn depends_on_named(self, token: impl Into<String>) -> Self {
755 self.with_dependency(ProviderDependency::named(token))
756 }
757
758 pub fn with_dependency(mut self, dependency: ProviderDependency) -> Self {
760 let mut dependencies = self
761 .dependencies
762 .as_deref()
763 .map(<[ProviderDependency]>::to_vec)
764 .unwrap_or_default();
765 dependencies.push(dependency);
766 self.dependencies = Some(dependencies.into());
767 self
768 }
769
770 pub fn with_on_module_init<T>(mut self) -> Self
771 where
772 T: ProviderOnModuleInit,
773 {
774 self.lifecycle.on_module_init = Some(Arc::new(|provider, module_ref| {
775 let provider = downcast_lifecycle_provider::<T>(provider)?;
776 provider.on_module_init(module_ref)
777 }));
778 self
779 }
780
781 pub fn with_on_application_bootstrap<T>(mut self) -> Self
782 where
783 T: ProviderOnApplicationBootstrap,
784 {
785 self.lifecycle.on_application_bootstrap =
786 Some(Arc::new(
787 |provider, module_ref| match downcast_lifecycle_provider::<T>(provider) {
788 Ok(provider) => provider.on_application_bootstrap(module_ref),
789 Err(error) => Box::pin(async move { Err(error) }),
790 },
791 ));
792 self
793 }
794
795 pub fn with_on_module_destroy<T>(mut self) -> Self
796 where
797 T: ProviderOnModuleDestroy,
798 {
799 self.lifecycle.on_module_destroy =
800 Some(Arc::new(
801 |provider, module_ref, signal| match downcast_lifecycle_provider::<T>(provider) {
802 Ok(provider) => provider.on_module_destroy(module_ref, signal),
803 Err(error) => Box::pin(async move { Err(error) }),
804 },
805 ));
806 self
807 }
808
809 pub fn with_before_application_shutdown<T>(mut self) -> Self
810 where
811 T: ProviderBeforeApplicationShutdown,
812 {
813 self.lifecycle.before_application_shutdown = Some(Arc::new(
814 |provider, module_ref, signal| match downcast_lifecycle_provider::<T>(provider) {
815 Ok(provider) => provider.before_application_shutdown(module_ref, signal),
816 Err(error) => Box::pin(async move { Err(error) }),
817 },
818 ));
819 self
820 }
821
822 pub fn with_on_application_shutdown<T>(mut self) -> Self
823 where
824 T: ProviderOnApplicationShutdown,
825 {
826 self.lifecycle.on_application_shutdown =
827 Some(Arc::new(
828 |provider, module_ref, signal| match downcast_lifecycle_provider::<T>(provider) {
829 Ok(provider) => {
830 provider.on_application_shutdown_with_signal(module_ref, signal)
831 }
832 Err(error) => Box::pin(async move { Err(error) }),
833 },
834 ));
835 self
836 }
837
838 pub fn token(&self) -> &ProviderToken {
839 &self.token
840 }
841
842 pub fn scope(&self) -> ProviderScope {
843 self.scope
844 }
845
846 pub fn dependencies(&self) -> Option<&[ProviderDependency]> {
848 self.dependencies.as_deref()
849 }
850
851 pub(super) fn is_alias(&self) -> bool {
852 self.alias_target.is_some()
853 }
854
855 pub(super) fn is_async_factory(&self) -> bool {
856 self.factory.is_async()
857 }
858
859 pub(super) fn alias_target(&self) -> Option<&ProviderToken> {
860 self.alias_target.as_ref()
861 }
862
863 pub(super) fn lifecycle(&self) -> &ProviderLifecycleHooks {
864 &self.lifecycle
865 }
866
867 pub(crate) fn enhancer_markers(&self) -> &[ProviderEnhancerMarker] {
868 &self.enhancers
869 }
870
871 pub(crate) fn with_enhancers_from(mut self, source: &Self) -> Self {
872 self.enhancers = Arc::clone(&source.enhancers);
873 self
874 }
875
876 pub(super) fn build(&self, module_ref: &ModuleRef) -> Result<Arc<AnyProvider>> {
877 match &self.factory {
878 ProviderFactoryKind::Sync(factory) => factory(module_ref),
879 ProviderFactoryKind::Async(_) => Err(BootError::Internal(format!(
880 "async provider factory requires async application build: {}",
881 self.token
882 ))),
883 }
884 }
885
886 pub(super) async fn build_async(&self, module_ref: ModuleRef) -> Result<Arc<AnyProvider>> {
887 match &self.factory {
888 ProviderFactoryKind::Sync(factory) => factory(&module_ref),
889 ProviderFactoryKind::Async(factory) => factory(module_ref).await,
890 }
891 }
892}
893
894fn downcast_lifecycle_provider<T>(provider: Arc<AnyProvider>) -> Result<Arc<T>>
895where
896 T: Send + Sync + 'static,
897{
898 Arc::downcast::<T>(provider)
899 .map_err(|_| BootError::ProviderTypeMismatch(std::any::type_name::<T>().to_string()))
900}