use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::{OnceLock, RwLock};
static CONFIG_REPOSITORY: OnceLock<RwLock<ConfigRepository>> = OnceLock::new();
pub struct ConfigRepository {
configs: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
}
impl ConfigRepository {
pub fn new() -> Self {
Self {
configs: HashMap::new(),
}
}
pub fn register<T: Any + Send + Sync + 'static>(&mut self, config: T) {
self.configs.insert(TypeId::of::<T>(), Box::new(config));
}
pub fn get<T: Any + Send + Sync + Clone + 'static>(&self) -> Option<T> {
self.configs
.get(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast_ref::<T>())
.cloned()
}
pub fn has<T: Any + 'static>(&self) -> bool {
self.configs.contains_key(&TypeId::of::<T>())
}
}
impl Default for ConfigRepository {
fn default() -> Self {
Self::new()
}
}
pub fn init_repository() -> &'static RwLock<ConfigRepository> {
CONFIG_REPOSITORY.get_or_init(|| RwLock::new(ConfigRepository::new()))
}
pub fn register<T: Any + Send + Sync + 'static>(config: T) {
let repo = init_repository();
if let Ok(mut repo) = repo.write() {
repo.register(config);
}
}
pub fn get<T: Any + Send + Sync + Clone + 'static>() -> Option<T> {
let repo = CONFIG_REPOSITORY.get()?;
repo.read().ok()?.get::<T>()
}
pub fn has<T: Any + 'static>() -> bool {
CONFIG_REPOSITORY
.get()
.and_then(|repo| repo.read().ok())
.map(|repo| repo.has::<T>())
.unwrap_or(false)
}