Skip to main content

auto_di/
deferred.rs

1use std::{any::Any, marker::PhantomData, sync::Arc};
2
3use crate::{Container, DiError, ResolutionContext};
4
5/// Resolves a dependency each time [`Provider::get`] is called.
6pub struct Provider<T> {
7    container: Container,
8    context: ResolutionContext,
9    _marker: PhantomData<fn() -> T>,
10}
11
12impl<T> Clone for Provider<T> {
13    fn clone(&self) -> Self {
14        Self {
15            container: self.container.clone(),
16            context: self.context.clone(),
17            _marker: PhantomData,
18        }
19    }
20}
21
22impl<T> Provider<T>
23where
24    T: Any + Send + Sync,
25{
26    #[doc(hidden)]
27    pub fn from_context(container: Container, context: ResolutionContext) -> Self {
28        Self {
29            container,
30            context,
31            _marker: PhantomData,
32        }
33    }
34
35    pub async fn get(&self) -> Result<Arc<T>, DiError> {
36        self.container.resolve_dependency::<T>(&self.context).await
37    }
38}
39
40/// Resolves a dependency on first access and caches it locally.
41pub struct Lazy<T> {
42    container: Container,
43    context: ResolutionContext,
44    cell: tokio::sync::OnceCell<Arc<T>>,
45}
46
47impl<T> Lazy<T>
48where
49    T: Any + Send + Sync,
50{
51    #[doc(hidden)]
52    pub fn from_context(container: Container, context: ResolutionContext) -> Self {
53        Self {
54            container,
55            context,
56            cell: tokio::sync::OnceCell::new(),
57        }
58    }
59
60    pub async fn get(&self) -> Result<&Arc<T>, DiError> {
61        self.cell
62            .get_or_try_init(|| async {
63                self.container.resolve_dependency::<T>(&self.context).await
64            })
65            .await
66    }
67}