improved error handling

This commit is contained in:
Jörn-Michael Miehe 2025-07-01 15:20:07 +00:00
parent bc4c15d17c
commit 0d68d139d5
4 changed files with 66 additions and 8 deletions

View file

@ -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) => {

View file

@ -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<T> for Parameter` impls
macro_rules! impl_param_from {
// $typ: the source type; $var: the enumvariant 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<T> for Error` impls
macro_rules! impl_error_from {
// $typ: the source type; $var: the enumvariant 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 {

View file

@ -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()
}

View file

@ -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 {