use thiserror::Error;
use crate::manager::FileMode;
use std::convert::Infallible;
use std::io;
#[derive(Debug, Error)]
pub enum Error<FE> {
#[error("format error: {0}")]
Format(FE),
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
Other(#[from] OtherError)
}
impl From<Error<io::Error>> for io::Error {
fn from(err: Error<io::Error>) -> Self {
match err {
Error::Format(err) | Error::Io(err) => err,
Error::Other(err) => io::Error::other(err)
}
}
}
#[derive(Debug, Error)]
pub enum OrUserError<T, U> {
#[error(transparent)]
Base(T),
#[error("user error: {0}")]
User(U)
}
impl<T, U> OrUserError<T, U> {
pub fn convert_with<E, F>(self, f: F) -> E
where T: Into<E>, F: FnOnce(U) -> E {
match self {
Self::Base(err) => err.into(),
Self::User(err) => f(err)
}
}
pub fn convert<E>(self) -> E
where T: Into<E>, U: Into<E> {
self.convert_with(U::into)
}
}
impl<T> OrUserError<T, Infallible> {
pub fn into_base(self) -> T {
match self {
Self::Base(err) => err,
Self::User(i) => match i {}
}
}
}
impl<U> OrUserError<Infallible, U> {
pub fn into_user(self) -> U {
match self {
Self::User(err) => err,
Self::Base(i) => match i {}
}
}
}
impl<T, U> From<T> for OrUserError<T, U> {
fn from(err: T) -> Self {
OrUserError::Base(err)
}
}
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum OtherError {
#[error("file mode {0:?} is incompatible with this operation")]
IncompatibleFileMode(FileMode)
}