diff options
author | Vika <vika@fireburn.ru> | 2023-06-22 20:25:28 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2023-06-22 20:25:28 +0300 |
commit | ff358723da641af9f4ae1f742eb1b382f4630220 (patch) | |
tree | 32a2319a0bea909b9d267e44fa3a632991ddda12 | |
parent | 0285e630f3cae1ee2df2c7c465998b1ce669944f (diff) | |
download | kittybox-ff358723da641af9f4ae1f742eb1b382f4630220.tar.zst |
StorageError: use std::borrow::Cow for msg field
This allows avoiding an unnecessary allocation whenever the error message is static.
-rw-r--r-- | kittybox-rs/src/database/file/mod.rs | 19 | ||||
-rw-r--r-- | kittybox-rs/src/database/memory.rs | 10 | ||||
-rw-r--r-- | kittybox-rs/src/database/mod.rs | 28 |
3 files changed, 36 insertions, 21 deletions
diff --git a/kittybox-rs/src/database/file/mod.rs b/kittybox-rs/src/database/file/mod.rs index 9319b67..531f7b1 100644 --- a/kittybox-rs/src/database/file/mod.rs +++ b/kittybox-rs/src/database/file/mod.rs @@ -3,6 +3,7 @@ use crate::database::{filter_post, ErrorKind, Result, settings, Storage, Storage use async_trait::async_trait; use futures::{stream, StreamExt, TryStreamExt}; use serde_json::json; +use std::borrow::Cow; use std::collections::HashMap; use std::io::ErrorKind as IOErrorKind; use std::path::{Path, PathBuf}; @@ -19,7 +20,7 @@ impl From<std::io::Error> for StorageError { IOErrorKind::AlreadyExists => ErrorKind::Conflict, _ => ErrorKind::Backend, }, - "file I/O error", + Cow::Owned(format!("file I/O error: {}", &source)), Box::new(source), ) } @@ -29,7 +30,7 @@ impl From<tokio::time::error::Elapsed> for StorageError { fn from(source: tokio::time::error::Elapsed) -> Self { Self::with_source( ErrorKind::Backend, - "timeout on I/O operation", + Cow::Borrowed("timeout on I/O operation"), Box::new(source), ) } @@ -135,7 +136,7 @@ fn modify_post(post: &serde_json::Value, update: &serde_json::Value) -> Result<s .or_default() .extend(v.clone()); } else { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::BadRequest, "Malformed update object", )); @@ -147,7 +148,7 @@ fn modify_post(post: &serde_json::Value, update: &serde_json::Value) -> Result<s if let Some(v) = v.as_array() { add_keys.insert(k.to_string(), v.clone()); } else { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::BadRequest, "Malformed update object", )); @@ -160,7 +161,7 @@ fn modify_post(post: &serde_json::Value, update: &serde_json::Value) -> Result<s if let Some(v) = v.as_array() { add_keys.insert(k.to_string(), v.clone()); } else { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::BadRequest, "Malformed update object", )); @@ -358,7 +359,7 @@ impl Storage for FileStorage { let orig = path.clone(); // We're supposed to have a parent here. let basedir = link.parent().ok_or_else(|| { - StorageError::new( + StorageError::from_static( ErrorKind::Backend, "Failed to calculate parent directory when creating a symlink", ) @@ -551,7 +552,7 @@ impl Storage for FileStorage { Err(err) => { return Err(StorageError::with_source( ErrorKind::Other, - "Feed assembly error", + Cow::Owned(format!("Feed assembly error: {}", &err)), Box::new(err), )); } @@ -560,7 +561,7 @@ impl Storage for FileStorage { hydrate_author(&mut feed, user, self).await; Ok(Some(feed)) } else { - Err(StorageError::new( + Err(StorageError::from_static( ErrorKind::PermissionDenied, "specified user cannot access this post", )) @@ -599,7 +600,7 @@ impl Storage for FileStorage { 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")) + None => Err(StorageError::from_static(ErrorKind::Backend, "Setting not set")) } } diff --git a/kittybox-rs/src/database/memory.rs b/kittybox-rs/src/database/memory.rs index 2fb55e5..9d79ecc 100644 --- a/kittybox-rs/src/database/memory.rs +++ b/kittybox-rs/src/database/memory.rs @@ -46,7 +46,7 @@ impl Storage for MemoryStorage { let key: &str = match post["properties"]["uid"][0].as_str() { Some(uid) => uid, None => { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::Other, "post doesn't have a UID", )) @@ -108,7 +108,7 @@ impl Storage for MemoryStorage { .or_default() .extend(v.clone()); } else { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::BadRequest, "Malformed update object", )); @@ -120,7 +120,7 @@ impl Storage for MemoryStorage { if v.is_array() { add_keys.insert(k.to_string(), v.clone()); } else { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::BadRequest, "Malformed update object", )); @@ -139,7 +139,7 @@ impl Storage for MemoryStorage { if let Some(new_post) = mapping.get(url) { post = new_post } else { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::NotFound, "The post you have requested is not found in the database.", )); @@ -191,7 +191,7 @@ impl Storage for MemoryStorage { post, ); } else { - return Err(StorageError::new( + return Err(StorageError::from_static( ErrorKind::NotFound, "The designated post wasn't found in the database.", )); diff --git a/kittybox-rs/src/database/mod.rs b/kittybox-rs/src/database/mod.rs index db0e360..ea4205c 100644 --- a/kittybox-rs/src/database/mod.rs +++ b/kittybox-rs/src/database/mod.rs @@ -1,4 +1,6 @@ #![warn(missing_docs)] +use std::borrow::Cow; + use async_trait::async_trait; mod file; @@ -122,7 +124,7 @@ pub mod settings { /// Error signalled from the database. #[derive(Debug)] pub struct StorageError { - msg: String, + msg: std::borrow::Cow<'static, str>, source: Option<Box<dyn std::error::Error + Send + Sync>>, kind: ErrorKind, } @@ -137,7 +139,7 @@ impl std::error::Error for StorageError { impl From<serde_json::Error> for StorageError { fn from(err: serde_json::Error) -> Self { Self { - msg: format!("{}", err), + msg: std::borrow::Cow::Owned(format!("{}", err)), source: Some(Box::new(err)), kind: ErrorKind::JsonParsing, } @@ -171,21 +173,33 @@ impl serde::Serialize for StorageError { } impl StorageError { /// Create a new StorageError of an ErrorKind with a message. - fn new(kind: ErrorKind, msg: &str) -> Self { + pub fn new(kind: ErrorKind, msg: String) -> Self { Self { - msg: msg.to_string(), + msg: Cow::Owned(msg), source: None, kind, } } + /// Create a new StorageError of an ErrorKind with a message from + /// a static string. + /// + /// This saves an allocation for a new string and is the preferred + /// way in case the error message doesn't change. + pub fn from_static(kind: ErrorKind, msg: &'static str) -> Self { + Self { + msg: Cow::Borrowed(msg), + source: None, + kind + } + } /// Create a StorageError using another arbitrary Error as a source. - fn with_source( + pub fn with_source( kind: ErrorKind, - msg: &str, + msg: std::borrow::Cow<'static, str>, source: Box<dyn std::error::Error + Send + Sync>, ) -> Self { Self { - msg: msg.to_string(), + msg, source: Some(source), kind, } |