use std::fs;
use lazy_static::lazy_static;
use serde_json::Value;
use std::collections::HashMap;
use std::sync::RwLock;
use serde::de::DeserializeOwned;
pub trait ConfigModule {
fn get(&self, name: &str) -> Option<&str>;
}
lazy_static! {
static ref CONFIGS: RwLock<HashMap<String, Value>> = RwLock::new(HashMap::new());
}
pub struct Config {
name: String,
}
impl Config {
pub fn new(name: &str) -> Self {
let has = {
let configs = CONFIGS.read().unwrap();
configs.get(name).is_some()
};
if !has {
let mut configs = CONFIGS.write().unwrap();
configs.insert(name.to_string(), from_name(name));
}
Config {
name: name.to_string(),
}
}
pub fn get<T: DeserializeOwned>(&self, path: &str) -> Option<T> {
let configs = CONFIGS.read().unwrap();
let value = configs.get(&self.name)?;
let mut current = value;
for key in path.split('.') {
current = match current.get(key) {
Some(v) => v,
None => return None,
};
}
serde_json::from_value(current.clone()).ok()
}
}
fn from_name(name: &str) -> Value {
let filename = format!("configs/{}.json", name);
let content = fs::read_to_string(&filename)
.unwrap_or_else(|_| panic!("Failed to read config file: {}", filename));
serde_json::from_str(&content).unwrap_or_else(|_| panic!("Invalid JSON format in {}", filename))
}