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 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}