elif_core/container/
scope.rs

1/// Service scope enumeration
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
3pub enum ServiceScope {
4    /// Single instance shared across the application
5    #[default]
6    Singleton,
7    /// New instance created for each request
8    Transient,
9    /// Instance scoped to a particular context (e.g., request scope)
10    Scoped,
11}
12
13impl ServiceScope {
14    /// Check if the scope is singleton
15    pub fn is_singleton(&self) -> bool {
16        matches!(self, ServiceScope::Singleton)
17    }
18    
19    /// Check if the scope is transient
20    pub fn is_transient(&self) -> bool {
21        matches!(self, ServiceScope::Transient)
22    }
23    
24    /// Check if the scope is scoped
25    pub fn is_scoped(&self) -> bool {
26        matches!(self, ServiceScope::Scoped)
27    }
28    
29    /// Get the scope name as a string
30    pub fn as_str(&self) -> &'static str {
31        match self {
32            ServiceScope::Singleton => "singleton",
33            ServiceScope::Transient => "transient",
34            ServiceScope::Scoped => "scoped",
35        }
36    }
37}
38
39
40impl std::fmt::Display for ServiceScope {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        write!(f, "{}", self.as_str())
43    }
44}
45
46impl std::str::FromStr for ServiceScope {
47    type Err = crate::errors::CoreError;
48    
49    fn from_str(s: &str) -> Result<Self, Self::Err> {
50        match s.to_lowercase().as_str() {
51            "singleton" => Ok(ServiceScope::Singleton),
52            "transient" => Ok(ServiceScope::Transient),
53            "scoped" => Ok(ServiceScope::Scoped),
54            _ => Err(crate::errors::CoreError::InvalidServiceScope {
55                scope: s.to_string(),
56            }),
57        }
58    }
59}
60
61/// Scoped service manager for managing services within a specific scope
62#[derive(Debug)]
63pub struct ScopedServiceManager {
64    scope_id: uuid::Uuid,
65    services: std::collections::HashMap<std::any::TypeId, Box<dyn std::any::Any + Send + Sync>>,
66}
67
68impl ScopedServiceManager {
69    /// Create a new scoped service manager
70    pub fn new() -> Self {
71        Self {
72            scope_id: uuid::Uuid::new_v4(),
73            services: std::collections::HashMap::new(),
74        }
75    }
76    
77    /// Get the scope ID
78    pub fn scope_id(&self) -> uuid::Uuid {
79        self.scope_id
80    }
81    
82    /// Add a service to this scope
83    pub fn add_service<T>(&mut self, service: T)
84    where
85        T: Send + Sync + 'static,
86    {
87        let type_id = std::any::TypeId::of::<T>();
88        self.services.insert(type_id, Box::new(service));
89    }
90    
91    /// Get a service from this scope
92    pub fn get_service<T>(&self) -> Option<&T>
93    where
94        T: Send + Sync + 'static,
95    {
96        let type_id = std::any::TypeId::of::<T>();
97        self.services.get(&type_id)?.downcast_ref::<T>()
98    }
99    
100    /// Check if a service exists in this scope
101    pub fn has_service<T>(&self) -> bool
102    where
103        T: Send + Sync + 'static,
104    {
105        let type_id = std::any::TypeId::of::<T>();
106        self.services.contains_key(&type_id)
107    }
108    
109    /// Clear all services from this scope
110    pub fn clear(&mut self) {
111        self.services.clear();
112    }
113    
114    /// Get the number of services in this scope
115    pub fn service_count(&self) -> usize {
116        self.services.len()
117    }
118}
119
120impl Default for ScopedServiceManager {
121    fn default() -> Self {
122        Self::new()
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use super::*;
129    
130    #[test]
131    fn test_service_scope_from_str() {
132        assert_eq!("singleton".parse::<ServiceScope>().unwrap(), ServiceScope::Singleton);
133        assert_eq!("transient".parse::<ServiceScope>().unwrap(), ServiceScope::Transient);
134        assert_eq!("scoped".parse::<ServiceScope>().unwrap(), ServiceScope::Scoped);
135        
136        assert!("invalid".parse::<ServiceScope>().is_err());
137    }
138    
139    #[test]
140    fn test_service_scope_display() {
141        assert_eq!(format!("{}", ServiceScope::Singleton), "singleton");
142        assert_eq!(format!("{}", ServiceScope::Transient), "transient");
143        assert_eq!(format!("{}", ServiceScope::Scoped), "scoped");
144    }
145    
146    #[test]
147    fn test_scoped_service_manager() {
148        let mut manager = ScopedServiceManager::new();
149        
150        manager.add_service("test_string".to_string());
151        manager.add_service(42u32);
152        
153        assert!(manager.has_service::<String>());
154        assert!(manager.has_service::<u32>());
155        assert!(!manager.has_service::<i32>());
156        
157        assert_eq!(manager.get_service::<String>(), Some(&"test_string".to_string()));
158        assert_eq!(manager.get_service::<u32>(), Some(&42u32));
159        
160        assert_eq!(manager.service_count(), 2);
161        
162        manager.clear();
163        assert_eq!(manager.service_count(), 0);
164    }
165}