elif_core/container/
scope.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
3pub enum ServiceScope {
4 #[default]
6 Singleton,
7 Transient,
9 Scoped,
11}
12
13impl ServiceScope {
14 pub fn is_singleton(&self) -> bool {
16 matches!(self, ServiceScope::Singleton)
17 }
18
19 pub fn is_transient(&self) -> bool {
21 matches!(self, ServiceScope::Transient)
22 }
23
24 pub fn is_scoped(&self) -> bool {
26 matches!(self, ServiceScope::Scoped)
27 }
28
29 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#[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 pub fn new() -> Self {
71 Self {
72 scope_id: uuid::Uuid::new_v4(),
73 services: std::collections::HashMap::new(),
74 }
75 }
76
77 pub fn scope_id(&self) -> uuid::Uuid {
79 self.scope_id
80 }
81
82 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 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 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 pub fn clear(&mut self) {
111 self.services.clear();
112 }
113
114 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}