quixutils/
errors.rs

1use std::io::Result;
2
3macro_rules! write_error_chain_checked {
4    ($e: expr, $to: expr) => {
5        if let Err(e) = crate::errors::write_error_chain($e, $to) {
6            panic!("failed to write: {:?}", e);
7        }
8    };
9}
10
11pub fn eprint_on_error<T, E>(result: &std::result::Result<T, E>)
12where
13    E: std::error::Error,
14{
15    if let Err(err) = result {
16        eprint_error_chain(err);
17    }
18}
19
20pub fn log_on_error<T, E>(result: &std::result::Result<T, E>)
21where
22    E: std::error::Error,
23{
24    if let Err(err) = result {
25        log_error_chain(err);
26    }
27}
28
29pub fn eprint_error_chain(e: &dyn std::error::Error) {
30    let mut out = std::io::stderr();
31    write_error_chain_checked!(e, &mut out);
32}
33
34pub fn log_error_chain(e: &dyn std::error::Error) {
35    let mut err_bytes = Vec::with_capacity(16);
36    write_error_chain_checked!(e, &mut err_bytes);
37    // We trim exactly one new line if present
38    // since log::error will output another newline
39    let log_message = if err_bytes.ends_with(&['\n' as u8]) {
40        &err_bytes[0..(err_bytes.len() - 1)]
41    } else {
42        &err_bytes[..]
43    };
44    log::error!("{}", String::from_utf8_lossy(log_message));
45}
46
47pub fn write_error_chain<W: std::io::Write>(e: &dyn std::error::Error, to: &mut W) -> Result<()> {
48    write_error_chain_with_opts(e, None, Some("Caused By: "), to)
49}
50
51pub fn write_error_chain_with_opts<W: std::io::Write>(
52    e: &dyn std::error::Error,
53    err_prefix: Option<&str>,
54    err_cause_prefix: Option<&str>,
55    to: &mut W,
56) -> Result<()> {
57    write_error(e, err_prefix, to)?;
58    let mut cause = e.source();
59    while let Some(e) = cause {
60        write_error(e, err_cause_prefix, to)?;
61        cause = e.source();
62    }
63    Ok(())
64}
65
66pub fn write_error<W: std::io::Write>(
67    e: &dyn std::error::Error,
68    err_prefix: Option<&str>,
69    to: &mut W,
70) -> Result<()> {
71    let err_prefix = err_prefix.unwrap_or("Error: ");
72    writeln!(to, "{}{}", err_prefix, e)?;
73
74    #[cfg(feature = "unstable")]
75    {
76        if let Some(b) = e.backtrace() {
77            writeln!(to, "{}", b)?;
78        }
79    }
80
81    Ok(())
82}