type_toppings/
result.rs

1impl<T, E> crate::ResultExt for Result<T, E> {
2    type T = T;
3    type E = E;
4
5    fn expect_with<M, F: FnOnce() -> M>(self, f: F) -> Self::T
6    where
7        Self::E: std::fmt::Debug,
8        M: AsRef<str>,
9    {
10        if let Ok(t) = self {
11            t
12        } else {
13            let msg = f();
14
15            #[allow(clippy::expect_fun_call)]
16            self.expect(msg.as_ref())
17        }
18    }
19
20    fn expect_or_report(self, msg: &str) -> Self::T
21    where
22        Self::E: std::error::Error,
23    {
24        self.map_err(|err| error_reporter::Report::new(err).pretty(true)).expect(msg)
25    }
26
27    fn expect_or_report_with<M, F: FnOnce() -> M>(self, f: F) -> Self::T
28    where
29        Self::E: std::error::Error,
30        M: AsRef<str>,
31    {
32        self.map_err(|err| error_reporter::Report::new(err).pretty(true)).expect_with(f)
33    }
34
35    fn unwrap_or_report(self) -> Self::T
36    where
37        Self::E: std::error::Error,
38    {
39        self.map_err(|err| error_reporter::Report::new(err).pretty(true))
40            .expect("called `unwrap_or_report()` on an `Err` value")
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use crate::ResultExt;
47
48    // A mock error for testing purposes
49    #[derive(Debug, derive_more::Error, derive_more::Display)]
50    #[display("A mock error occurred")]
51    struct MockError(MockSubError);
52
53    // A mock error for testing purposes
54    #[derive(Debug, derive_more::Error, derive_more::Display)]
55    #[display("A mock sub error occurred")]
56    struct MockSubError;
57
58    // Sanity test for how this works with the std lib expect method that just uses the Debug impl to display the error
59    #[test]
60    #[should_panic(expected = "Custom panic: MockError(MockSubError)")]
61    fn expect_err() {
62        let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
63        #[allow(clippy::unnecessary_literal_unwrap)]
64        err_val.expect("Custom panic");
65    }
66
67    /// Tests the [ResultExt::expect_with] method.
68    mod expect_with {
69        use super::*;
70
71        #[test]
72        fn ok() {
73            let ok_val: Result<i32, MockError> = Ok(42);
74            assert_eq!(ok_val.expect_with(|| "Shouldn't see this"), 42);
75        }
76
77        #[test]
78        #[should_panic(expected = "Custom panic: MockError(MockSubError)")]
79        fn err() {
80            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
81            err_val.expect_with(|| "Custom panic");
82        }
83
84        #[test]
85        #[should_panic(expected = "Error in module A: MockError(MockSubError)")]
86        fn err_format() {
87            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
88            let this_module = "module A";
89            err_val.expect_with(|| format!("Error in {}", this_module));
90        }
91
92        #[test]
93        #[should_panic(expected = "Custom panic: MockError(MockSubError)")]
94        fn err_borrowed_string() {
95            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
96            let err_msg = String::from("Custom panic");
97            err_val.expect_with(|| &err_msg);
98        }
99    }
100
101    /// Tests the [ResultExt::expect_or_report] method.
102    mod expect_or_report {
103        use super::*;
104
105        #[test]
106        fn ok() {
107            let ok_val: Result<i32, MockError> = Ok(42);
108            assert_eq!(ok_val.expect_or_report("Shouldn't see this"), 42);
109        }
110
111        #[test]
112        #[should_panic(expected = "Custom report: A mock error occurred\n\nCaused by:\n      A mock sub error occurred")]
113        fn err() {
114            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
115            err_val.expect_or_report("Custom report");
116        }
117
118        #[test]
119        #[should_panic(expected = "Error in module A: A mock error occurred\n\nCaused by:\n      A mock sub error occurred")]
120        fn err_format() {
121            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
122            let this_module = "module A";
123            err_val.expect_or_report(&format!("Error in {}", this_module));
124        }
125    }
126
127    /// Tests the [ResultExt::expect_or_report_with] method.
128    mod expect_or_report_with {
129        use super::*;
130
131        #[test]
132        fn ok() {
133            let ok_val: Result<i32, MockError> = Ok(42);
134            assert_eq!(ok_val.expect_or_report_with(|| "Shouldn't see this"), 42);
135        }
136
137        #[test]
138        #[should_panic(expected = "Dynamic report: A mock error occurred\n\nCaused by:\n      A mock sub error occurred")]
139        fn err() {
140            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
141            err_val.expect_or_report_with(|| "Dynamic report");
142        }
143
144        #[test]
145        #[should_panic(expected = "Error in module A: A mock error occurred\n\nCaused by:\n      A mock sub error occurred")]
146        fn err_format() {
147            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
148            let this_module = "module A";
149            err_val.expect_or_report_with(|| format!("Error in {}", this_module));
150        }
151    }
152
153    /// Tests the [ResultExt::unwrap_or_report] method.
154    mod unwrap_or_report {
155        use super::*;
156
157        #[test]
158        fn ok() {
159            let ok_val: Result<i32, MockError> = Ok(42);
160            assert_eq!(ok_val.unwrap_or_report(), 42);
161        }
162
163        #[test]
164        #[should_panic(
165            expected = "called `unwrap_or_report()` on an `Err` value: A mock error occurred\n\nCaused by:\n      A mock sub error occurred"
166        )]
167        fn err() {
168            let err_val: Result<i32, MockError> = Err(MockError(MockSubError));
169            err_val.unwrap_or_report();
170        }
171    }
172}