142 lines
3.3 KiB
Rust
142 lines
3.3 KiB
Rust
use std::fmt;
|
||
|
||
use crate::sharry;
|
||
|
||
#[derive(Debug, thiserror::Error)]
|
||
pub enum Parameter {
|
||
#[error("given URI {0:?}")]
|
||
Uri(sharry::Uri),
|
||
|
||
#[error("given Alias ID {0:?}")]
|
||
AliasID(sharry::AliasID),
|
||
|
||
#[error("stored Share ID {0:?}")]
|
||
ShareID(sharry::ShareID),
|
||
|
||
#[error("stored {0:?}")]
|
||
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 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(_))
|
||
}
|
||
}
|
||
|
||
#[derive(Debug, thiserror::Error)]
|
||
pub enum Error {
|
||
#[error(transparent)]
|
||
StdIo(#[from] std::io::Error),
|
||
|
||
#[error("Response error: {0}")]
|
||
Response(String),
|
||
|
||
#[error("Invalid {0}")]
|
||
InvalidParameter(Parameter),
|
||
|
||
#[error("Mismatch, expected {expected:?} but got {actual:?}")]
|
||
Mismatch { expected: String, actual: String },
|
||
|
||
#[error("Unknown error: {0}")]
|
||
Unknown(String),
|
||
}
|
||
|
||
// a helper to generate all the `From<T> for Error` impls
|
||
macro_rules! impl_error_from {
|
||
// $typ: the source type
|
||
( $( $typ:path ),* $(,)? ) => {
|
||
$(
|
||
// // 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,
|
||
}
|
||
|
||
#[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))
|
||
}
|
||
|
||
pub fn mismatch(expected: impl ToString, actual: impl ToString) -> Self {
|
||
Self::Mismatch {
|
||
expected: into_string(expected),
|
||
actual: into_string(actual),
|
||
}
|
||
}
|
||
|
||
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(),
|
||
Self::Mismatch { .. } | Self::Unknown(_) => true,
|
||
_ => false,
|
||
}
|
||
}
|
||
}
|
||
|
||
pub type Result<T> = std::result::Result<T, Error>;
|