digdigdig3_station/settings/
store.rs1use std::collections::HashMap;
8use std::path::PathBuf;
9
10use serde_json::Value;
11
12use super::SettingsError;
13
14#[derive(Debug)]
19pub struct SettingsStore {
20 path: PathBuf,
21 map: HashMap<String, Value>,
22}
23
24impl SettingsStore {
25 pub async fn open(
34 root: impl AsRef<std::path::Path>,
35 namespace: &str,
36 ) -> Result<Self, SettingsError> {
37 let path = root.as_ref().join(format!("{namespace}.json"));
38
39 if let Some(parent) = path.parent() {
41 std::fs::create_dir_all(parent)
42 .map_err(|e| SettingsError::Io(e.to_string()))?;
43 }
44
45 let map = if path.exists() {
46 let content = std::fs::read_to_string(&path)
47 .map_err(|e| SettingsError::Io(e.to_string()))?;
48 serde_json::from_str::<HashMap<String, Value>>(&content)
49 .map_err(|e| SettingsError::Serde(e.to_string()))?
50 } else {
51 HashMap::new()
52 };
53
54 Ok(Self { path, map })
55 }
56
57 pub fn get<T: serde::de::DeserializeOwned>(&self, key: &str) -> Option<T> {
62 let value = self.map.get(key)?;
63 serde_json::from_value(value.clone()).ok()
64 }
65
66 pub fn set<T: serde::Serialize>(
70 &mut self,
71 key: &str,
72 value: &T,
73 ) -> Result<(), SettingsError> {
74 let json_value =
75 serde_json::to_value(value).map_err(|e| SettingsError::Serde(e.to_string()))?;
76 self.map.insert(key.to_string(), json_value);
77 Ok(())
78 }
79
80 pub fn remove(&mut self, key: &str) -> bool {
82 self.map.remove(key).is_some()
83 }
84
85 pub fn keys(&self) -> Vec<String> {
87 self.map.keys().cloned().collect()
88 }
89
90 pub fn contains(&self, key: &str) -> bool {
92 self.map.contains_key(key)
93 }
94
95 pub async fn save(&self) -> Result<(), SettingsError> {
100 let json = serde_json::to_string_pretty(&self.map)
101 .map_err(|e| SettingsError::Serde(e.to_string()))?;
102
103 let tmp_path = {
104 let mut p = self.path.clone();
105 let fname = p
106 .file_name()
107 .and_then(|n| n.to_str())
108 .unwrap_or("settings")
109 .to_string();
110 p.set_file_name(format!("{fname}.tmp"));
111 p
112 };
113
114 std::fs::write(&tmp_path, &json)
115 .map_err(|e| SettingsError::Io(e.to_string()))?;
116
117 std::fs::rename(&tmp_path, &self.path)
118 .map_err(|e| SettingsError::Io(e.to_string()))?;
119
120 Ok(())
121 }
122}