rust-lang-deprecated / error-chain

Error boilerplate for Rust
Apache License 2.0
730 stars 111 forks source link

Single-line version of DisplayChain #236

Open dbrgn opened 7 years ago

dbrgn commented 7 years ago

Is there a way to get a string representation of the error chain without newlines?

For example, this chain:

Error: decoding error
Caused by: cannot decode message payload
Caused by: could not decrypt bytes

...could be written into a string without newlines like this:

Error: decoding error (caused by: cannot decode message payload (caused by: could not decrypt bytes))

The version with newlines is much easier to read when printing it to the terminal, but there are some use cases where a single line is required without newlines.

A workaround could be:

e.display_chain().to_string().trim().replace("\n", " -> "))

...but that's a bit ugly.

Yamakaky commented 7 years ago

I think you have to iter on the error chain and do the formating yourself

kaimaera commented 3 years ago

Or derive a custom trait from ChainedError, for instance:

use std::fmt;

#[macro_use]
extern crate error_chain;
use error_chain::ChainedError;

fn main() {
    match make_second_error() {
        Err(e) => {
            eprintln!("Single Line\n{}\n", e.string_chain());
            eprintln!("Multiple Line\n{}", e.display_chain());
        }
        Ok(()) => (),
    }
}
fn make_second_error() -> Result<()> {
    make_error().chain_err(|| "doing something else")?;
    Ok(())
}

fn make_error() -> Result<()> {
    make_io_error().chain_err(|| "doing something")?;
    Ok(())
}

fn make_io_error() -> Result<()> {
    return Err(::std::io::Error::new(::std::io::ErrorKind::Other, "some io error").into());
}

error_chain! {
    foreign_links {
        Io(::std::io::Error);
    }
}

trait ChainedString: ChainedError + Send + 'static {
    fn string_chain<'a>(&'a self) -> DisplayString<'a, Self>;
}

impl ChainedString for Error {
    fn string_chain<'a>(&'a self) -> DisplayString<'a, Self> {
        DisplayString(self)
    }
}

struct DisplayString<'a, T: ChainedError + 'a + ?Sized>(&'a T);

impl<'a, T: ChainedError + 'a + ?Sized> fmt::Display for DisplayString<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)?;
        for err in self.0.iter().skip(1) {
            write!(f, ": {}", err)?;
        }
        Ok(())
    }
}

which produces:

Single Line
doing something else: doing something: some io error

Multiple Line
Error: doing something else
Caused by: doing something
Caused by: some io error