Skip to main content

kabel/
lib.rs

1#[cfg(feature = "axum")]
2pub mod axum;
3pub mod error;
4#[cfg(feature = "jav")]
5pub mod jav;
6pub mod scope;
7
8use std::{
9	any::{Any, TypeId},
10	sync::{Arc, OnceLock},
11};
12
13use arc_swap::ArcSwapOption;
14use scc::HashMap;
15
16use crate::{
17	error::{ServiceAlreadyExistsError, ServiceNotFoundError},
18	scope::{Scope, ScopeProvider, get_default_scope_full},
19};
20
21pub struct DI<T: ?Sized + Send + Sync + 'static>(pub Arc<T>);
22pub struct DIK<T: ?Sized + Send + Sync + 'static, K: 'static>(
23	pub Arc<T>,
24	pub std::marker::PhantomData<K>,
25);
26
27#[derive(Clone)]
28pub enum Service {
29	Singleton(Arc<dyn Any + Send + Sync>),
30	Transient(Arc<dyn Fn() -> Arc<dyn Any + Send + Sync> + Send + Sync>),
31	Scoped(Arc<dyn Fn() -> Arc<dyn Any + Send + Sync> + Send + Sync>),
32}
33
34#[derive(Clone)]
35pub struct ServiceCollection {
36	collection: HashMap<(TypeId, Option<TypeId>), Service>,
37}
38
39impl ServiceCollection {
40	pub fn new() -> Self {
41		Self {
42			collection: HashMap::new(),
43		}
44	}
45
46	pub fn add_singleton<T: Send + Sync + 'static>(
47		&self,
48		service: T,
49	) -> Result<(), ServiceAlreadyExistsError> {
50		self.add_internal::<T>(Service::Singleton(Arc::new(Arc::new(service))), None)
51	}
52
53	pub fn add_singleton_keyed<T: Send + Sync + 'static>(
54		&self,
55		service: T,
56		key: TypeId,
57	) -> Result<(), ServiceAlreadyExistsError> {
58		self.add_internal::<T>(Service::Singleton(Arc::new(Arc::new(service))), Some(key))
59	}
60
61	pub fn add_singleton_trait<Trait: ?Sized + Send + Sync + 'static>(
62		&self,
63		service: Arc<Trait>,
64	) -> Result<(), ServiceAlreadyExistsError> {
65		self.add_internal::<Trait>(Service::Singleton(Arc::new(service)), None)
66	}
67
68	pub fn add_singleton_trait_keyed<Trait: ?Sized + Send + Sync + 'static>(
69		&self,
70		service: Arc<Trait>,
71		key: TypeId,
72	) -> Result<(), ServiceAlreadyExistsError> {
73		self.add_internal::<Trait>(Service::Singleton(Arc::new(service)), Some(key))
74	}
75
76	fn add_internal<T: ?Sized + Send + Sync + 'static>(
77		&self,
78		service: Service,
79		key: Option<TypeId>,
80	) -> Result<(), ServiceAlreadyExistsError> {
81		let tid = (TypeId::of::<T>(), key);
82		if self.collection.contains_sync(&tid) {
83			return Err(ServiceAlreadyExistsError);
84		}
85		let _ = self.collection.insert_sync(tid, service);
86		Ok(())
87	}
88
89	pub fn add_transient<T: Send + Sync + 'static, F>(
90		&self,
91		service_factory: F,
92	) -> Result<(), ServiceAlreadyExistsError>
93	where
94		F: Fn() -> T + Send + Sync + 'static,
95	{
96		self.add_internal::<T>(
97			Service::Transient(Arc::new(move || Arc::new(Arc::new(service_factory())))),
98			None,
99		)
100	}
101	pub fn add_transient_keyed<T: Send + Sync + 'static, F>(
102		&self,
103		service_factory: F,
104		key: TypeId,
105	) -> Result<(), ServiceAlreadyExistsError>
106	where
107		F: Fn() -> T + Send + Sync + 'static,
108	{
109		self.add_internal::<T>(
110			Service::Transient(Arc::new(move || Arc::new(Arc::new(service_factory())))),
111			Some(key),
112		)
113	}
114
115	pub fn add_transient_trait<Trait: ?Sized + Send + Sync + 'static, F>(
116		&self,
117		service_factory: F,
118	) -> Result<(), ServiceAlreadyExistsError>
119	where
120		F: Fn() -> Arc<Trait> + Send + Sync + 'static,
121	{
122		self.add_internal::<Trait>(
123			Service::Transient(Arc::new(move || Arc::new(service_factory()))),
124			None,
125		)
126	}
127
128	pub fn add_transient_trait_keyed<Trait: ?Sized + Send + Sync + 'static, F>(
129		&self,
130		service_factory: F,
131		key: TypeId,
132	) -> Result<(), ServiceAlreadyExistsError>
133	where
134		F: Fn() -> Arc<Trait> + Send + Sync + 'static,
135	{
136		self.add_internal::<Trait>(
137			Service::Transient(Arc::new(move || Arc::new(service_factory()))),
138			Some(key),
139		)
140	}
141
142	pub fn add_scoped<T: Send + Sync + 'static, F>(
143		&self,
144		service_factory: F,
145	) -> Result<(), ServiceAlreadyExistsError>
146	where
147		F: Fn() -> T + Send + Sync + 'static,
148	{
149		self.add_internal::<T>(
150			Service::Scoped(Arc::new(move || Arc::new(Arc::new(service_factory())))),
151			None,
152		)
153	}
154	pub fn add_scoped_keyed<T: Send + Sync + 'static, F>(
155		&self,
156		service_factory: F,
157		key: TypeId,
158	) -> Result<(), ServiceAlreadyExistsError>
159	where
160		F: Fn() -> T + Send + Sync + 'static,
161	{
162		self.add_internal::<T>(
163			Service::Scoped(Arc::new(move || Arc::new(Arc::new(service_factory())))),
164			Some(key),
165		)
166	}
167
168	pub fn add_scoped_trait<Trait: ?Sized + Send + Sync + 'static, F>(
169		&self,
170		service_factory: F,
171	) -> Result<(), ServiceAlreadyExistsError>
172	where
173		F: Fn() -> Arc<Trait> + Send + Sync + 'static,
174	{
175		self.add_internal::<Trait>(
176			Service::Scoped(Arc::new(move || Arc::new(service_factory()))),
177			None,
178		)
179	}
180
181	pub fn add_scoped_trait_keyed<Trait: ?Sized + Send + Sync + 'static, F>(
182		&self,
183		service_factory: F,
184		key: TypeId,
185	) -> Result<(), ServiceAlreadyExistsError>
186	where
187		F: Fn() -> Arc<Trait> + Send + Sync + 'static,
188	{
189		self.add_internal::<Trait>(
190			Service::Scoped(Arc::new(move || Arc::new(service_factory()))),
191			Some(key),
192		)
193	}
194
195	pub fn create_scope(&self) -> Arc<Scope> {
196		let scope: Scope = HashMap::new();
197		self.collection.iter_sync(|k, v| {
198			let Service::Scoped(_) = v else {
199				return true;
200			};
201			let _ = scope.insert_sync(k.clone(), OnceLock::new());
202			true
203		});
204		Arc::new(scope)
205	}
206
207	fn di_internal<T: ?Sized + Send + Sync + 'static>(
208		&self,
209		key: Option<TypeId>,
210		scope: Option<Arc<Arc<dyn ScopeProvider>>>,
211	) -> Result<Arc<T>, ServiceNotFoundError> {
212		let tid = (TypeId::of::<T>(), key);
213		if let Some(s) = self.collection.read_sync(&tid, |_, s| match s {
214			Service::Singleton(service) if let Ok(res) = service.clone().downcast::<Arc<T>>() => {
215				Ok((*res).clone())
216			},
217			Service::Transient(factory) => {
218				let instance = factory.clone()();
219				if let Ok(res) = instance.downcast::<Arc<T>>() {
220					Ok((*res).clone())
221				} else {
222					Err(ServiceNotFoundError)
223				}
224			},
225			Service::Scoped(factory) => {
226				let scope = scope
227					.unwrap_or_else(|| get_default_scope_full())
228					.provide_scope()?;
229				let Some(res) = scope.get_sync(&tid) else {
230					return Err(ServiceNotFoundError);
231				};
232				let instance = res.get_or_init(|| factory.clone()()).clone();
233				if let Ok(res) = instance.downcast::<Arc<T>>() {
234					Ok((*res).clone())
235				} else {
236					Err(ServiceNotFoundError)
237				}
238			},
239			_ => Err(ServiceNotFoundError),
240		}) {
241			return s;
242		} else {
243			Err(ServiceNotFoundError)
244		}
245	}
246
247	pub fn dir<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, ServiceNotFoundError> {
248		self.di_internal(None, None)
249	}
250
251	pub fn dikr<T: ?Sized + Send + Sync + 'static, K: 'static>(
252		&self,
253	) -> Result<Arc<T>, ServiceNotFoundError> {
254		self.di_internal(Some(TypeId::of::<K>()), None)
255	}
256
257	pub fn disr<T: ?Sized + Send + Sync + 'static>(
258		&self,
259		scope: Arc<Arc<dyn ScopeProvider>>,
260	) -> Result<Arc<T>, ServiceNotFoundError> {
261		self.di_internal(None, Some(scope))
262	}
263	pub fn diskr<T: ?Sized + Send + Sync + 'static, K: 'static>(
264		&self,
265		scope: Arc<Arc<dyn ScopeProvider>>,
266	) -> Result<Arc<T>, ServiceNotFoundError> {
267		self.di_internal(Some(TypeId::of::<K>()), Some(scope))
268	}
269
270	pub fn di<T: ?Sized + Send + Sync + 'static>(&self) -> Arc<T> {
271		self.di_internal(None, None)
272			.expect("Failed to find service")
273	}
274
275	pub fn dik<T: ?Sized + Send + Sync + 'static, K: 'static>(&self) -> Arc<T> {
276		self.di_internal(Some(TypeId::of::<K>()), None)
277			.expect("Failed to find service")
278	}
279
280	pub fn dis<T: ?Sized + Send + Sync + 'static>(
281		&self,
282		scope: Arc<Arc<dyn ScopeProvider>>,
283	) -> Arc<T> {
284		self.di_internal(None, Some(scope))
285			.expect("Failed to find service")
286	}
287	pub fn disk<T: ?Sized + Send + Sync + 'static, K: 'static>(
288		&self,
289		scope: Arc<Arc<dyn ScopeProvider>>,
290	) -> Arc<T> {
291		self.di_internal(Some(TypeId::of::<K>()), Some(scope))
292			.expect("Failed to find service")
293	}
294}
295
296static SERVICE_PROVIDER: ArcSwapOption<ServiceCollection> = ArcSwapOption::const_empty();
297
298pub fn spo() -> Option<Arc<ServiceCollection>> {
299	SERVICE_PROVIDER.load_full()
300}
301
302pub fn sp() -> Arc<ServiceCollection> {
303	spo().expect("ServiceProvider not yet initialized")
304}
305
306pub fn set_sp(sp: ServiceCollection) -> Option<Arc<ServiceCollection>> {
307	set_sp_arc(Arc::new(sp))
308}
309pub fn set_sp_arc(sp: Arc<ServiceCollection>) -> Option<Arc<ServiceCollection>> {
310	SERVICE_PROVIDER.swap(Some(sp))
311}
312
313pub fn init_sp() {
314	set_sp(ServiceCollection::new());
315}