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
969#[doc(hidden)]
977pub struct SlotReader<'values> {
978 singletons: &'values [Option<DependencyValue>],
979 requests: &'values [Option<DependencyValue>],
980 slots: &'values [DependencySlot],
981 depends_count: usize,
982}
983
984impl SlotReader<'_> {
985 pub fn depends<T: 'static>(&self, position: usize) -> Result<Depends<T>, DependencyError> {
992 let slot = self.slots.get(position).copied().ok_or_else(|| {
993 DependencyError::internal(
994 "invalid_dependency_slot",
995 "compiled provider requested an undeclared dependency position",
996 )
997 })?;
998 resolve(slot, self.singletons, self.requests)
999 }
1000
1001 pub fn input<T: 'static>(&self, position: usize) -> Result<Rc<T>, DependencyError> {
1009 let slot = self
1010 .slots
1011 .get(self.depends_count + position)
1012 .copied()
1013 .ok_or_else(|| {
1014 DependencyError::internal(
1015 "invalid_dependency_slot",
1016 "compiled provider requested an undeclared input position",
1017 )
1018 })?;
1019 let value = match slot {
1020 DependencySlot::Singleton(index) => self.singletons.get(index),
1021 DependencySlot::Request(index) => self.requests.get(index),
1022 }
1023 .and_then(Option::as_ref)
1024 .ok_or_else(|| {
1025 DependencyError::internal(
1026 "invalid_dependency_slot",
1027 "compiled request input slot was not initialized",
1028 )
1029 })?;
1030 Rc::clone(value).downcast::<T>().map_err(|_| {
1031 DependencyError::internal(
1032 "dependency_type_mismatch",
1033 "compiled request input slot contained an unexpected type",
1034 )
1035 })
1036 }
1037}
1038
1039#[doc(hidden)]
1041pub type SlotFactory<T> = Rc<dyn Fn(&SlotReader<'_>) -> Result<T, DependencyError>>;
1042
1043#[doc(hidden)]
1048pub type AsyncSlotFactory<T> = Rc<
1049 dyn Fn(&SlotReader<'_>) -> Pin<Box<dyn Future<Output = Result<T, DependencyError>> + 'static>>,
1050>;
1051
1052impl Provider {
1053 fn from_slots_inner<T: 'static>(
1054 lifetime: DependencyLifetime,
1055 dependencies: Vec<DependencyKey>,
1056 input_count: usize,
1057 runner_of: impl Fn(Rc<Vec<DependencySlot>>, usize) -> ProviderRunner + 'static,
1058 ) -> Self {
1059 let depends_count = dependencies.len();
1060 let expected = depends_count + input_count;
1061 let compiler = Rc::new(move |slots: &[DependencySlot]| {
1062 expect_arity(slots, expected)?;
1063 let slots = Rc::new(slots.to_vec());
1064 Ok(CompiledProvider {
1065 runner: runner_of(slots, depends_count),
1066 finalizer: None,
1067 })
1068 });
1069 Self {
1070 key: DependencyKey::of::<T>(),
1071 lifetime,
1072 dependencies,
1073 compiler,
1074 finalizer: None,
1075 }
1076 }
1077
1078 #[doc(hidden)]
1081 #[must_use]
1082 pub fn request_from_slots<T: 'static>(
1083 dependencies: Vec<DependencyKey>,
1084 input_count: usize,
1085 factory: SlotFactory<T>,
1086 ) -> Self {
1087 Self::slot_provider::<T>(
1088 DependencyLifetime::Request,
1089 dependencies,
1090 input_count,
1091 factory,
1092 )
1093 }
1094
1095 #[doc(hidden)]
1097 #[must_use]
1098 pub fn transient_from_slots<T: 'static>(
1099 dependencies: Vec<DependencyKey>,
1100 input_count: usize,
1101 factory: SlotFactory<T>,
1102 ) -> Self {
1103 Self::slot_provider::<T>(
1104 DependencyLifetime::Transient,
1105 dependencies,
1106 input_count,
1107 factory,
1108 )
1109 }
1110
1111 #[doc(hidden)]
1113 #[must_use]
1114 pub fn request_from_slots_async<T: 'static>(
1115 dependencies: Vec<DependencyKey>,
1116 input_count: usize,
1117 factory: AsyncSlotFactory<T>,
1118 ) -> Self {
1119 Self::async_slot_provider::<T>(
1120 DependencyLifetime::Request,
1121 dependencies,
1122 input_count,
1123 factory,
1124 )
1125 }
1126
1127 #[doc(hidden)]
1129 #[must_use]
1130 pub fn transient_from_slots_async<T: 'static>(
1131 dependencies: Vec<DependencyKey>,
1132 input_count: usize,
1133 factory: AsyncSlotFactory<T>,
1134 ) -> Self {
1135 Self::async_slot_provider::<T>(
1136 DependencyLifetime::Transient,
1137 dependencies,
1138 input_count,
1139 factory,
1140 )
1141 }
1142
1143 fn slot_provider<T: 'static>(
1144 lifetime: DependencyLifetime,
1145 dependencies: Vec<DependencyKey>,
1146 input_count: usize,
1147 factory: SlotFactory<T>,
1148 ) -> Self {
1149 Self::from_slots_inner::<T>(
1150 lifetime,
1151 dependencies,
1152 input_count,
1153 move |slots, depends| {
1154 let factory = Rc::clone(&factory);
1155 ProviderRunner::Sync(Rc::new(move |singletons, requests| {
1156 let reader = SlotReader {
1157 singletons,
1158 requests,
1159 slots: &slots,
1160 depends_count: depends,
1161 };
1162 factory(&reader).map(|value| Rc::new(value) as DependencyValue)
1163 }))
1164 },
1165 )
1166 }
1167
1168 fn async_slot_provider<T: 'static>(
1169 lifetime: DependencyLifetime,
1170 dependencies: Vec<DependencyKey>,
1171 input_count: usize,
1172 factory: AsyncSlotFactory<T>,
1173 ) -> Self {
1174 Self::from_slots_inner::<T>(
1175 lifetime,
1176 dependencies,
1177 input_count,
1178 move |slots, depends| {
1179 let factory = Rc::clone(&factory);
1180 ProviderRunner::Async(Rc::new(move |singletons, requests| {
1181 let reader = SlotReader {
1182 singletons,
1183 requests,
1184 slots: &slots,
1185 depends_count: depends,
1186 };
1187 let future = factory(&reader);
1188 Box::pin(
1189 async move { future.await.map(|value| Rc::new(value) as DependencyValue) },
1190 )
1191 }))
1192 },
1193 )
1194 }
1195}
1196
1197fn resolve<T: 'static>(
1198 slot: DependencySlot,
1199 singletons: &[Option<DependencyValue>],
1200 requests: &[Option<DependencyValue>],
1201) -> Result<Depends<T>, DependencyError> {
1202 let value = match slot {
1203 DependencySlot::Singleton(index) => singletons.get(index),
1204 DependencySlot::Request(index) => requests.get(index),
1205 }
1206 .and_then(Option::as_ref)
1207 .ok_or_else(|| {
1208 DependencyError::internal(
1209 "invalid_dependency_slot",
1210 "compiled dependency slot was not initialized",
1211 )
1212 })?;
1213 Rc::clone(value)
1214 .downcast::<T>()
1215 .map(Depends::from_rc)
1216 .map_err(|_| {
1217 DependencyError::internal(
1218 "dependency_type_mismatch",
1219 "compiled dependency slot contained an unexpected type",
1220 )
1221 })
1222}