diff options
author | Vika <vika@fireburn.ru> | 2023-06-15 17:02:39 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2023-06-15 17:02:39 +0300 |
commit | eca7687439c2b6f804603de75501b6737a82e5a2 (patch) | |
tree | a4715e0b8d3d63ee8b77830670c473b83a70031e /kittybox-rs/src/database/file/mod.rs | |
parent | 59f3e2d43d30642e4242039ce3ab934961e69602 (diff) | |
download | kittybox-eca7687439c2b6f804603de75501b6737a82e5a2.tar.zst |
Database: use newtypes to represent settings
This allows much for a cleaner and idiomatic settings interface.
Diffstat (limited to 'kittybox-rs/src/database/file/mod.rs')
-rw-r--r-- | kittybox-rs/src/database/file/mod.rs | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/kittybox-rs/src/database/file/mod.rs b/kittybox-rs/src/database/file/mod.rs index bafb7bf..9319b67 100644 --- a/kittybox-rs/src/database/file/mod.rs +++ b/kittybox-rs/src/database/file/mod.rs @@ -1,5 +1,5 @@ //#![warn(clippy::unwrap_used)] -use crate::database::{filter_post, ErrorKind, Result, Settings, Storage, StorageError}; +use crate::database::{filter_post, ErrorKind, Result, settings, Storage, StorageError}; use async_trait::async_trait; use futures::{stream, StreamExt, TryStreamExt}; use serde_json::json; @@ -582,7 +582,7 @@ impl Storage for FileStorage { } #[tracing::instrument(skip(self))] - async fn get_setting(&self, setting: Settings, user: &'_ str) -> Result<String> { + async fn get_setting<S: settings::Setting<'a>, 'a>(&self, user: &'_ str) -> Result<S> { debug!("User for getting settings: {}", user); let url = axum::http::Uri::try_from(user).expect("Couldn't parse a URL"); let mut path = relative_path::RelativePathBuf::new(); @@ -591,22 +591,20 @@ impl Storage for FileStorage { let path = path.to_path(&self.root_dir); debug!("Getting settings from {:?}", &path); - let setting = setting.to_string(); + let mut file = File::open(path).await?; let mut content = String::new(); file.read_to_string(&mut content).await?; - let settings: HashMap<String, String> = serde_json::from_str(&content)?; - // XXX consider returning string slices instead of cloning a string every time - // it might come with a performance hit and/or memory usage inflation - settings - .get(&setting) - .cloned() - .ok_or_else(|| StorageError::new(ErrorKind::Backend, "Setting not set")) + let settings: HashMap<&str, serde_json::Value> = serde_json::from_str(&content)?; + match settings.get(S::ID) { + Some(value) => Ok(serde_json::from_value::<S>(value.clone())?), + None => Err(StorageError::new(ErrorKind::Backend, "Setting not set")) + } } #[tracing::instrument(skip(self))] - async fn set_setting(&self, setting: Settings, user: &'_ str, value: &'_ str) -> Result<()> { + async fn set_setting<S: settings::Setting<'a>, 'a>(&self, user: &'_ str, value: S::Data) -> Result<()> { let url = axum::http::Uri::try_from(user).expect("Couldn't parse a URL"); let mut path = relative_path::RelativePathBuf::new(); path.push(url.authority().unwrap().to_string()); @@ -620,33 +618,32 @@ impl Storage for FileStorage { tokio::fs::create_dir_all(path.parent().unwrap()).await?; } - let (setting, value) = (setting.to_string(), value.to_string()); - let mut tempfile = OpenOptions::new() .write(true) .create_new(true) .open(&temppath) .await?; - let mut settings: HashMap<String, String> = match File::open(&path).await { + let mut settings: HashMap<String, serde_json::Value> = match File::open(&path).await { Ok(mut f) => { let mut content = String::new(); f.read_to_string(&mut content).await?; if content.is_empty() { - HashMap::default() + Default::default() } else { serde_json::from_str(&content)? } } Err(err) => { if err.kind() == IOErrorKind::NotFound { - HashMap::default() + Default::default() } else { return Err(err.into()); } } }; - settings.insert(setting, value); + settings.insert(S::ID.to_owned(), serde_json::to_value(S::new(value))?); + tempfile .write_all(serde_json::to_string(&settings)?.as_bytes()) .await?; |