Skip to main content

nidus_core/container/
dependency.rs

1use std::{ops::Deref, sync::Arc};
2
3use crate::Result;
4
5/// A typed dependency reference resolved from the container.
6#[derive(Debug)]
7pub struct Inject<T: Send + Sync + 'static>(Arc<T>);
8
9impl<T: Send + Sync + 'static> Inject<T> {
10    /// Wraps an already constructed shared dependency.
11    pub fn new(value: Arc<T>) -> Self {
12        Self(value)
13    }
14
15    /// Returns a cloned shared pointer to the dependency.
16    pub fn into_inner(self) -> Arc<T> {
17        self.0
18    }
19}
20
21impl<T: Send + Sync + 'static> Clone for Inject<T> {
22    fn clone(&self) -> Self {
23        Self(Arc::clone(&self.0))
24    }
25}
26
27impl<T: Send + Sync + 'static> Deref for Inject<T> {
28    type Target = T;
29
30    fn deref(&self) -> &Self::Target {
31        self.0.as_ref()
32    }
33}
34
35/// Optional dependency wrapper.
36#[derive(Clone, Debug)]
37pub struct Optional<T: Send + Sync + 'static>(Option<Inject<T>>);
38
39impl<T: Send + Sync + 'static> Optional<T> {
40    /// Creates an optional dependency wrapper.
41    pub fn new(value: Option<Inject<T>>) -> Self {
42        Self(value)
43    }
44
45    /// Returns `true` when the optional dependency is present.
46    pub fn is_some(&self) -> bool {
47        self.0.is_some()
48    }
49
50    /// Returns `true` when the optional dependency is absent.
51    pub fn is_none(&self) -> bool {
52        self.0.is_none()
53    }
54
55    /// Returns a shared reference to the optional dependency.
56    pub fn as_ref(&self) -> Option<&Inject<T>> {
57        self.0.as_ref()
58    }
59
60    /// Returns the optional dependency.
61    pub fn into_option(self) -> Option<Inject<T>> {
62        self.0
63    }
64}
65
66/// Lazily resolved dependency wrapper.
67#[derive(Clone)]
68pub struct Lazy<T: Send + Sync + 'static> {
69    resolver: Arc<dyn Fn() -> Result<Inject<T>> + Send + Sync>,
70}
71
72impl<T: Send + Sync + 'static> Lazy<T> {
73    /// Creates a lazy dependency from a resolver closure.
74    pub fn new(resolver: impl Fn() -> Result<Inject<T>> + Send + Sync + 'static) -> Self {
75        Self {
76            resolver: Arc::new(resolver),
77        }
78    }
79
80    /// Resolves the dependency.
81    pub fn get(&self) -> Result<Inject<T>> {
82        (self.resolver)()
83    }
84}
85
86/// Factory dependency wrapper.
87#[derive(Clone)]
88pub struct Factory<T: Send + Sync + 'static> {
89    factory: Arc<dyn Fn() -> Result<T> + Send + Sync>,
90}
91
92impl<T: Send + Sync + 'static> Factory<T> {
93    /// Creates a typed factory wrapper.
94    pub fn new(factory: impl Fn() -> Result<T> + Send + Sync + 'static) -> Self {
95        Self {
96            factory: Arc::new(factory),
97        }
98    }
99
100    /// Creates a fresh value.
101    pub fn create(&self) -> Result<T> {
102        (self.factory)()
103    }
104}
105
106/// Request-scoped dependency wrapper.
107#[derive(Clone, Debug)]
108pub struct Scoped<T: Send + Sync + 'static>(Inject<T>);
109
110impl<T: Send + Sync + 'static> Scoped<T> {
111    /// Creates a scoped dependency wrapper.
112    pub fn new(value: Inject<T>) -> Self {
113        Self(value)
114    }
115
116    /// Returns the scoped dependency.
117    pub fn into_inject(self) -> Inject<T> {
118        self.0
119    }
120}
121
122impl<T: Send + Sync + 'static> Deref for Scoped<T> {
123    type Target = T;
124
125    fn deref(&self) -> &Self::Target {
126        &self.0
127    }
128}