1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#![cfg_attr(feature="clippy", allow(redundant_closure))]
use std;
error_chain! {
foreign_links {
std::io::Error, IO;
::regex::Error, Regex;
}
errors {
Unexpected(msg: String) {
display("{}", msg)
}
}
}
use backtrace::Symbol;
impl Error {
pub fn is_unexpected(&self) -> bool {
if let ErrorKind::Unexpected(..) = *self.kind() {
true
} else {
false
}
}
pub fn discard_expected(&self) {
if self.is_unexpected() {
self.display_report();
panic!("unexpected error");
}
}
pub fn display_report(&self) {
use log;
if let Some(backtrace) = self.backtrace() {
log::error(format!("{:?}", backtrace));
log::error("");
let mut next_frame_num = 0;
for frame in backtrace.frames() {
for symbol in frame.symbols() {
if let Some(path) = symbol.filename() {
let path_is_good = |x: std::path::Component| if let Some(x) = x.as_os_str().to_str() {
x == "libstd" || x == "libpanic_unwind" || x == "libcore" || x == "errors.rs" ||
x.starts_with("backtrace") || x.starts_with("error-chain")
} else {
false
};
if path.components().any(path_is_good) {
continue;
}
let name = if let Some(name) = symbol.name() {
name.to_string()
} else {
"<no name>".to_string()
};
if next_frame_num == 0 {
log::error("Best of stack backtrace:");
}
log::error(format!("{:>w$}: {}", next_frame_num, name, w = 4));
let line = if let Some(n) = symbol.lineno() {
n.to_string()
} else {
"<no lineno>".to_string()
};
log::error(format!(" at {}:{}", path.display(), line));
log::error("");
next_frame_num += 1;
}
}
}
if next_frame_num > 0 {
log::error("");
}
}
log::error("Error:");
let items: Vec<_> = self.iter().collect();
for (i, err) in items.iter().rev().enumerate() {
log::error(format!("{:>w$}: {}", i, err, w = 4));
}
}
}
pub fn unexpected<S: Into<String>>(text: S) -> ErrorKind {
ErrorKind::Unexpected(text.into())
}
impl<T> ChainErr<T> for Option<T> {
fn chain_err<F, EK>(self, callback: F) -> Result<T>
where F: FnOnce() -> EK,
EK: Into<ErrorKind>
{
match self {
Some(x) => Ok(x),
None => Err(Error::from("None encountered")).chain_err(callback),
}
}
}
pub fn fancy_unwrap<T>(value: Result<T>) -> T {
if let Err(ref err) = value {
err.display_report();
}
value.unwrap()
}