use std::borrow::Cow;
use serde::{Deserialize, Serialize};
mod kind;
pub use kind::ErrorKind;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum Error {
InvalidField {
field: String,
have: String,
expected: String,
},
Io {
kind: ErrorKind,
message: String,
},
}
impl Error {
pub fn invalid_field<'f, 'h, 'e, F, H, E>(field: F, have: H, expected: E) -> Self
where
F: Into<Cow<'f, str>>,
H: Into<Cow<'h, str>>,
E: Into<Cow<'e, str>>,
{
Self::InvalidField {
field: F::into(field).into(),
have: H::into(have).into(),
expected: E::into(expected).into(),
}
}
pub fn std_io(err: std::io::Error) -> Self {
Self::Io {
kind: ErrorKind::from_io(err.kind()),
message: format!("{err}"),
}
}
pub fn io<'m, M: Into<Cow<'m, str>>>(kind: ErrorKind, message: M) -> Self {
Self::Io {
kind,
message: M::into(message).into(),
}
}
pub fn io_other<'m, M: Into<Cow<'m, str>>>(message: M) -> Self {
Self::Io {
kind: ErrorKind::Other,
message: M::into(message).into(),
}
}
pub fn io_filename<'m, M: Into<Cow<'m, str>>>(message: M) -> Self {
Self::Io {
kind: ErrorKind::InvalidFilename,
message: M::into(message).into(),
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidField {
field,
have,
expected,
} => write!(f, "invalid {field}, have: {have}, expected: {expected}"),
Self::Io { kind, message } => write!(f, "I/O error, kind: {kind}, message: {message}"),
}
}
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Self::std_io(err)
}
}
impl From<Error> for std::io::Error {
fn from(err: Error) -> Self {
match err {
Error::Io { kind, message } => Self::new(kind.as_io(), message),
err => Self::other(err),
}
}
}
impl From<uuid::Error> for Error {
fn from(err: uuid::Error) -> Self {
Self::std_io(std::io::Error::other(err))
}
}
impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Self {
Self::std_io(std::io::Error::other(err))
}
}
impl From<serde_json::Error> for Error {
fn from(err: serde_json::Error) -> Self {
Self::std_io(std::io::Error::other(err))
}
}
impl From<std::str::Utf8Error> for Error {
fn from(err: std::str::Utf8Error) -> Self {
Self::std_io(std::io::Error::other(err))
}
}
impl From<std::num::ParseIntError> for Error {
fn from(err: std::num::ParseIntError) -> Self {
Self::io(ErrorKind::Other, format!("{err}"))
}
}
impl From<reqwest::header::ToStrError> for Error {
fn from(err: reqwest::header::ToStrError) -> Self {
Self::io(ErrorKind::Other, format!("{err}"))
}
}
#[cfg(target_family = "wasm")]
impl From<Error> for wasm_bindgen::JsValue {
fn from(err: Error) -> Self {
serde_wasm_bindgen::to_value(&err).unwrap_or_default()
}
}
impl serde::de::Error for Error {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
Self::io(ErrorKind::Other, format!("{msg}"))
}
}
impl std::error::Error for Error {}