use std::{self, str::FromStr};
use trackable;
use trackable::error::ErrorKindExt;
#[derive(Debug, Clone, TrackableError)]
pub struct Error(trackable::error::TrackableError<ErrorKind>);
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
if let Some(e) = e.get_ref().and_then(|e| e.downcast_ref::<Error>()).cloned() {
e
} else if e.kind() == std::io::ErrorKind::InvalidInput {
ErrorKind::InvalidInput.cause(e).into()
} else {
ErrorKind::Other.cause(e).into()
}
}
}
impl From<Error> for std::io::Error {
fn from(e: Error) -> Self {
if *e.kind() == ErrorKind::InvalidInput {
std::io::Error::new(std::io::ErrorKind::InvalidInput, e)
} else {
std::io::Error::new(std::io::ErrorKind::Other, e)
}
}
}
impl<T> From<std::sync::PoisonError<T>> for Error {
fn from(e: std::sync::PoisonError<T>) -> Self {
ErrorKind::Other.cause(e.to_string()).into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ErrorKind {
DeviceBusy,
DeviceTerminated,
StorageFull,
StorageCorrupted,
InvalidInput,
InconsistentState,
RequestDropped,
RequestRefused,
Other,
}
impl trackable::error::ErrorKind for ErrorKind {}
impl std::fmt::Display for ErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ErrorKind::StorageFull => write!(f, "StorageFull"),
ErrorKind::StorageCorrupted => write!(f, "StorageCorrupted"),
ErrorKind::DeviceBusy => write!(f, "DeviceBusy"),
ErrorKind::DeviceTerminated => write!(f, "DeviceTerminated"),
ErrorKind::InvalidInput => write!(f, "InvalidInput"),
ErrorKind::InconsistentState => write!(f, "InconsistentState"),
ErrorKind::RequestDropped => write!(f, "RequestDropped"),
ErrorKind::RequestRefused => write!(f, "RequestRefused"),
ErrorKind::Other => write!(f, "Other"),
}
}
}
impl FromStr for ErrorKind {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let kind = match s {
"StorageFull" => ErrorKind::StorageFull,
"StorageCorrupted" => ErrorKind::StorageCorrupted,
"DeviceBusy" => ErrorKind::DeviceBusy,
"DeviceTerminated" => ErrorKind::DeviceTerminated,
"InvalidInput" => ErrorKind::InvalidInput,
"RequestDropped" => ErrorKind::RequestDropped,
"RequestRefused" => ErrorKind::RequestRefused,
"InconsistentState" => ErrorKind::InconsistentState,
"Other" => ErrorKind::Other,
_ => return Err(()),
};
Ok(kind)
}
}