Since error-chain is no longer maintained, I've now switched to my own error module but I notice that it is slower than error-chain and I don't know why.
It is in the source for retest's xerror.rs
file which I've also copied below since its only 100 lines.
Is there any way to make it faster (without making it too complicated!)?
use std::error::Error;
use std::fmt;
use std::io;
use std::num;
pub type XResult<T> = Result<T, XError>;
pub fn xerror<T>(message: &str) -> XResult<T> {
Err(XError::new(&message))
}
#[macro_export]
macro_rules! xerr {
($x:expr) => {{return xerror($x);}};
($x:expr, $($y:expr),+) => {{return xerror(&format!($x, $($y),+));}};
}
#[derive(Debug)]
pub enum XError {
Image(image::ImageError),
Io(::std::io::Error),
Json(json::Error),
Log(log::SetLoggerError),
ParseFloat(::std::num::ParseFloatError),
ParseInt(::std::num::ParseIntError),
Rayon(rayon::ThreadPoolBuildError),
Retest(String),
}
impl Error for XError {}
impl XError {
pub fn new(message: &str) -> XError {
XError::Retest(message.to_string())
}
}
impl fmt::Display for XError {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
match *self {
XError::Image(ref err) => write!(out, "Image error: {}", err),
XError::Io(ref err) => write!(out, "File error: {}", err),
XError::Json(ref err) => write!(out, "JSON error: {}", err),
XError::Log(ref err) => {
write!(out, "Failed to set logger: {}", err)
}
XError::ParseFloat(ref err) => {
write!(out, "Failed to read decimal number: {}", err)
}
XError::ParseInt(ref err) => {
write!(out, "Failed to read whole number: {}", err)
}
XError::Rayon(ref err) => {
write!(out, "Failed to create thread pool: {}", err)
}
XError::Retest(ref err) => write!(out, "{}", err),
}
}
}
impl From<image::ImageError> for XError {
fn from(err: image::ImageError) -> XError {
XError::Image(err)
}
}
impl From<io::Error> for XError {
fn from(err: io::Error) -> XError {
XError::Io(err)
}
}
impl From<json::Error> for XError {
fn from(err: json::Error) -> XError {
XError::Json(err)
}
}
impl From<log::SetLoggerError> for XError {
fn from(err: log::SetLoggerError) -> XError {
XError::Log(err)
}
}
impl From<num::ParseFloatError> for XError {
fn from(err: num::ParseFloatError) -> XError {
XError::ParseFloat(err)
}
}
impl From<num::ParseIntError> for XError {
fn from(err: num::ParseIntError) -> XError {
XError::ParseInt(err)
}
}
impl From<rayon::ThreadPoolBuildError> for XError {
fn from(err: rayon::ThreadPoolBuildError) -> XError {
XError::Rayon(err)
}
}
I have another version of this that's slower still, but used in a private project so can't be posted. In that the errors in the enum are these:
#[derive(Debug)]
pub enum XError {
Clap(::clap::Error),
PrivateProject(String),
Image(image::ImageError),
Io(::std::io::Error),
ParseFloat(::std::num::ParseFloatError),
ParseInt(::std::num::ParseIntError),
Rayon(rayon::ThreadPoolBuildError),
SerdeJson(serde_json::error::Error),
SharedLib(sharedlib::error::Error),
Utf8(::std::string::FromUtf8Error),
}
For this the fmt() method and the From's have all been implemented in exactly the same way as the retest version.