use std::fmt::Display;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Error {
Abort,
InvalidData(String),
InvalidInput(String),
IO(String),
}
impl std::error::Error for Error {}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Error::Abort => write!(f, "operation aborted"),
Error::InvalidData(msg) => write!(f, "invalid data: {msg}"),
Error::InvalidInput(msg) => write!(f, "invalid input: {msg}"),
Error::IO(msg) => write!(f, "io error: {msg}"),
}
}
}
impl Error {
pub fn is_deterministic(&self) -> bool {
match self {
Error::Abort => false,
Error::InvalidData(_) => false,
Error::InvalidInput(_) => true,
Error::IO(_) => false,
}
}
}
#[macro_export]
macro_rules! errdata {
($($args:tt)*) => { $crate::error::Error::InvalidData(format!($($args)*)).into() };
}
#[macro_export]
macro_rules! errinput {
($($args:tt)*) => { $crate::error::Error::InvalidInput(format!($($args)*)).into() };
}
pub type Result<T> = std::result::Result<T, Error>;
impl<T> From<Error> for Result<T> {
fn from(error: Error) -> Self {
Err(error)
}
}
impl From<bincode::error::DecodeError> for Error {
fn from(err: bincode::error::DecodeError) -> Self {
Error::InvalidData(err.to_string())
}
}
impl From<bincode::error::EncodeError> for Error {
fn from(err: bincode::error::EncodeError) -> Self {
Error::InvalidData(err.to_string())
}
}
impl From<crossbeam::channel::RecvError> for Error {
fn from(err: crossbeam::channel::RecvError) -> Self {
Error::IO(err.to_string())
}
}
impl<T> From<crossbeam::channel::SendError<T>> for Error {
fn from(err: crossbeam::channel::SendError<T>) -> Self {
Error::IO(err.to_string())
}
}
impl From<crossbeam::channel::TryRecvError> for Error {
fn from(err: crossbeam::channel::TryRecvError) -> Self {
Error::IO(err.to_string())
}
}
impl<T> From<crossbeam::channel::TrySendError<T>> for Error {
fn from(err: crossbeam::channel::TrySendError<T>) -> Self {
Error::IO(err.to_string())
}
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Error::IO(err.to_string())
}
}
impl From<std::array::TryFromSliceError> for Error {
fn from(err: std::array::TryFromSliceError) -> Self {
Error::InvalidData(err.to_string())
}
}
impl From<std::string::FromUtf8Error> for Error {
fn from(err: std::string::FromUtf8Error) -> Self {
Error::InvalidData(err.to_string())
}
}
impl From<std::num::TryFromIntError> for Error {
fn from(err: std::num::TryFromIntError) -> Self {
Error::InvalidData(err.to_string())
}
}
impl<T> From<std::sync::PoisonError<T>> for Error {
fn from(err: std::sync::PoisonError<T>) -> Self {
panic!("{err}")
}
}