1use std::borrow::Cow;
2
3use crate::ErrorChain;
4
5pub trait ResultChain<I, T, E, D> {
6 fn about(self, desc: D) -> Result<T, ErrorChain<I>>
7 where
8 Self: Sized,
9 E: Into<I>,
10 D: Into<Cow<'static, str>>;
11 fn about_else(self, f: impl FnOnce() -> D) -> Result<T, ErrorChain<I>>
12 where
13 Self: Sized,
14 E: Into<I>,
15 D: Into<Cow<'static, str>>;
16}
17
18impl<I, T, E> ResultChain<I, T, E, &'static str> for std::result::Result<T, E> {
19 fn about(self, desc: &'static str) -> Result<T, ErrorChain<I>>
20 where
21 Self: Sized,
22 E: Into<I>,
23 {
24 self.map_err(|e| ErrorChain {
25 source: e.into(),
26 context: vec![desc.into()],
27 })
28 }
29 fn about_else(self, f: impl FnOnce() -> &'static str) -> Result<T, ErrorChain<I>>
30 where
31 Self: Sized,
32 E: Into<I>,
33 {
34 self.map_err(|e| ErrorChain {
35 source: e.into(),
36 context: vec![f().into()],
37 })
38 }
39}
40
41impl<I, T, E> ResultChain<I, T, E, String> for std::result::Result<T, E> {
42 fn about(self, desc: String) -> Result<T, ErrorChain<I>>
43 where
44 Self: Sized,
45 E: Into<I>,
46 {
47 self.map_err(|e| ErrorChain {
48 source: e.into(),
49 context: vec![desc.into()],
50 })
51 }
52 fn about_else(self, f: impl FnOnce() -> String) -> Result<T, ErrorChain<I>>
53 where
54 Self: Sized,
55 E: Into<I>,
56 {
57 self.map_err(|e| ErrorChain {
58 source: e.into(),
59 context: vec![f().into()],
60 })
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::ResultChain;
67 use crate as resplus;
68 use crate::tests::{about, about_else};
69 use test_util::*;
70
71 #[test]
72 fn about() {
73 assert_result!(about!(f0()), "source: Error\n source");
74 assert_result!(about!(f1(1)), "source: Error\n source");
75 assert_result!(about!(f2(1, 1)), "source: Error\n source");
76 }
77
78 #[test]
79 fn about_else() {
80 assert_result!(about_else!(f0()), "source: Error\n source");
81 assert_result!(about_else!(f1(1)), "source: Error\n source");
82 assert_result!(about_else!(f2(1, 1)), "source: Error\n source");
83 }
84}