@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "db"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
rustc-hash = "2"
|
||||
serde_json = "1"
|
||||
@@ -0,0 +1,115 @@
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
pub const PERSIST_PATH: &str = "/run/lxdeviced.json";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Db {
|
||||
path: Option<PathBuf>,
|
||||
map: RwLock<FxHashMap<String, String>>,
|
||||
}
|
||||
impl Db {
|
||||
pub fn open_in_memory() -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
path: None,
|
||||
map: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn open(path: impl Into<PathBuf>) -> Arc<Self> {
|
||||
let path = path.into();
|
||||
let text = std::fs::read_to_string(&path).unwrap_or_default();
|
||||
let map = serde_json::from_str(&text).unwrap_or_default();
|
||||
Arc::new(Self {
|
||||
path: Some(path),
|
||||
map: RwLock::new(map),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn section(self: &Arc<Self>, name: impl Into<String>) -> DbSection {
|
||||
DbSection {
|
||||
name: name.into(),
|
||||
db: self.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(&self) {
|
||||
if let Some(path) = &self.path {
|
||||
let text = serde_json::to_string(&*self.map.read().unwrap()).unwrap();
|
||||
_ = std::fs::write(&path, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DbSection {
|
||||
name: String,
|
||||
db: Arc<Db>,
|
||||
}
|
||||
impl DbSection {
|
||||
pub fn db(&self) -> &Arc<Db> {
|
||||
&self.db
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
let mut map = self.db.map.write().unwrap();
|
||||
let mut keys = Vec::new();
|
||||
let prefix = self.real_key_name("");
|
||||
for key in map.keys() {
|
||||
if key.starts_with(&prefix) {
|
||||
keys.push(key.clone());
|
||||
}
|
||||
}
|
||||
for key in keys {
|
||||
map.remove(&key);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&self, key: &str, val: String) -> Option<String> {
|
||||
let mut map = self.db.map.write().unwrap();
|
||||
map.insert(self.real_key_name(key), val)
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &str) -> Option<String> {
|
||||
self.db
|
||||
.map
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&self.real_key_name(key))
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn remove(&self, key: &str) -> Option<String> {
|
||||
self.db
|
||||
.map
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(&self.real_key_name(key))
|
||||
}
|
||||
|
||||
pub fn restore(&self, dump: FxHashMap<String, String>) {
|
||||
self.clear();
|
||||
for (k, v) in dump {
|
||||
self.insert(&k, v);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump(&self) -> FxHashMap<String, String> {
|
||||
let mut result = FxHashMap::default();
|
||||
let prefix = self.real_key_name("");
|
||||
let total = self.db.map.read().unwrap();
|
||||
for (key, val) in total.iter() {
|
||||
if let Some(realkey) = key.strip_prefix(&prefix) {
|
||||
result.insert(realkey.into(), val.into());
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn real_key_name(&self, name: &str) -> String {
|
||||
format!("{}\0{}", self.name, name)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user