diff --git a/src/bin/shrupl.rs b/src/bin/shrupl.rs index 6e029f0..0b4b775 100644 --- a/src/bin/shrupl.rs +++ b/src/bin/shrupl.rs @@ -86,7 +86,7 @@ fn main() { Err(e) => { Log::handle(&e); - if let shrupl::Error::InvalidParameter(p) = e { + if let Some(p) = e.get_invalid_param() { match p { // Error 404 (File not found) shrupl::Parameter::FileID(fid) => { diff --git a/src/error.rs b/src/error.rs index e674931..0f1d104 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,7 +5,7 @@ use crate::sharry; #[derive(Debug, thiserror::Error)] pub enum Parameter { #[error("given URI {0:?}")] - Uri(String), + Uri(sharry::Uri), #[error("given Alias ID {0:?}")] AliasID(sharry::AliasID), @@ -17,6 +17,27 @@ pub enum Parameter { FileID(sharry::FileID), } +// a helper to generate all the `From for Parameter` impls +macro_rules! impl_param_from { + // $typ: the source type; $var: the enum‐variant name + ( $( $typ:path => $var:ident ),* $(,)? ) => { + $( + impl From<$typ> for Parameter { + fn from(value: $typ) -> Self { + Self::$var(value) + } + } + )* + }; +} + +impl_param_from! { + sharry::Uri => Uri, + sharry::AliasID => AliasID, + sharry::ShareID => ShareID, + sharry::FileID => FileID, +} + impl Parameter { fn is_fatal(&self) -> bool { matches!(self, Self::Uri(_) | Self::AliasID(_)) @@ -41,6 +62,35 @@ pub enum Error { Unknown(String), } +// a helper to generate all the `From for Error` impls +macro_rules! impl_error_from { + // $typ: the source type; $var: the enum‐variant name + ( $( $typ:path => $var:ident ),* $(,)? ) => { + $( + // // implement for values + // impl From<$typ> for Error { + // fn from(value: $typ) -> Self { + // Self::InvalidParameter(value.into()) + // } + // } + + // implement for references + impl From<&$typ> for Error { + fn from(value: &$typ) -> Self { + Self::InvalidParameter(value.clone().into()) + } + } + )* + }; +} + +impl_error_from! { + sharry::Uri => Uri, + sharry::AliasID => AliasID, + sharry::ShareID => ShareID, + sharry::FileID => FileID, +} + #[allow(clippy::needless_pass_by_value)] fn into_string(val: impl ToString) -> String { val.to_string() @@ -71,6 +121,14 @@ impl Error { } } + pub fn get_invalid_param(&self) -> Option<&Parameter> { + if let Self::InvalidParameter(p) = self { + Some(p) + } else { + None + } + } + #[must_use] pub fn is_fatal(&self) -> bool { match self { diff --git a/src/impl_ureq.rs b/src/impl_ureq.rs index a0b1cc5..c4bacee 100644 --- a/src/impl_ureq.rs +++ b/src/impl_ureq.rs @@ -15,17 +15,17 @@ fn find_cause( ureq::Error::StatusCode(403) => { trace!("HTTP Error 403: Alias not found!"); - crate::Error::InvalidParameter(crate::Parameter::AliasID(alias_id.to_owned())) + alias_id.into() } ureq::Error::StatusCode(404) => { trace!("HTTP Error 404: Share and/or file may have been deleted!"); if let Some(file_id) = file_id { - crate::Error::InvalidParameter(crate::Parameter::FileID(file_id.to_owned())) + file_id.into() } else if let Some(share_id) = share_id { - crate::Error::InvalidParameter(crate::Parameter::ShareID(share_id.to_owned())) + share_id.into() } else { - crate::Error::InvalidParameter(crate::Parameter::Uri(uri.to_string())) + uri.into() } } ureq::Error::Io(error) => { @@ -33,7 +33,7 @@ fn find_cause( if let Some(msg) = error.get_ref().map(ToString::to_string) { if msg.starts_with("failed to lookup address information") { - crate::Error::InvalidParameter(crate::Parameter::Uri(uri.to_string())) + uri.into() } else { error.into() } diff --git a/src/sharry/uri.rs b/src/sharry/uri.rs index ea3e647..793a133 100644 --- a/src/sharry/uri.rs +++ b/src/sharry/uri.rs @@ -3,7 +3,7 @@ use std::fmt; use log::trace; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Uri(String); impl fmt::Display for Uri {