1mod dependency;
4mod request_scope;
5
6use std::{
7 any::{Any, TypeId, type_name},
8 collections::HashMap,
9 hash::{BuildHasherDefault, Hasher},
10 sync::Arc,
11};
12
13use crate::{NidusError, ProviderEntry, ProviderLifetime, Result};
14
15pub use dependency::{Factory, Inject, Lazy, Optional, Scoped};
16pub use request_scope::{RequestScope, SharedRequestScope};
17
18pub(crate) type TypeIdMap<V> = HashMap<TypeId, V, BuildHasherDefault<TypeIdHasher>>;
20
21#[derive(Default)]
28pub(crate) struct TypeIdHasher(u64);
29
30impl Hasher for TypeIdHasher {
31 fn write(&mut self, bytes: &[u8]) {
32 for &byte in bytes {
35 self.0 = self.0.rotate_left(8) ^ u64::from(byte);
36 }
37 }
38
39 fn write_u64(&mut self, value: u64) {
40 self.0 = value;
41 }
42
43 fn finish(&self) -> u64 {
44 self.0
45 }
46}
47
48#[derive(Default)]
50pub struct Container {
51 providers: TypeIdMap<ProviderEntry>,
52}
53
54impl Container {
55 pub fn new() -> Self {
57 Self::default()
58 }
59
60 pub fn request_scope(&self) -> RequestScope<'_> {
62 RequestScope::borrowed(self)
63 }
64
65 pub fn register_singleton<T>(&mut self, value: T) -> Result<()>
67 where
68 T: Send + Sync + 'static,
69 {
70 let value = Arc::new(value);
71 self.insert::<T>(ProviderLifetime::Singleton, move |_container| {
72 Ok(Arc::clone(&value) as Arc<dyn Any + Send + Sync>)
73 })
74 }
75
76 pub fn override_singleton<T>(&mut self, value: T) -> Result<()>
78 where
79 T: Send + Sync + 'static,
80 {
81 self.providers.remove(&TypeId::of::<T>());
82 self.register_singleton(value)
83 }
84
85 pub fn register_factory<T, F>(&mut self, lifetime: ProviderLifetime, factory: F) -> Result<()>
87 where
88 T: Send + Sync + 'static,
89 F: Fn(&Container) -> Result<T> + Send + Sync + 'static,
90 {
91 self.insert::<T>(lifetime, move |container| {
92 factory(container).map(|value| Arc::new(value) as Arc<dyn Any + Send + Sync>)
93 })
94 }
95
96 pub fn register_singleton_factory<T, F>(&mut self, factory: F) -> Result<()>
98 where
99 T: Send + Sync + 'static,
100 F: Fn(&Container) -> Result<T> + Send + Sync + 'static,
101 {
102 self.register_factory::<T, F>(ProviderLifetime::Singleton, factory)
103 }
104
105 pub fn register_transient<T, F>(&mut self, factory: F) -> Result<()>
107 where
108 T: Send + Sync + 'static,
109 F: Fn(&Container) -> Result<T> + Send + Sync + 'static,
110 {
111 self.register_factory::<T, F>(ProviderLifetime::Transient, factory)
112 }
113
114 pub fn register_request<T, F>(&mut self, factory: F) -> Result<()>
116 where
117 T: Send + Sync + 'static,
118 F: Fn(&Container) -> Result<T> + Send + Sync + 'static,
119 {
120 self.register_factory::<T, F>(ProviderLifetime::Request, factory)
121 }
122
123 pub fn register_request_scoped<T, F>(&mut self, factory: F) -> Result<()>
126 where
127 T: Send + Sync + 'static,
128 F: for<'scope> Fn(&RequestScope<'scope>) -> Result<T> + Send + Sync + 'static,
129 {
130 self.insert_request_scoped::<T>(
131 |_container| {
132 Err(NidusError::RequestScopeRequired {
133 type_name: type_name::<T>(),
134 })
135 },
136 move |scope| factory(scope).map(|value| Arc::new(value) as Arc<dyn Any + Send + Sync>),
137 )
138 }
139
140 pub fn inject<T>(&self) -> Result<Inject<T>>
142 where
143 T: Send + Sync + 'static,
144 {
145 self.resolve::<T>().map(Inject::new)
146 }
147
148 pub fn optional<T>(&self) -> Result<Optional<T>>
153 where
154 T: Send + Sync + 'static,
155 {
156 match self.inject::<T>() {
157 Ok(value) => Ok(Optional::new(Some(value))),
158 Err(NidusError::MissingProvider { .. }) => Ok(Optional::new(None)),
159 Err(error) => Err(error),
160 }
161 }
162
163 pub fn resolve<T>(&self) -> Result<Arc<T>>
165 where
166 T: Send + Sync + 'static,
167 {
168 let entry = self.entry::<T>()?;
169 if entry.lifetime() == ProviderLifetime::Request {
170 return Err(NidusError::RequestScopeRequired {
171 type_name: type_name::<T>(),
172 });
173 }
174 let erased = entry.resolve_erased(self)?;
175 downcast::<T>(erased)
176 }
177
178 pub fn eagerly_resolve_singletons(&self) -> Result<()> {
191 for entry in self.providers.values() {
192 if entry.lifetime() == ProviderLifetime::Singleton {
193 entry.resolve_erased(self)?;
194 }
195 }
196 Ok(())
197 }
198
199 fn insert<T>(
200 &mut self,
201 lifetime: ProviderLifetime,
202 factory: impl Fn(&Container) -> Result<Arc<dyn Any + Send + Sync>> + Send + Sync + 'static,
203 ) -> Result<()>
204 where
205 T: Send + Sync + 'static,
206 {
207 let type_id = TypeId::of::<T>();
208 if self.providers.contains_key(&type_id) {
209 return Err(NidusError::DuplicateProvider {
210 type_name: type_name::<T>(),
211 });
212 }
213
214 self.providers.insert(
215 type_id,
216 ProviderEntry::new(type_id, type_name::<T>(), lifetime, Arc::new(factory)),
217 );
218 Ok(())
219 }
220
221 fn insert_request_scoped<T>(
222 &mut self,
223 factory: impl Fn(&Container) -> Result<Arc<dyn Any + Send + Sync>> + Send + Sync + 'static,
224 request_factory: impl for<'scope> Fn(
225 &RequestScope<'scope>,
226 ) -> Result<Arc<dyn Any + Send + Sync>>
227 + Send
228 + Sync
229 + 'static,
230 ) -> Result<()>
231 where
232 T: Send + Sync + 'static,
233 {
234 let type_id = TypeId::of::<T>();
235 if self.providers.contains_key(&type_id) {
236 return Err(NidusError::DuplicateProvider {
237 type_name: type_name::<T>(),
238 });
239 }
240
241 self.providers.insert(
242 type_id,
243 ProviderEntry::new_request_scoped(
244 type_id,
245 type_name::<T>(),
246 Arc::new(factory),
247 Arc::new(request_factory),
248 ),
249 );
250 Ok(())
251 }
252
253 fn entry<T>(&self) -> Result<&ProviderEntry>
254 where
255 T: Send + Sync + 'static,
256 {
257 self.providers
258 .get(&TypeId::of::<T>())
259 .ok_or_else(|| NidusError::MissingProvider {
260 type_name: type_name::<T>(),
261 })
262 }
263}
264
265fn downcast<T>(erased: Arc<dyn Any + Send + Sync>) -> Result<Arc<T>>
266where
267 T: Send + Sync + 'static,
268{
269 erased
270 .downcast::<T>()
271 .map_err(|_| NidusError::MissingProvider {
272 type_name: type_name::<T>(),
273 })
274}
275
276#[cfg(test)]
277mod tests {
278 use std::{
279 any::TypeId,
280 hash::{Hash, Hasher},
281 };
282
283 use super::TypeIdHasher;
284
285 #[test]
286 fn type_id_hasher_uses_written_u64_directly() {
287 let mut hasher = TypeIdHasher::default();
288 hasher.write_u64(42);
289 assert_eq!(hasher.finish(), 42);
290 }
291
292 #[test]
293 fn type_id_hasher_distinguishes_type_ids() {
294 let mut first = TypeIdHasher::default();
295 TypeId::of::<u32>().hash(&mut first);
296 let mut second = TypeIdHasher::default();
297 TypeId::of::<u64>().hash(&mut second);
298 assert_ne!(first.finish(), second.finish());
299 }
300
301 #[test]
302 fn type_id_hasher_byte_fallback_mixes_all_bytes() {
303 let mut first = TypeIdHasher::default();
304 first.write(b"ab");
305 let mut second = TypeIdHasher::default();
306 second.write(b"ba");
307 assert_ne!(first.finish(), second.finish());
308 }
309}