1use std::{
2 any::{Any, TypeId},
3 collections::{HashMap, HashSet},
4 future::Future,
5 pin::Pin,
6 sync::{Arc, Mutex},
7};
8
9pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
10
11pub trait Injectable: Send + Sync + 'static {
12 fn create(container: &Container) -> BoxFuture<'_, crate::Result<Self>>
13 where
14 Self: Sized;
15
16 fn dependencies() -> Vec<crate::ProviderDependency>
22 where
23 Self: Sized;
24
25 fn on_module_init(&self) -> BoxFuture<'_, crate::Result<()>> {
26 Box::pin(async { Ok(()) })
27 }
28
29 fn on_bootstrap(&self) -> BoxFuture<'_, crate::Result<()>> {
30 Box::pin(async { Ok(()) })
31 }
32
33 fn on_shutdown(&self) -> BoxFuture<'_, crate::Result<()>> {
34 Box::pin(async { Ok(()) })
35 }
36}
37
38pub struct Container {
39 services: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
40 pub(crate) pending_overrides: HashMap<TypeId, crate::ProviderDef>,
42 pub(crate) applied_overrides: HashSet<TypeId>,
44 declared_provider_types: HashSet<TypeId>,
45 pub(crate) initialized_providers: Arc<Mutex<Vec<TypeId>>>,
47 pub(crate) bootstrapped_providers: Arc<Mutex<HashSet<TypeId>>>,
48 dependency_scope: Option<Arc<DependencyScope>>,
49}
50
51struct DependencyScope {
52 provider_type_name: &'static str,
53 allowed_type_ids: HashSet<TypeId>,
54}
55
56impl Clone for Container {
57 fn clone(&self) -> Self {
58 Self {
59 services: self.services.clone(),
60 pending_overrides: HashMap::new(),
62 applied_overrides: self.applied_overrides.clone(),
63 declared_provider_types: self.declared_provider_types.clone(),
64 initialized_providers: self.initialized_providers.clone(),
65 bootstrapped_providers: self.bootstrapped_providers.clone(),
66 dependency_scope: self.dependency_scope.clone(),
67 }
68 }
69}
70
71impl Container {
72 pub fn new() -> Self {
73 crate::logging::init_logging();
74
75 let mut services: HashMap<TypeId, Arc<dyn Any + Send + Sync>> = HashMap::new();
76 services.insert(
77 TypeId::of::<crate::Logger>(),
78 Arc::new(crate::Logger::new("Application")),
79 );
80
81 Self {
82 services,
83 pending_overrides: HashMap::new(),
84 applied_overrides: HashSet::new(),
85 declared_provider_types: HashSet::new(),
86 initialized_providers: Arc::new(Mutex::new(Vec::new())),
87 bootstrapped_providers: Arc::new(Mutex::new(HashSet::new())),
88 dependency_scope: None,
89 }
90 }
91
92 pub fn register_instance<T: Send + Sync + 'static>(&mut self, value: T) {
93 self.services.insert(TypeId::of::<T>(), Arc::new(value));
94 }
95
96 pub async fn register<T: Injectable>(&mut self) -> crate::Result<()> {
97 let instance = T::create(self).await?;
98 let instance = Arc::new(instance);
99 instance.on_module_init().await.map_err(|err| {
100 crate::exception::startup_error(format!(
101 "on_module_init failed for {}: {}: {}",
102 std::any::type_name::<T>(),
103 err.error,
104 err.message
105 ))
106 })?;
107 self.services.insert(TypeId::of::<T>(), instance);
108 Ok(())
109 }
110
111 pub(crate) fn register_erased(&mut self, type_id: TypeId, value: Arc<dyn Any + Send + Sync>) {
112 self.services.insert(type_id, value);
113 }
114
115 pub(crate) fn resolve_erased(&self, type_id: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
116 self.services.get(&type_id).cloned()
117 }
118
119 pub(crate) fn contains_type_id(&self, type_id: TypeId) -> bool {
120 self.services.contains_key(&type_id)
121 }
122
123 pub(crate) fn take_pending_override(&mut self, type_id: TypeId) -> Option<crate::ProviderDef> {
124 self.pending_overrides.remove(&type_id)
125 }
126
127 pub(crate) fn mark_override_applied(&mut self, type_id: TypeId) {
128 self.applied_overrides.insert(type_id);
129 }
130
131 pub(crate) fn was_overridden(&self, type_id: TypeId) -> bool {
132 self.applied_overrides.contains(&type_id)
133 }
134
135 pub(crate) fn begin_provider_bootstrap(&self, type_id: TypeId) -> bool {
136 self.bootstrapped_providers
137 .lock()
138 .expect("provider lifecycle lock poisoned")
139 .insert(type_id)
140 }
141
142 pub(crate) fn mark_provider_declared(&mut self, type_id: TypeId) {
143 self.declared_provider_types.insert(type_id);
144 }
145
146 pub(crate) fn seed_overrides(&mut self, overrides: crate::ProviderOverrides) {
147 self.pending_overrides = overrides.into_inner();
148 }
149
150 pub(crate) fn has_pending_override(&self, type_id: TypeId) -> bool {
151 self.pending_overrides.contains_key(&type_id)
152 }
153
154 pub(crate) fn pending_override(&self, type_id: TypeId) -> Option<&crate::ProviderDef> {
155 self.pending_overrides.get(&type_id)
156 }
157
158 pub(crate) fn record_initialized_provider(&self, type_id: TypeId) {
159 self.initialized_providers
160 .lock()
161 .expect("provider lifecycle lock poisoned")
162 .push(type_id);
163 }
164
165 pub(crate) fn take_initialized_providers(&self) -> Vec<TypeId> {
166 std::mem::take(
167 &mut *self
168 .initialized_providers
169 .lock()
170 .expect("provider lifecycle lock poisoned"),
171 )
172 }
173
174 pub(crate) fn initialized_provider_types(&self) -> Vec<TypeId> {
175 self.initialized_providers
176 .lock()
177 .expect("provider lifecycle lock poisoned")
178 .clone()
179 }
180
181 pub(crate) fn scoped_for_provider(
182 &self,
183 provider_type_name: &'static str,
184 dependencies: &[crate::ProviderDependency],
185 ) -> Self {
186 let mut scoped = self.clone();
187 scoped.dependency_scope = Some(Arc::new(DependencyScope {
188 provider_type_name,
189 allowed_type_ids: dependencies
190 .iter()
191 .map(|dependency| dependency.type_id())
192 .collect(),
193 }));
194 scoped
195 }
196
197 pub(crate) fn assert_no_unused_overrides(&self) -> crate::Result<()> {
198 if self.pending_overrides.is_empty() {
199 return Ok(());
200 }
201
202 let mut names: Vec<&'static str> = self
203 .pending_overrides
204 .values()
205 .map(|provider| provider.type_name())
206 .collect();
207 names.sort_unstable();
208
209 Err(crate::exception::startup_error(format!(
210 "provider override was never applied: {}; is it registered in the module tree?",
211 names.join(", ")
212 )))
213 }
214
215 pub fn resolve<T: Send + Sync + 'static>(&self) -> crate::Result<Arc<T>> {
216 let type_id = TypeId::of::<T>();
217 if let Some(scope) = &self.dependency_scope
218 && type_id != TypeId::of::<crate::Logger>()
219 && !scope.allowed_type_ids.contains(&type_id)
220 {
221 return Err(crate::exception::startup_error(format!(
222 "{} resolved {} without declaring it in dependencies()",
223 scope.provider_type_name,
224 std::any::type_name::<T>()
225 )));
226 }
227
228 let value = self.services.get(&type_id).ok_or_else(|| {
229 crate::exception::startup_error(format!(
230 "no provider registered for {}",
231 std::any::type_name::<T>()
232 ))
233 })?;
234
235 value.clone().downcast::<T>().map_err(|_| {
236 crate::exception::startup_error(format!(
237 "type mismatch resolving {}",
238 std::any::type_name::<T>()
239 ))
240 })
241 }
242
243 pub fn resolve_logger(&self, context: impl Into<String>) -> Arc<crate::Logger> {
244 Arc::new(crate::Logger::new(context))
245 }
246}
247
248impl Default for Container {
249 fn default() -> Self {
250 Self::new()
251 }
252}