use std::fmt;
use std::fmt::Debug;
use backtrace::Backtrace as _Backtrace;
#[macro_export]
macro_rules! fallible {
($variant:ident) => (Err(err!($variant)));
($variant:ident, $($inner:expr),+) => (Err(err!($variant, $($inner),+)));
}
#[macro_export]
macro_rules! err {
($variant:ident) => (crate::error::Error {
variant: crate::error::ErrorVariant::$variant,
message: None,
backtrace: backtrace::Backtrace::new_unresolved()
});
($variant:ident, $message:expr) => (crate::error::Error {
variant: crate::error::ErrorVariant::$variant,
message: Some($message.to_string()), backtrace: backtrace::Backtrace::new_unresolved()
});
($variant:ident, $template:expr, $($args:expr),+) =>
(err!($variant, format!($template, $($args,)+)));
}
#[derive(thiserror::Error, Debug)]
pub struct Error {
pub variant: ErrorVariant,
pub message: Option<String>,
pub backtrace: _Backtrace
}
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
self.variant == other.variant && self.message == other.message
}
}
#[derive(PartialEq, thiserror::Error, Debug)]
#[non_exhaustive]
pub enum ErrorVariant {
#[error("FFI")]
FFI,
#[error("TypeParse")]
TypeParse,
#[error("FailedFunction")]
FailedFunction,
#[error("FailedRelation")]
FailedRelation,
#[error("RelationDebug")]
RelationDebug,
#[error("FailedCast")]
FailedCast,
#[error("DomainMismatch")]
DomainMismatch,
#[error("MetricMismatch")]
MetricMismatch,
#[error("MeasureMismatch")]
MeasureMismatch,
#[error("MakeDomain")]
MakeDomain,
#[error("MakeTransformation")]
MakeTransformation,
#[error("MakeMeasurement")]
MakeMeasurement,
#[error("InvalidDistance")]
InvalidDistance,
#[error("NotImplemented")]
NotImplemented,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.variant)
}
}
#[cfg(all(test, feature="test-plot"))]
impl From<String> for Error {
fn from(v: String) -> Self {
err!(FailedFunction, v)
}
}
impl From<ErrorVariant> for Error {
fn from(variant: ErrorVariant) -> Self {
Self { variant, message: None, backtrace: _Backtrace::new() }
}
}
impl<T> From<Error> for Result<T, Error> {
fn from(e: Error) -> Self {
Err(e)
}
}
pub type Fallible<T> = Result<T, Error>;
pub trait ExplainUnwrap {
type Inner;
fn unwrap_assert(self, explanation: &'static str) -> Self::Inner;
fn unwrap_test(self) -> Self::Inner;
}
impl<T> ExplainUnwrap for Option<T> {
type Inner = T;
fn unwrap_assert(self, _explanation: &'static str) -> T {
self.unwrap()
}
fn unwrap_test(self) -> T {
self.unwrap()
}
}
impl<T, E: Debug> ExplainUnwrap for Result<T, E> {
type Inner = T;
fn unwrap_assert(self, _explanation: &'static str) -> T {
self.unwrap()
}
fn unwrap_test(self) -> T {
self.unwrap()
}
}