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
use eyre::Report;
use serde_json::Value;
use crate::Handler;
pub trait Section {
type Output;
fn section(self, key: impl ToString, value: impl Into<Value>) -> Self::Output;
fn get_section(&self, key: impl AsRef<str>) -> Option<&Value>;
fn get_section_str(&self, key: impl AsRef<str>) -> Option<&str>;
}
impl Section for Report {
type Output = Self;
fn section(mut self, key: impl ToString, value: impl Into<Value>) -> Self::Output {
if let Some(handler) = self.handler_mut().downcast_mut::<Handler>() {
handler.sections.insert(key.to_string(), value.into());
}
self
}
fn get_section(&self, key: impl AsRef<str>) -> Option<&Value> {
self.handler()
.downcast_ref::<Handler>()
.and_then(|h| h.sections.get(key.as_ref()))
}
fn get_section_str(&self, key: impl AsRef<str>) -> Option<&str> {
self.get_section(key).and_then(|v| v.as_str())
}
}
impl<T, E> Section for Result<T, E>
where
E: Into<Report>,
{
type Output = Result<T, Report>;
fn section(self, key: impl ToString, value: impl Into<Value>) -> Self::Output {
self.map_err(Into::into).map_err(|e| e.section(key, value))
}
fn get_section(&self, _key: impl AsRef<str>) -> Option<&Value> {
None
}
fn get_section_str(&self, _key: impl AsRef<str>) -> Option<&str> {
None
}
}
#[cfg(test)]
mod tests {
use eyre::eyre;
use serde_json::Value;
use crate::ext::Section;
use crate::tests::{hack_install, AdhocError};
use crate::Hook;
#[test]
fn attach_to_report() {
let _guard = hack_install(Hook::simple());
let report = eyre!(AdhocError::new("boom"))
.section("a", true)
.section("b", "key b");
assert_eq!(report.get_section("a").unwrap(), &Value::Bool(true));
assert_eq!(
report.get_section("b").unwrap(),
&Value::String("key b".into())
);
assert!(report.get_section_str("a").is_none());
assert_eq!(report.get_section_str("b").unwrap(), "key b");
}
}