use serde::{de::DeserializeOwned, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
#[derive(Debug)]
pub struct LocalDatabase<T> {
path: PathBuf,
data: Mutex<HashMap<String, T>>,
}
impl<T> LocalDatabase<T>
where
T: Serialize + DeserializeOwned + Clone + Default,
{
#[must_use]
pub fn open<P: AsRef<Path>>(path: P) -> Self {
let path = path.as_ref();
let parent_dir = path.parent().expect("Failed to get parent directory");
fs::create_dir_all(parent_dir).expect("Failed to create parent directory");
let data = if path.exists() {
let content = fs::read_to_string(path).expect("Failed to read the file");
serde_json::from_str(&content).unwrap_or_default()
} else {
HashMap::new()
};
Self {
path: path.to_owned(),
data: Mutex::new(data),
}
}
pub fn len(&self) -> usize {
let data = self.data.lock().unwrap();
data.len()
}
pub fn is_empty(&self) -> bool {
let data = self.data.lock().unwrap();
data.is_empty()
}
pub fn set(&self, key: &str, value: T) {
let mut data = self.data.lock().unwrap();
let _old = data.insert(key.to_string(), value);
let json_string = serde_json::to_string(&*data).expect("Failed to serialize data to JSON");
fs::write(&self.path, json_string).expect("Failed to write to the file");
}
pub fn get(&self, key: &str) -> Option<T> {
let data = self.data.lock().unwrap();
data.get(key).cloned()
}
}