From eca7687439c2b6f804603de75501b6737a82e5a2 Mon Sep 17 00:00:00 2001 From: Vika Date: Thu, 15 Jun 2023 17:02:39 +0300 Subject: Database: use newtypes to represent settings This allows much for a cleaner and idiomatic settings interface. --- kittybox-rs/src/database/file/mod.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'kittybox-rs/src/database/file') 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 { + async fn get_setting, 'a>(&self, user: &'_ str) -> Result { 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 = 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::(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, '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 = match File::open(&path).await { + let mut settings: HashMap = 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?; -- cgit 1.4.1