diff options
Diffstat (limited to '')
-rw-r--r-- | filamento/src/error.rs | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/filamento/src/error.rs b/filamento/src/error.rs index 6b7d0ae..bf28160 100644 --- a/filamento/src/error.rs +++ b/filamento/src/error.rs @@ -3,11 +3,12 @@ use std::{num::TryFromIntError, string::FromUtf8Error, sync::Arc}; use base64::DecodeError; use image::ImageError; use jid::JID; -use lampada::error::{ActorError, ConnectionError, ReadError, WriteError}; -use stanza::client::{Stanza, iq::Query}; +use lampada::error::{ActorError, ReadError, WriteError}; +use stanza::client::{iq::Query, Stanza}; use thiserror::Error; pub use lampada::error::CommandError; +pub use lampada::error::ConnectionError; use crate::files::FileStore; @@ -166,11 +167,86 @@ pub enum ResponseError { #[derive(Debug, Error, Clone)] #[error("database error: {0}")] -pub struct DatabaseError(pub Arc<rusqlite::Error>); +pub struct DatabaseError(pub Serializeable<Arc<rusqlite::Error>>); + +pub enum Serializeable<T> { + String(String), + Unserialized(T), +} + +impl<T: std::fmt::Display> std::fmt::Display for Serializeable<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + Serializeable::String(s) => s.fmt(f), + Serializeable::Unserialized(t) => t.fmt(f), + } + } +} + +impl<T: std::fmt::Debug> std::fmt::Debug for Serializeable<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + Serializeable::String(s) => s.fmt(f), + Serializeable::Unserialized(t) => t.fmt(f), + } + } +} + +impl<T: Clone> Clone for Serializeable<T> { + fn clone(&self) -> Self { + match self { + Serializeable::String(s) => Self::String(s.clone()), + Serializeable::Unserialized(t) => Self::Unserialized(t.clone()), + } + } +} + +#[cfg(feature = "serde")] +struct StringVisitor; + +#[cfg(feature = "serde")] +impl<'de> serde::de::Visitor<'de> for StringVisitor { + type Value = String; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a string") + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + Ok(v) + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for DatabaseError { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let string = deserializer.deserialize_string(StringVisitor)?; + Ok(Self(Serializeable::String(string))) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for DatabaseError { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + match &self.0 { + Serializeable::String(s) => serializer.serialize_str(s), + Serializeable::Unserialized(u) => serializer.serialize_str(&u.to_string()), + } + } +} impl From<rusqlite::Error> for DatabaseError { fn from(e: rusqlite::Error) -> Self { - Self(Arc::new(e)) + Self(Serializeable::Unserialized(Arc::new(e))) } } |