1use std::any::{Any, TypeId, type_name};
2use std::collections::HashMap;
3use std::fmt::Display;
4use std::sync::{Arc, RwLock};
5
6#[derive(Debug, Clone, Copy, PartialEq)]
7pub enum Scope {
8 Singleton,
9 Prototype,
10}
11
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13enum Identifier {
14 Named(String),
16 TypeSpec(TypeId, &'static str),
18 Unnamed(TypeId, &'static str),
20}
21
22impl Identifier {
23 pub fn named(name: &str) -> Self {
24 Identifier::Named(name.to_string())
25 }
26
27 pub fn type_spec<T: 'static>() -> Self {
28 Identifier::TypeSpec(TypeId::of::<T>(), type_name::<T>())
29 }
30
31 pub fn unnamed<T: 'static>() -> Self {
32 Identifier::Unnamed(TypeId::of::<T>(), type_name::<T>())
33 }
34}
35
36impl Display for Identifier {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 Identifier::Named(name) => write!(f, "Bean({})", name),
40 Identifier::TypeSpec(_, name) => write!(f, "Bean({})", name),
41 Identifier::Unnamed(_, name) => write!(f, "Bean({})[unnamed]", name),
42 }
43 }
44}
45
46struct CreationContext {
48 creating: Vec<Identifier>,
50}
51
52impl CreationContext {
53 fn new() -> Self {
54 CreationContext {
55 creating: Vec::new(),
56 }
57 }
58
59 fn enter(&mut self, id: Identifier) -> Result<(), String> {
60 if self.creating.len() > 100 {
61 return Err("Dependency chain too deep (>100)".to_string());
62 }
63
64 if self.creating.iter().any(|i| i == &id) {
66 let path = self
67 .creating
68 .iter()
69 .map(|id| id.to_string())
70 .collect::<Vec<_>>()
71 .join(" -> ");
72 return Err(format!("Circular dependency detected: {} -> {}", path, id));
73 }
74
75 self.creating.push(id);
76 Ok(())
77 }
78
79 fn exit(&mut self) {
80 self.creating.pop();
81 }
82
83 pub fn get_path(&self) -> String {
85 self.creating
86 .iter()
87 .map(|k| k.to_string())
88 .collect::<Vec<_>>()
89 .join(" -> ")
90 }
91}
92
93pub struct Dependencies<'a> {
95 container: &'a BeanContainer,
96 context: &'a mut CreationContext,
97}
98
99impl<'a> Dependencies<'a> {
100 pub fn get<T: Any + Send + Sync + 'static>(&mut self) -> Result<Arc<T>, String> {
102 self.get_named::<T>(None)
103 }
104
105 pub fn get_named<T: Any + Send + Sync + 'static>(
107 &mut self,
108 name: Option<&str>,
109 ) -> Result<Arc<T>, String> {
110 self.container.get_with_context::<T>(name, self.context)
111 }
112
113 pub fn current_path(&self) -> String {
115 self.context.get_path()
116 }
117}
118
119pub trait BeanFactory: Send + Sync {
120 fn create(&self, deps: &mut Dependencies) -> Result<Arc<dyn Any + Send + Sync>, String>;
121}
122
123struct BeanDefinition {
124 factory: Arc<dyn BeanFactory>,
125 scope: Scope,
126 instance: Option<Arc<dyn Any + Send + Sync>>,
127}
128
129pub struct BeanContainer {
130 beans: RwLock<HashMap<Identifier, BeanDefinition>>,
131}
132
133impl BeanContainer {
134 pub fn new() -> Self {
135 BeanContainer {
136 beans: RwLock::new(HashMap::new()),
137 }
138 }
139
140 pub fn register<T, F>(&self, scope: Scope, factory: F) -> Result<(), String>
141 where
142 T: Any + Send + Sync + 'static,
143 F: Fn(&mut Dependencies) -> Result<T, String> + Send + Sync + 'static,
144 {
145 let type_spec_id = Identifier::type_spec::<T>();
146 let unnamed_id = Identifier::unnamed::<T>();
147
148 let bean_factory: Arc<dyn BeanFactory> = Arc::new(move |deps: &mut Dependencies| {
149 let instance = factory(deps)?;
150 Ok(Arc::new(instance) as Arc<dyn Any + Send + Sync>)
151 });
152
153 let definition = BeanDefinition {
154 factory: bean_factory,
155 scope,
156 instance: None,
157 };
158
159 let mut beans = self.beans.write().unwrap();
160
161 if beans.contains_key(&type_spec_id) {
163 return Err(format!("Bean already registered: {}", &type_spec_id));
164 }
165 beans.remove(&unnamed_id);
167 beans.insert(type_spec_id, definition);
169
170 Ok(())
171 }
172
173 pub fn register_named<T, F>(&self, name: &str, scope: Scope, factory: F) -> Result<(), String>
174 where
175 T: Any + Send + Sync + 'static,
176 F: Fn(&mut Dependencies) -> Result<T, String> + Send + Sync + 'static,
177 {
178 let named_id = Identifier::named(name);
179 let type_spec_id = Identifier::type_spec::<T>();
180 let unnamed_id = Identifier::unnamed::<T>();
181
182 let bean_factory: Arc<dyn BeanFactory> = Arc::new(move |deps: &mut Dependencies| {
183 let instance = factory(deps)?;
184 Ok(Arc::new(instance) as Arc<dyn Any + Send + Sync>)
185 });
186
187 let definition = BeanDefinition {
188 factory: bean_factory.clone(),
189 scope,
190 instance: None,
191 };
192
193 let mut beans = self.beans.write().unwrap();
194
195 if beans.contains_key(&named_id) {
197 return Err(format!("Bean already registered with name: {}", name));
198 }
199
200 beans.insert(named_id, definition);
202
203 if !beans.contains_key(&type_spec_id) && !beans.contains_key(&unnamed_id) {
205 let unnamed_definition = BeanDefinition {
206 factory: bean_factory,
207 scope,
208 instance: None,
209 };
210 beans.insert(unnamed_id, unnamed_definition);
211 }
212
213 Ok(())
214 }
215
216 pub fn get<T: Any + Send + Sync + 'static>(&self) -> Arc<T> {
219 self.try_get::<T>(None).unwrap()
220 }
221
222 pub fn get_named<T: Any + Send + Sync + 'static>(&self, name: &str) -> Arc<T> {
225 self.try_get::<T>(Some(name)).unwrap()
226 }
227
228 fn try_get<T: Any + Send + Sync + 'static>(
229 &self,
230 name: Option<&str>,
231 ) -> Result<Arc<T>, String> {
232 let mut context = CreationContext::new();
233 self.get_with_context::<T>(name, &mut context)
234 }
235
236 fn get_with_context<T: Any + Send + Sync + 'static>(
237 &self,
238 name: Option<&str>,
239 context: &mut CreationContext,
240 ) -> Result<Arc<T>, String> {
241 let id = if let Some(n) = name {
243 Identifier::named(n)
244 } else {
245 let type_spec_id = Identifier::type_spec::<T>();
247 let unnamed_id = Identifier::unnamed::<T>();
248
249 let beans = self.beans.read().unwrap();
250 if beans.contains_key(&type_spec_id) {
251 type_spec_id
252 } else if beans.contains_key(&unnamed_id) {
253 unnamed_id
254 } else {
255 return Err(format!("Bean not found: {}", type_spec_id));
256 }
257 };
258
259 context.enter(id.clone())?;
261
262 {
264 let beans = self.beans.read().unwrap();
265 if let Some(definition) = beans.get(&id)
266 && definition.scope == Scope::Singleton
267 && let Some(inst) = &definition.instance
268 {
269 return inst
270 .clone()
271 .downcast::<T>()
272 .map_err(|_| "Type downcast failed".to_string());
273 }
274 }
275
276 let result = (|| -> Result<Arc<T>, String> {
277 let (factory, scope) = {
278 let beans = self.beans.read().unwrap();
279 let definition = beans
280 .get(&id)
281 .ok_or_else(|| format!("Bean not found: {}", id))?;
282
283 if definition.scope == Scope::Singleton
284 && let Some(inst) = &definition.instance
285 {
286 return inst
287 .clone()
288 .downcast::<T>()
289 .map_err(|_| "Type downcast failed".to_string());
290 }
291
292 (definition.factory.clone(), definition.scope)
293 };
294
295 let mut deps = Dependencies {
296 container: self,
297 context,
298 };
299 let new_instance = factory.create(&mut deps)?;
300
301 if scope == Scope::Singleton {
302 let mut beans = self.beans.write().unwrap();
303 if let Some(definition) = beans.get_mut(&id)
304 && definition.instance.is_none()
305 {
306 definition.instance = Some(new_instance.clone());
307 }
308 }
309
310 new_instance
311 .downcast::<T>()
312 .map_err(|_| "Type downcast failed".to_string())
313 })();
314
315 context.exit();
316 result
317 }
318
319 pub fn contains<T: Any + Send + Sync + 'static>(&self, name: Option<&str>) -> bool {
321 let beans = self.beans.read().unwrap();
322
323 if let Some(n) = name {
324 beans.contains_key(&Identifier::Named(n.to_string()))
325 } else {
326 beans.contains_key(&Identifier::type_spec::<T>())
327 || beans.contains_key(&Identifier::unnamed::<T>())
328 }
329 }
330
331 pub fn len(&self) -> usize {
333 self.beans.read().unwrap().len()
334 }
335
336 pub fn is_empty(&self) -> bool {
338 self.beans.read().unwrap().is_empty()
339 }
340}
341
342impl Default for BeanContainer {
343 fn default() -> Self {
344 Self::new()
345 }
346}
347
348impl<F> BeanFactory for F
349where
350 F: Fn(&mut Dependencies) -> Result<Arc<dyn Any + Send + Sync>, String> + Send + Sync,
351{
352 fn create(&self, deps: &mut Dependencies) -> Result<Arc<dyn Any + Send + Sync>, String> {
353 self(deps)
354 }
355}