use std::error::Error as StdError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NeverErr {}
impl std::fmt::Display for NeverErr {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self {} }
}
impl std::error::Error for NeverErr {}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum FatalError<E> {
Error(E),
Fatal(E),
}
impl<E> FatalError<E> {
pub fn is_error(&self) -> bool { matches!(self, FatalError::Error(_)) }
pub fn is_fatal(&self) -> bool { matches!(self, FatalError::Fatal(_)) }
pub fn into_inner(self) -> E {
match self {
FatalError::Error(x) => x,
FatalError::Fatal(x) => x,
}
}
pub fn map<E2, F>(self, f: F) -> FatalError<E2>
where
F: FnOnce(E) -> E2,
{
match self {
FatalError::Error(x) => FatalError::Error(f(x)),
FatalError::Fatal(x) => FatalError::Fatal(f(x)),
}
}
pub fn escalate(self) -> Self { FatalError::Fatal(self.into_inner()) }
pub fn deescalate(self) -> Self { FatalError::Error(self.into_inner()) }
pub fn fatality(self) -> Result<E, Self> {
match self {
FatalError::Error(x) => Ok(x),
x @ FatalError::Fatal(_) => Err(x),
}
}
pub fn recover(self) -> Result<E, E> {
match self {
FatalError::Error(x) => Ok(x),
FatalError::Fatal(x) => Err(x),
}
}
pub fn map_error<T, F>(self, f: F) -> Result<T, Self>
where
F: FnOnce(E) -> Result<T, Self>,
{
match self {
FatalError::Error(x) => f(x),
x @ FatalError::Fatal(_) => Err(x),
}
}
pub fn map_fatal<T, F>(self, f: F) -> Result<T, Self>
where
F: FnOnce(E) -> Result<T, Self>,
{
match self {
x @ FatalError::Error(_) => Err(x),
FatalError::Fatal(x) => f(x),
}
}
pub fn then<T, F>(self, f: F) -> Result<T, Self>
where
F: FnOnce(E) -> Result<T, Self>,
{
f(self.into_inner())
}
}
impl<E: std::fmt::Display> std::fmt::Display for FatalError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FatalError::Error(x) => write!(f, "Error: {x}"),
FatalError::Fatal(x) => write!(f, "Fatal Error: {x}"),
}
}
}
impl<E: StdError + 'static> StdError for FatalError<E> {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
FatalError::Error(x) | FatalError::Fatal(x) => x.source(),
}
}
}