1#![forbid(unsafe_code)]
2
3use blazingly_contract::OperationFailure;
4use core::any::{Any, TypeId};
5use core::fmt;
6use core::future::Future;
7use core::ops::Deref;
8use core::pin::Pin;
9use std::rc::Rc;
10
11#[derive(Clone, Debug)]
13pub struct Depends<T> {
14 value: Rc<T>,
15}
16
17impl<T> Depends<T> {
18 #[doc(hidden)]
19 #[must_use]
20 pub const fn from_rc(value: Rc<T>) -> Self {
21 Self { value }
22 }
23
24 #[must_use]
25 pub fn into_inner(self) -> Rc<T> {
26 self.value
27 }
28}
29
30impl<T> Deref for Depends<T> {
31 type Target = T;
32
33 fn deref(&self) -> &Self::Target {
34 &self.value
35 }
36}
37
38#[derive(Clone, Copy, Debug, Eq, PartialEq)]
40pub enum DependencyLifetime {
41 Singleton,
43 Request,
45 Transient,
47}
48
49#[derive(Clone, Copy, Eq, Hash, PartialEq)]
51pub struct DependencyKey {
52 type_id: TypeId,
53 type_name: &'static str,
54}
55
56impl DependencyKey {
57 #[must_use]
58 pub fn of<T: 'static>() -> Self {
59 Self {
60 type_id: TypeId::of::<T>(),
61 type_name: core::any::type_name::<T>(),
62 }
63 }
64
65 #[must_use]
66 pub const fn type_id(self) -> TypeId {
67 self.type_id
68 }
69
70 #[must_use]
71 pub const fn type_name(self) -> &'static str {
72 self.type_name
73 }
74}
75
76impl fmt::Debug for DependencyKey {
77 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
78 formatter
79 .debug_tuple("DependencyKey")
80 .field(&self.type_name)
81 .finish()
82 }
83}
84
85#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
87pub struct DependencyRequest {
88 key: DependencyKey,
89}
90
91impl DependencyRequest {
92 #[must_use]
93 pub fn of<T: 'static>() -> Self {
94 Self {
95 key: DependencyKey::of::<T>(),
96 }
97 }
98
99 #[must_use]
100 pub const fn key(self) -> DependencyKey {
101 self.key
102 }
103}
104
105#[derive(Clone, Debug, PartialEq)]
107pub enum DependencyError {
108 Rejected(OperationFailure),
109 Internal { code: &'static str, message: String },
110}
111
112impl DependencyError {
113 #[must_use]
114 pub const fn rejected(failure: OperationFailure) -> Self {
115 Self::Rejected(failure)
116 }
117
118 #[must_use]
119 pub fn internal(code: &'static str, message: impl Into<String>) -> Self {
120 Self::Internal {
121 code,
122 message: message.into(),
123 }
124 }
125}
126
127impl fmt::Display for DependencyError {
128 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
129 match self {
130 Self::Rejected(failure) => write!(formatter, "{}", failure.message),
131 Self::Internal { message, .. } => formatter.write_str(message),
132 }
133 }
134}
135
136impl std::error::Error for DependencyError {}
137
138#[doc(hidden)]
139pub type DependencyValue = Rc<dyn Any>;
140
141#[doc(hidden)]
143#[derive(Clone, Copy, Debug, Eq, PartialEq)]
144pub enum DependencySlot {
145 Singleton(usize),
146 Request(usize),
147}
148
149#[doc(hidden)]
151#[derive(Clone)]
152pub struct CompiledProvider {
153 runner: ProviderRunner,
154 finalizer: Option<ProviderFinalizer>,
155}
156
157type SyncProviderRunner = Rc<
158 dyn Fn(
159 &[Option<DependencyValue>],
160 &[Option<DependencyValue>],
161 ) -> Result<DependencyValue, DependencyError>,
162>;
163type ProviderFuture =
164 Pin<Box<dyn Future<Output = Result<DependencyValue, DependencyError>> + 'static>>;
165type AsyncProviderRunner =
166 Rc<dyn Fn(&[Option<DependencyValue>], &[Option<DependencyValue>]) -> ProviderFuture>;
167
168#[derive(Clone)]
169enum ProviderRunner {
170 Sync(SyncProviderRunner),
171 Async(AsyncProviderRunner),
172}
173
174type SyncProviderFinalizer = Rc<dyn Fn(&DependencyValue) -> Result<(), DependencyError>>;
175type FinalizerFuture = Pin<Box<dyn Future<Output = Result<(), DependencyError>> + 'static>>;
176type AsyncProviderFinalizer = Rc<dyn Fn(&DependencyValue) -> FinalizerFuture>;
177
178#[derive(Clone)]
179enum ProviderFinalizer {
180 Sync(SyncProviderFinalizer),
181 Async(AsyncProviderFinalizer),
182}
183
184impl CompiledProvider {
185 #[doc(hidden)]
186 #[must_use]
187 pub fn run(
188 &self,
189 singletons: &[Option<DependencyValue>],
190 requests: &[Option<DependencyValue>],
191 ) -> ProviderFuture {
192 match &self.runner {
193 ProviderRunner::Sync(runner) => {
194 let result = runner(singletons, requests);
195 Box::pin(async move { result })
196 }
197 ProviderRunner::Async(runner) => runner(singletons, requests),
198 }
199 }
200
201 #[doc(hidden)]
202 pub fn run_sync(
203 &self,
204 singletons: &[Option<DependencyValue>],
205 requests: &[Option<DependencyValue>],
206 ) -> Result<DependencyValue, DependencyError> {
207 match &self.runner {
208 ProviderRunner::Sync(runner) => runner(singletons, requests),
209 ProviderRunner::Async(_) => Err(DependencyError::internal(
210 "async_singleton_provider",
211 "async providers cannot use the singleton lifetime",
212 )),
213 }
214 }
215
216 #[doc(hidden)]
217 pub fn finalize(&self, value: &DependencyValue) -> FinalizerFuture {
218 match &self.finalizer {
219 None => Box::pin(async { Ok(()) }),
220 Some(ProviderFinalizer::Sync(finalizer)) => {
221 let result = finalizer(value);
222 Box::pin(async move { result })
223 }
224 Some(ProviderFinalizer::Async(finalizer)) => finalizer(value),
225 }
226 }
227}
228
229#[doc(hidden)]
232#[derive(Clone, Copy, Debug, Eq, PartialEq)]
233pub struct ProviderCompileError {
234 expected: usize,
235 actual: usize,
236}
237
238impl ProviderCompileError {
239 const fn arity(expected: usize, actual: usize) -> Self {
240 Self { expected, actual }
241 }
242}
243
244impl fmt::Display for ProviderCompileError {
245 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
246 write!(
247 formatter,
248 "provider expected {} dependency slots but received {}",
249 self.expected, self.actual
250 )
251 }
252}
253
254impl std::error::Error for ProviderCompileError {}
255
256type ProviderCompiler =
257 Rc<dyn Fn(&[DependencySlot]) -> Result<CompiledProvider, ProviderCompileError>>;
258
259#[derive(Clone)]
261pub struct Provider {
262 key: DependencyKey,
263 lifetime: DependencyLifetime,
264 dependencies: Vec<DependencyKey>,
265 compiler: ProviderCompiler,
266 finalizer: Option<ProviderFinalizer>,
267}
268
269impl Provider {
270 #[must_use]
272 pub fn value<T: 'static>(value: T) -> Self {
273 let value: DependencyValue = Rc::new(value);
274 let compiler = Rc::new(move |slots: &[DependencySlot]| {
275 if !slots.is_empty() {
276 return Err(ProviderCompileError::arity(0, slots.len()));
277 }
278 let value = Rc::clone(&value);
279 Ok(CompiledProvider {
280 runner: ProviderRunner::Sync(Rc::new(move |_, _| Ok(Rc::clone(&value)))),
281 finalizer: None,
282 })
283 });
284 Self {
285 key: DependencyKey::of::<T>(),
286 lifetime: DependencyLifetime::Singleton,
287 dependencies: Vec::new(),
288 compiler,
289 finalizer: None,
290 }
291 }
292
293 #[must_use]
295 pub fn singleton<Arguments, Output, Factory>(factory: Factory) -> Self
296 where
297 Factory: ProviderFactory<Arguments, Output>,
298 Output: 'static,
299 {
300 Self::from_factory(DependencyLifetime::Singleton, factory)
301 }
302
303 #[must_use]
305 pub fn request<Arguments, Output, Factory>(factory: Factory) -> Self
306 where
307 Factory: ProviderFactory<Arguments, Output>,
308 Output: 'static,
309 {
310 Self::from_factory(DependencyLifetime::Request, factory)
311 }
312
313 #[must_use]
315 pub fn transient<Arguments, Output, Factory>(factory: Factory) -> Self
316 where
317 Factory: ProviderFactory<Arguments, Output>,
318 Output: 'static,
319 {
320 Self::from_factory(DependencyLifetime::Transient, factory)
321 }
322
323 #[must_use]
325 pub fn try_singleton<Arguments, Output, Factory>(factory: Factory) -> Self
326 where
327 Factory: FallibleProviderFactory<Arguments, Output>,
328 Output: 'static,
329 {
330 Self::from_fallible_factory(DependencyLifetime::Singleton, factory)
331 }
332
333 #[must_use]
335 pub fn try_request<Arguments, Output, Factory>(factory: Factory) -> Self
336 where
337 Factory: FallibleProviderFactory<Arguments, Output>,
338 Output: 'static,
339 {
340 Self::from_fallible_factory(DependencyLifetime::Request, factory)
341 }
342
343 #[must_use]
345 pub fn try_transient<Arguments, Output, Factory>(factory: Factory) -> Self
346 where
347 Factory: FallibleProviderFactory<Arguments, Output>,
348 Output: 'static,
349 {
350 Self::from_fallible_factory(DependencyLifetime::Transient, factory)
351 }
352
353 #[must_use]
355 pub fn request_scoped<Arguments, Output, Factory, Finalizer>(
356 factory: Factory,
357 finalizer: Finalizer,
358 ) -> Self
359 where
360 Factory: ProviderFactory<Arguments, Output>,
361 Finalizer: Fn(Depends<Output>) + 'static,
362 Output: 'static,
363 {
364 let mut provider = Self::from_factory(DependencyLifetime::Request, factory);
365 provider.finalizer = Some(typed_finalizer(finalizer));
366 provider
367 }
368
369 #[must_use]
371 pub fn try_request_scoped<Arguments, Output, Factory, Finalizer>(
372 factory: Factory,
373 finalizer: Finalizer,
374 ) -> Self
375 where
376 Factory: FallibleProviderFactory<Arguments, Output>,
377 Finalizer: Fn(Depends<Output>) + 'static,
378 Output: 'static,
379 {
380 let mut provider = Self::from_fallible_factory(DependencyLifetime::Request, factory);
381 provider.finalizer = Some(typed_finalizer(finalizer));
382 provider
383 }
384
385 #[must_use]
387 pub fn request_async<Arguments, Output, Factory, FactoryFuture>(factory: Factory) -> Self
388 where
389 Factory: AsyncProviderFactory<Arguments, Output, FactoryFuture>,
390 FactoryFuture: Future<Output = Output> + 'static,
391 Output: 'static,
392 {
393 Self::from_async_factory(DependencyLifetime::Request, factory)
394 }
395
396 #[must_use]
398 pub fn transient_async<Arguments, Output, Factory, FactoryFuture>(factory: Factory) -> Self
399 where
400 Factory: AsyncProviderFactory<Arguments, Output, FactoryFuture>,
401 FactoryFuture: Future<Output = Output> + 'static,
402 Output: 'static,
403 {
404 Self::from_async_factory(DependencyLifetime::Transient, factory)
405 }
406
407 #[must_use]
409 pub fn try_request_async<Arguments, Output, Factory, FactoryFuture>(factory: Factory) -> Self
410 where
411 Factory: FallibleAsyncProviderFactory<Arguments, Output, FactoryFuture>,
412 FactoryFuture: Future<Output = Result<Output, DependencyError>> + 'static,
413 Output: 'static,
414 {
415 Self::from_fallible_async_factory(DependencyLifetime::Request, factory)
416 }
417
418 #[must_use]
420 pub fn try_transient_async<Arguments, Output, Factory, FactoryFuture>(factory: Factory) -> Self
421 where
422 Factory: FallibleAsyncProviderFactory<Arguments, Output, FactoryFuture>,
423 FactoryFuture: Future<Output = Result<Output, DependencyError>> + 'static,
424 Output: 'static,
425 {
426 Self::from_fallible_async_factory(DependencyLifetime::Transient, factory)
427 }
428
429 #[must_use]
431 pub fn request_async_scoped<
432 Arguments,
433 Output,
434 Factory,
435 FactoryFuture,
436 Finalizer,
437 FinalizerFuture,
438 >(
439 factory: Factory,
440 finalizer: Finalizer,
441 ) -> Self
442 where
443 Factory: AsyncProviderFactory<Arguments, Output, FactoryFuture>,
444 FactoryFuture: Future<Output = Output> + 'static,
445 Finalizer: Fn(Depends<Output>) -> FinalizerFuture + 'static,
446 FinalizerFuture: Future<Output = ()> + 'static,
447 Output: 'static,
448 {
449 let mut provider = Self::from_async_factory(DependencyLifetime::Request, factory);
450 provider.finalizer = Some(typed_async_finalizer(finalizer));
451 provider
452 }
453
454 #[must_use]
456 pub fn try_request_async_scoped<
457 Arguments,
458 Output,
459 Factory,
460 FactoryFuture,
461 Finalizer,
462 FinalizerFuture,
463 >(
464 factory: Factory,
465 finalizer: Finalizer,
466 ) -> Self
467 where
468 Factory: FallibleAsyncProviderFactory<Arguments, Output, FactoryFuture>,
469 FactoryFuture: Future<Output = Result<Output, DependencyError>> + 'static,
470 Finalizer: Fn(Depends<Output>) -> FinalizerFuture + 'static,
471 FinalizerFuture: Future<Output = ()> + 'static,
472 Output: 'static,
473 {
474 let mut provider = Self::from_fallible_async_factory(DependencyLifetime::Request, factory);
475 provider.finalizer = Some(typed_async_finalizer(finalizer));
476 provider
477 }
478
479 fn from_factory<Arguments, Output, Factory>(
480 lifetime: DependencyLifetime,
481 factory: Factory,
482 ) -> Self
483 where
484 Factory: ProviderFactory<Arguments, Output>,
485 Output: 'static,
486 {
487 let dependencies = Factory::dependency_keys();
488 let factory = Rc::new(factory);
489 let compiler =
490 Rc::new(move |slots: &[DependencySlot]| Factory::compile(Rc::clone(&factory), slots));
491 Self {
492 key: DependencyKey::of::<Output>(),
493 lifetime,
494 dependencies,
495 compiler,
496 finalizer: None,
497 }
498 }
499
500 fn from_fallible_factory<Arguments, Output, Factory>(
501 lifetime: DependencyLifetime,
502 factory: Factory,
503 ) -> Self
504 where
505 Factory: FallibleProviderFactory<Arguments, Output>,
506 Output: 'static,
507 {
508 let dependencies = Factory::dependency_keys();
509 let factory = Rc::new(factory);
510 let compiler =
511 Rc::new(move |slots: &[DependencySlot]| Factory::compile(Rc::clone(&factory), slots));
512 Self {
513 key: DependencyKey::of::<Output>(),
514 lifetime,
515 dependencies,
516 compiler,
517 finalizer: None,
518 }
519 }
520
521 fn from_async_factory<Arguments, Output, Factory, FactoryFuture>(
522 lifetime: DependencyLifetime,
523 factory: Factory,
524 ) -> Self
525 where
526 Factory: AsyncProviderFactory<Arguments, Output, FactoryFuture>,
527 FactoryFuture: Future<Output = Output> + 'static,
528 Output: 'static,
529 {
530 let dependencies = Factory::dependency_keys();
531 let factory = Rc::new(factory);
532 let compiler =
533 Rc::new(move |slots: &[DependencySlot]| Factory::compile(Rc::clone(&factory), slots));
534 Self {
535 key: DependencyKey::of::<Output>(),
536 lifetime,
537 dependencies,
538 compiler,
539 finalizer: None,
540 }
541 }
542
543 fn from_fallible_async_factory<Arguments, Output, Factory, FactoryFuture>(
544 lifetime: DependencyLifetime,
545 factory: Factory,
546 ) -> Self
547 where
548 Factory: FallibleAsyncProviderFactory<Arguments, Output, FactoryFuture>,
549 FactoryFuture: Future<Output = Result<Output, DependencyError>> + 'static,
550 Output: 'static,
551 {
552 let dependencies = Factory::dependency_keys();
553 let factory = Rc::new(factory);
554 let compiler =
555 Rc::new(move |slots: &[DependencySlot]| Factory::compile(Rc::clone(&factory), slots));
556 Self {
557 key: DependencyKey::of::<Output>(),
558 lifetime,
559 dependencies,
560 compiler,
561 finalizer: None,
562 }
563 }
564
565 #[must_use]
566 pub const fn key(&self) -> DependencyKey {
567 self.key
568 }
569
570 #[must_use]
571 pub const fn lifetime(&self) -> DependencyLifetime {
572 self.lifetime
573 }
574
575 #[must_use]
576 pub fn dependencies(&self) -> &[DependencyKey] {
577 &self.dependencies
578 }
579
580 #[doc(hidden)]
581 pub fn compile(
582 &self,
583 slots: &[DependencySlot],
584 ) -> Result<CompiledProvider, ProviderCompileError> {
585 let mut compiled = (self.compiler)(slots)?;
586 compiled.finalizer.clone_from(&self.finalizer);
587 Ok(compiled)
588 }
589}
590
591#[doc(hidden)]
593pub trait ProviderFactory<Arguments, Output>: 'static {
594 fn dependency_keys() -> Vec<DependencyKey>;
595
596 fn compile(
597 factory: Rc<Self>,
598 slots: &[DependencySlot],
599 ) -> Result<CompiledProvider, ProviderCompileError>;
600}
601
602#[doc(hidden)]
604pub trait FallibleProviderFactory<Arguments, Output>: 'static {
605 fn dependency_keys() -> Vec<DependencyKey>;
606
607 fn compile(
608 factory: Rc<Self>,
609 slots: &[DependencySlot],
610 ) -> Result<CompiledProvider, ProviderCompileError>;
611}
612
613#[doc(hidden)]
615pub trait AsyncProviderFactory<Arguments, Output, FactoryFuture>: 'static
616where
617 FactoryFuture: Future<Output = Output> + 'static,
618{
619 fn dependency_keys() -> Vec<DependencyKey>;
620
621 fn compile(
622 factory: Rc<Self>,
623 slots: &[DependencySlot],
624 ) -> Result<CompiledProvider, ProviderCompileError>;
625}
626
627#[doc(hidden)]
629pub trait FallibleAsyncProviderFactory<Arguments, Output, FactoryFuture>: 'static
630where
631 FactoryFuture: Future<Output = Result<Output, DependencyError>> + 'static,
632{
633 fn dependency_keys() -> Vec<DependencyKey>;
634
635 fn compile(
636 factory: Rc<Self>,
637 slots: &[DependencySlot],
638 ) -> Result<CompiledProvider, ProviderCompileError>;
639}
640
641impl<Factory, Output> ProviderFactory<(), Output> for Factory
642where
643 Factory: Fn() -> Output + 'static,
644 Output: 'static,
645{
646 fn dependency_keys() -> Vec<DependencyKey> {
647 Vec::new()
648 }
649
650 fn compile(
651 factory: Rc<Self>,
652 slots: &[DependencySlot],
653 ) -> Result<CompiledProvider, ProviderCompileError> {
654 expect_arity(slots, 0)?;
655 Ok(CompiledProvider {
656 runner: ProviderRunner::Sync(Rc::new(move |_, _| {
657 Ok(Rc::new(factory()) as DependencyValue)
658 })),
659 finalizer: None,
660 })
661 }
662}
663
664impl<Factory, Output, FactoryFuture> AsyncProviderFactory<(), Output, FactoryFuture> for Factory
665where
666 Factory: Fn() -> FactoryFuture + 'static,
667 FactoryFuture: Future<Output = Output> + 'static,
668 Output: 'static,
669{
670 fn dependency_keys() -> Vec<DependencyKey> {
671 Vec::new()
672 }
673
674 fn compile(
675 factory: Rc<Self>,
676 slots: &[DependencySlot],
677 ) -> Result<CompiledProvider, ProviderCompileError> {
678 expect_arity(slots, 0)?;
679 Ok(CompiledProvider {
680 runner: ProviderRunner::Async(Rc::new(move |_, _| {
681 let future = factory();
682 Box::pin(async move { Ok(Rc::new(future.await) as DependencyValue) })
683 })),
684 finalizer: None,
685 })
686 }
687}
688
689impl<Factory, Output, FactoryFuture> FallibleAsyncProviderFactory<(), Output, FactoryFuture>
690 for Factory
691where
692 Factory: Fn() -> FactoryFuture + 'static,
693 FactoryFuture: Future<Output = Result<Output, DependencyError>> + 'static,
694 Output: 'static,
695{
696 fn dependency_keys() -> Vec<DependencyKey> {
697 Vec::new()
698 }
699
700 fn compile(
701 factory: Rc<Self>,
702 slots: &[DependencySlot],
703 ) -> Result<CompiledProvider, ProviderCompileError> {
704 expect_arity(slots, 0)?;
705 Ok(CompiledProvider {
706 runner: ProviderRunner::Async(Rc::new(move |_, _| {
707 let future = factory();
708 Box::pin(async move { future.await.map(|value| Rc::new(value) as DependencyValue) })
709 })),
710 finalizer: None,
711 })
712 }
713}
714
715impl<Factory, Output> FallibleProviderFactory<(), Output> for Factory
716where
717 Factory: Fn() -> Result<Output, DependencyError> + 'static,
718 Output: 'static,
719{
720 fn dependency_keys() -> Vec<DependencyKey> {
721 Vec::new()
722 }
723
724 fn compile(
725 factory: Rc<Self>,
726 slots: &[DependencySlot],
727 ) -> Result<CompiledProvider, ProviderCompileError> {
728 expect_arity(slots, 0)?;
729 Ok(CompiledProvider {
730 runner: ProviderRunner::Sync(Rc::new(move |_, _| {
731 factory().map(|value| Rc::new(value) as DependencyValue)
732 })),
733 finalizer: None,
734 })
735 }
736}
737
738macro_rules! provider_factory {
739 ($(($argument:ident, $value:ident, $index:tt)),+ $(,)?) => {
740 impl<Factory, Output, $($argument),+> ProviderFactory<($($argument,)+), Output> for Factory
741 where
742 Factory: Fn($(Depends<$argument>),+) -> Output + 'static,
743 Output: 'static,
744 $($argument: 'static),+
745 {
746 fn dependency_keys() -> Vec<DependencyKey> {
747 vec![$(DependencyKey::of::<$argument>()),+]
748 }
749
750 fn compile(
751 factory: Rc<Self>,
752 slots: &[DependencySlot],
753 ) -> Result<CompiledProvider, ProviderCompileError> {
754 expect_arity(slots, provider_factory!(@count $($argument),+))?;
755 $(let $value = slots[$index];)+
756 Ok(CompiledProvider {
757 runner: ProviderRunner::Sync(Rc::new(move |singletons, requests| {
758 $(
759 let $value =
760 resolve::<$argument>($value, singletons, requests)?;
761 )+
762 Ok(Rc::new(factory($($value),+)) as DependencyValue)
763 })),
764 finalizer: None,
765 })
766 }
767 }
768
769 impl<Factory, Output, $($argument),+>
770 FallibleProviderFactory<($($argument,)+), Output> for Factory
771 where
772 Factory: Fn($(Depends<$argument>),+) -> Result<Output, DependencyError> + 'static,
773 Output: 'static,
774 $($argument: 'static),+
775 {
776 fn dependency_keys() -> Vec<DependencyKey> {
777 vec![$(DependencyKey::of::<$argument>()),+]
778 }
779
780 fn compile(
781 factory: Rc<Self>,
782 slots: &[DependencySlot],
783 ) -> Result<CompiledProvider, ProviderCompileError> {
784 expect_arity(slots, provider_factory!(@count $($argument),+))?;
785 $(let $value = slots[$index];)+
786 Ok(CompiledProvider {
787 runner: ProviderRunner::Sync(Rc::new(move |singletons, requests| {
788 $(
789 let $value =
790 resolve::<$argument>($value, singletons, requests)?;
791 )+
792 factory($($value),+)
793 .map(|value| Rc::new(value) as DependencyValue)
794 })),
795 finalizer: None,
796 })
797 }
798 }
799
800 impl<Factory, Output, FactoryFuture, $($argument),+>
801 AsyncProviderFactory<($($argument,)+), Output, FactoryFuture> for Factory
802 where
803 Factory: Fn($(Depends<$argument>),+) -> FactoryFuture + 'static,
804 FactoryFuture: Future<Output = Output> + 'static,
805 Output: 'static,
806 $($argument: 'static),+
807 {
808 fn dependency_keys() -> Vec<DependencyKey> {
809 vec![$(DependencyKey::of::<$argument>()),+]
810 }
811
812 fn compile(
813 factory: Rc<Self>,
814 slots: &[DependencySlot],
815 ) -> Result<CompiledProvider, ProviderCompileError> {
816 expect_arity(slots, provider_factory!(@count $($argument),+))?;
817 $(let $value = slots[$index];)+
818 Ok(CompiledProvider {
819 runner: ProviderRunner::Async(Rc::new(move |singletons, requests| {
820 $(
821 let $value = match
822 resolve::<$argument>($value, singletons, requests)
823 {
824 Ok(value) => value,
825 Err(error) => return failed_provider_future(error),
826 };
827 )+
828 let future = factory($($value),+);
829 Box::pin(async move {
830 Ok(Rc::new(future.await) as DependencyValue)
831 })
832 })),
833 finalizer: None,
834 })
835 }
836 }
837
838 impl<Factory, Output, FactoryFuture, $($argument),+>
839 FallibleAsyncProviderFactory<($($argument,)+), Output, FactoryFuture> for Factory
840 where
841 Factory: Fn($(Depends<$argument>),+) -> FactoryFuture + 'static,
842 FactoryFuture: Future<Output = Result<Output, DependencyError>> + 'static,
843 Output: 'static,
844 $($argument: 'static),+
845 {
846 fn dependency_keys() -> Vec<DependencyKey> {
847 vec![$(DependencyKey::of::<$argument>()),+]
848 }
849
850 fn compile(
851 factory: Rc<Self>,
852 slots: &[DependencySlot],
853 ) -> Result<CompiledProvider, ProviderCompileError> {
854 expect_arity(slots, provider_factory!(@count $($argument),+))?;
855 $(let $value = slots[$index];)+
856 Ok(CompiledProvider {
857 runner: ProviderRunner::Async(Rc::new(move |singletons, requests| {
858 $(
859 let $value = match
860 resolve::<$argument>($value, singletons, requests)
861 {
862 Ok(value) => value,
863 Err(error) => return failed_provider_future(error),
864 };
865 )+
866 let future = factory($($value),+);
867 Box::pin(async move {
868 future
869 .await
870 .map(|value| Rc::new(value) as DependencyValue)
871 })
872 })),
873 finalizer: None,
874 })
875 }
876 }
877 };
878 (@count $($argument:ident),+) => {
879 <[()]>::len(&[$(provider_factory!(@unit $argument)),+])
880 };
881 (@unit $argument:ident) => { () };
882}
883
884provider_factory!((A, a, 0));
885provider_factory!((A, a, 0), (B, b, 1));
886provider_factory!((A, a, 0), (B, b, 1), (C, c, 2));
887provider_factory!((A, a, 0), (B, b, 1), (C, c, 2), (D, d, 3));
888provider_factory!((A, a, 0), (B, b, 1), (C, c, 2), (D, d, 3), (E, e, 4));
889provider_factory!(
890 (A, a, 0),
891 (B, b, 1),
892 (C, c, 2),
893 (D, d, 3),
894 (E, e, 4),
895 (F, f, 5)
896);
897provider_factory!(
898 (A, a, 0),
899 (B, b, 1),
900 (C, c, 2),
901 (D, d, 3),
902 (E, e, 4),
903 (F, f, 5),
904 (G, g, 6)
905);
906provider_factory!(
907 (A, a, 0),
908 (B, b, 1),
909 (C, c, 2),
910 (D, d, 3),
911 (E, e, 4),
912 (F, f, 5),
913 (G, g, 6),
914 (H, h, 7)
915);
916
917fn typed_finalizer<T, Finalizer>(finalizer: Finalizer) -> ProviderFinalizer
918where
919 Finalizer: Fn(Depends<T>) + 'static,
920 T: 'static,
921{
922 ProviderFinalizer::Sync(Rc::new(move |value| {
923 let dependency = Rc::clone(value).downcast::<T>().map_err(|_| {
924 DependencyError::internal(
925 "dependency_type_mismatch",
926 "compiled finalizer received an unexpected dependency type",
927 )
928 })?;
929 finalizer(Depends::from_rc(dependency));
930 Ok(())
931 }))
932}
933
934fn typed_async_finalizer<T, Finalizer, FinalizerOutput>(finalizer: Finalizer) -> ProviderFinalizer
935where
936 Finalizer: Fn(Depends<T>) -> FinalizerOutput + 'static,
937 FinalizerOutput: Future<Output = ()> + 'static,
938 T: 'static,
939{
940 ProviderFinalizer::Async(Rc::new(move |value| {
941 let Ok(dependency) = Rc::clone(value).downcast::<T>() else {
942 return Box::pin(async {
943 Err(DependencyError::internal(
944 "dependency_type_mismatch",
945 "compiled async finalizer received an unexpected dependency type",
946 ))
947 });
948 };
949 let future = finalizer(Depends::from_rc(dependency));
950 Box::pin(async move {
951 future.await;
952 Ok(())
953 })
954 }))
955}
956
957fn failed_provider_future(error: DependencyError) -> ProviderFuture {
958 Box::pin(async move { Err(error) })
959}
960
961fn expect_arity(slots: &[DependencySlot], expected: usize) -> Result<(), ProviderCompileError> {
962 if slots.len() == expected {
963 Ok(())
964 } else {
965 Err(ProviderCompileError::arity(expected, slots.len()))
966 }
967}
968
969fn resolve<T: 'static>(
970 slot: DependencySlot,
971 singletons: &[Option<DependencyValue>],
972 requests: &[Option<DependencyValue>],
973) -> Result<Depends<T>, DependencyError> {
974 let value = match slot {
975 DependencySlot::Singleton(index) => singletons.get(index),
976 DependencySlot::Request(index) => requests.get(index),
977 }
978 .and_then(Option::as_ref)
979 .ok_or_else(|| {
980 DependencyError::internal(
981 "invalid_dependency_slot",
982 "compiled dependency slot was not initialized",
983 )
984 })?;
985 Rc::clone(value)
986 .downcast::<T>()
987 .map(Depends::from_rc)
988 .map_err(|_| {
989 DependencyError::internal(
990 "dependency_type_mismatch",
991 "compiled dependency slot contained an unexpected type",
992 )
993 })
994}