reifydb_core/util/ioc/
mod.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4mod resolve_arc;
5mod resolve_rc;
6
7use std::{
8	any::{Any, TypeId, type_name},
9	collections::HashMap,
10	sync::{Arc, RwLock},
11};
12
13use reifydb_type::{Result, diagnostic::internal, error};
14#[allow(unused_imports)]
15pub use resolve_arc::LazyResolveArc;
16pub use resolve_rc::LazyResolveRc;
17
18struct BoxedValue {
19	value: Box<dyn Any + Send + Sync>,
20}
21
22impl BoxedValue {
23	fn new<T: Clone + Any + Send + Sync + 'static>(value: T) -> Self {
24		Self {
25			value: Box::new(value),
26		}
27	}
28
29	fn value<T: Clone + Any + Send + Sync + 'static>(&self) -> Option<T> {
30		self.value.downcast_ref::<T>().cloned()
31	}
32}
33
34/// Lightweight IoC container for dependency injection
35pub struct IocContainer {
36	dependencies: Arc<RwLock<HashMap<TypeId, BoxedValue>>>,
37}
38
39impl IocContainer {
40	pub fn new() -> Self {
41		Self {
42			dependencies: Arc::new(RwLock::new(HashMap::new())),
43		}
44	}
45
46	pub fn register<T: Clone + Any + Send + Sync + 'static>(self, service: T) -> Self {
47		self.dependencies.write().unwrap().insert(TypeId::of::<T>(), BoxedValue::new(service));
48		self
49	}
50
51	pub fn resolve<T: Clone + Any + Send + Sync + 'static>(&self) -> Result<T> {
52		self.dependencies
53			.read()
54			.unwrap()
55			.get(&TypeId::of::<T>())
56			.and_then(|boxed| boxed.value::<T>())
57			.ok_or_else(|| {
58				error!(internal(format!("Type {} not registered in IoC container", type_name::<T>())))
59			})
60	}
61}
62
63impl Clone for IocContainer {
64	fn clone(&self) -> Self {
65		Self {
66			dependencies: self.dependencies.clone(),
67		}
68	}
69}
70
71impl Default for IocContainer {
72	fn default() -> Self {
73		Self::new()
74	}
75}