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