Skip to main content

rs_bean/
bean.rs

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 Bean
15    Named(String),
16    // Type-specific default Bean
17    TypeSpec(TypeId, &'static str),
18    // Unnamed temporary Bean (replaced by TypeSpec)
19    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
46/// Creation context
47struct CreationContext {
48    // Creation stack
49    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        // Check for circular dependencies
65        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    /// get current dependency path
84    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
93/// Dependency provider
94pub struct Dependencies<'a> {
95    container: &'a BeanContainer,
96    context: &'a mut CreationContext,
97}
98
99impl<'a> Dependencies<'a> {
100    /// Get bean with default name
101    pub fn get<T: Any + Send + Sync + 'static>(&mut self) -> Result<Arc<T>, String> {
102        self.get_named::<T>(None)
103    }
104
105    /// Get bean with specified name
106    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    /// Get current dependency path (for debugging)
114    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 TypeSpec exists, throw error
162        if beans.contains_key(&type_spec_id) {
163            return Err(format!("Bean already registered: {}", &type_spec_id));
164        }
165        // If unnamed exists, remove it
166        beans.remove(&unnamed_id);
167        // Add TypeSpec
168        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        // Check if Named already exists
196        if beans.contains_key(&named_id) {
197            return Err(format!("Bean already registered with name: {}", name));
198        }
199
200        // Register Named
201        beans.insert(named_id, definition);
202
203        // Rule 1: If TypeSpec and Unnamed do not exist, add Unnamed
204        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    /// Get bean by type
217    /// **NOTE**: panics if bean not found
218    pub fn get<T: Any + Send + Sync + 'static>(&self) -> Arc<T> {
219        self.try_get::<T>(None).unwrap()
220    }
221
222    /// Get named bean by type
223    /// **NOTE**: panics if bean not found
224    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        // Determine the key to look up
242        let id = if let Some(n) = name {
243            Identifier::named(n)
244        } else {
245            // Prefer TypeSpec, then Unnamed
246            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        // Check for circular dependencies
260        context.enter(id.clone())?;
261
262        // Check if singleton is already created
263        {
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    /// Check if the container contains the specified bean
320    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    /// Get the number of registered beans
332    pub fn len(&self) -> usize {
333        self.beans.read().unwrap().len()
334    }
335
336    /// Check if the container is empty
337    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}