shrupl/src/error.rs

156 lines
3.6 KiB
Rust
Raw Normal View History

use std::fmt;
2025-06-25 23:15:33 +00:00
use crate::sharry;
#[derive(Debug, thiserror::Error)]
pub enum Parameter {
#[error("given URI {0:?}")]
2025-07-01 15:20:07 +00:00
Uri(sharry::Uri),
#[error("given Alias ID {0:?}")]
2025-06-27 01:47:38 +00:00
AliasID(sharry::AliasID),
#[error("stored Share ID {0:?}")]
2025-06-27 01:47:38 +00:00
ShareID(sharry::ShareID),
2025-06-25 23:15:33 +00:00
#[error("stored {0:?}")]
FileID(sharry::FileID),
}
2025-07-01 15:20:07 +00:00
// 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(_))
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
StdIo(#[from] std::io::Error),
2025-06-26 09:56:29 +00:00
#[error("Response error: {0}")]
Response(String),
#[error("Invalid {0}")]
InvalidParameter(Parameter),
2025-06-26 09:56:29 +00:00
#[error("Mismatch, expected {expected:?} but got {actual:?}")]
Mismatch { expected: String, actual: String },
#[error("Unknown error: {0}")]
Unknown(String),
}
2025-07-01 15:20:07 +00:00
// a helper to generate all the `From<T> for Error` impls
macro_rules! impl_error_from {
// $typ: the source type
( $( $typ:path ),* $(,)? ) => {
2025-07-01 15:20:07 +00:00
$(
// // 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,
sharry::AliasID,
sharry::ShareID,
sharry::FileID,
2025-07-01 15:20:07 +00:00
}
#[allow(clippy::needless_pass_by_value)]
fn into_string(val: impl ToString) -> String {
val.to_string()
}
impl Error {
pub fn res_status_check<T>(actual: T, expected: T) -> Result<()>
where
T: PartialEq + fmt::Display + Copy,
{
if actual == expected {
Ok(())
} else {
Err(Self::Response(format!(
"unexpected status: {actual} (expected {expected})"
)))
}
}
pub fn response(e: impl ToString) -> Self {
Self::Response(into_string(e))
}
2025-06-26 09:56:29 +00:00
pub fn mismatch(expected: impl ToString, actual: impl ToString) -> Self {
Self::Mismatch {
expected: into_string(expected),
actual: into_string(actual),
}
}
pub fn is_mismatch<E, A>(&self, has_expected: E, has_actual: A) -> bool
where
String: PartialEq<E> + PartialEq<A>,
{
matches!(
self,
Self::Mismatch { expected, actual }
if *expected == has_expected
&& *actual == has_actual
)
}
2025-07-01 15:24:26 +00:00
#[must_use]
2025-07-01 15:20:07 +00:00
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 {
Self::InvalidParameter(p) => p.is_fatal(),
2025-06-26 10:13:23 +00:00
Self::Mismatch { .. } | Self::Unknown(_) => true,
_ => false,
}
}
}
pub type Result<T> = std::result::Result<T, Error>;