chain_assertions/
result.rs

1/// An extension trait to add the assertion_ok methods.
2pub trait AssertOkExt {
3    /// Asserts the [`Result`] is [`Ok`].
4    ///
5    /// # Panics
6    ///
7    /// If it is [`Err`], the method panics.
8    ///
9    /// # Examples
10    ///
11    /// ```rust
12    /// use chain_assertions::prelude::*;
13    ///
14    /// let x: Result<i32, &str> = Ok(21);
15    /// let x = x.assert_ok().map(|v| v * 2);
16    /// assert_eq!(x, Ok(42));
17    /// ```
18    ///
19    /// ```rust,should_panic
20    /// use chain_assertions::prelude::*;
21    ///
22    /// let x: Result<i32, &str> = Err("oops");
23    /// let _ = x.assert_ok().map(|v| v * 2);
24    /// //        ^-- panics here
25    /// ```
26    fn assert_ok(self) -> Self;
27
28    /// Asserts the [`Result`] is [`Ok`] only in debug builds.
29    ///
30    /// # Panics
31    ///
32    /// If it is [`Err`] and `debug_assertions` are enabled, the method panics.
33    /// If `debug_assertions` are disabled, the method is a no-op even if it is [`Err`].
34    ///
35    /// # Examples
36    ///
37    /// ```rust
38    /// use chain_assertions::prelude::*;
39    ///
40    /// let x: Result<i32, &str> = Ok(21);
41    /// let x = x.debug_assert_ok().map(|v| v * 2);
42    /// assert_eq!(x, Ok(42));
43    /// ```
44    fn debug_assert_ok(self) -> Self;
45}
46
47/// An extension trait to add the assertion_err methods.
48pub trait AssertErrExt {
49    /// Asserts the [`Result`] is [`Err`].
50    ///
51    /// # Panics
52    ///
53    /// If it is [`Ok`], the method panics.
54    ///
55    /// # Examples
56    ///
57    /// This sample
58    ///
59    /// ```rust
60    /// use chain_assertions::prelude::*;
61    ///
62    /// let x: Result<&str, i32> = Err(21);
63    /// let x = x.assert_err().map_err(|v| v * 2);
64    /// assert_eq!(x, Err(42));
65    /// ```
66    ///
67    /// ```rust,should_panic
68    /// use chain_assertions::prelude::*;
69    ///
70    /// let x: Result<&str, i32> = Ok("success");
71    /// let _ = x.assert_err().map_err(|v| v * 2);
72    /// //        ^-- panics here
73    fn assert_err(self) -> Self;
74
75    /// Asserts the [`Result`] is [`Err`] only in debug builds.
76    ///
77    /// # Panics
78    ///
79    /// If it is [`Ok`] and `debug_assertions` are enabled, the method panics.
80    /// If `debug_assertions` are disabled, the method is a no-op even if it is [`Ok`].
81    ///
82    /// # Examples
83    ///
84    /// ```rust
85    /// use chain_assertions::prelude::*;
86    ///
87    /// let x: Result<&str, i32> = Err(42);
88    /// let _ = x.debug_assert_err();
89    /// ```
90    fn debug_assert_err(self) -> Self;
91}
92
93impl<T, E> AssertOkExt for Result<T, E>
94where
95    E: crate::fmt::Debug,
96{
97    #[track_caller]
98    #[inline]
99    fn assert_ok(self) -> Self {
100        if let Err(ref e) = self {
101            panic!("Expected Ok(_), got Err({:?})", e);
102        }
103        self
104    }
105
106    #[track_caller]
107    #[inline]
108    fn debug_assert_ok(self) -> Self {
109        #[cfg(all(debug_assertions, not(feature = "passthrough")))]
110        {
111            if let Err(ref e) = self {
112                panic!("Expected Ok(_), got Err({:?})", e);
113            }
114        }
115        self
116    }
117}
118
119impl<T, E> AssertErrExt for Result<T, E>
120where
121    T: crate::fmt::Debug,
122{
123    #[track_caller]
124    #[inline]
125    fn assert_err(self) -> Self {
126        if let Ok(ref v) = self {
127            panic!("Expected Err(_), got Ok({:?})", v);
128        }
129        self
130    }
131
132    #[track_caller]
133    #[inline]
134    fn debug_assert_err(self) -> Self {
135        #[cfg(all(debug_assertions, not(feature = "passthrough")))]
136        {
137            if let Ok(ref v) = self {
138                panic!("Expected Err(_), got Ok({:?})", v);
139            }
140        }
141        self
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    struct NonDebuggable;
148
149    #[derive(Debug)]
150    struct Debuggable;
151
152    mod assert_ok {
153        use super::{super::*, *};
154
155        #[test]
156        fn it_succeeds_on_ok() {
157            let res: Result<NonDebuggable, Debuggable> = Ok(NonDebuggable);
158            let target = res.assert_ok();
159
160            assert!(
161                matches!(target, Ok(NonDebuggable)),
162                "Expected Ok(NonDebuggable)"
163            );
164        }
165
166        #[test]
167        #[should_panic(expected = "Expected Ok(_), got Err(Debuggable)")]
168        fn it_fails_on_err() {
169            let res: Result<NonDebuggable, Debuggable> = Err(Debuggable);
170            let _ = res.assert_ok();
171            //          ^-- should panic here
172        }
173    }
174
175    mod debug_assert_ok {
176        use super::{super::*, *};
177
178        #[test]
179        fn it_succeeds_on_ok() {
180            let res: Result<NonDebuggable, Debuggable> = Ok(NonDebuggable);
181            let target = res.debug_assert_ok();
182
183            assert!(matches!(target, Ok(NonDebuggable)), "Expected Ok(_)");
184        }
185
186        #[test]
187        #[cfg_attr(
188            all(debug_assertions, not(feature = "passthrough")),
189            should_panic = "Expected Ok(_), got Err(Debuggable)"
190        )]
191        fn it_fails_on_err_only_in_debug_mode() {
192            let res: Result<NonDebuggable, Debuggable> = Err(Debuggable);
193            let target = res.debug_assert_ok();
194            //               ^-- panic here only in debug builds
195
196            assert!(
197                matches!(target, Err(Debuggable)),
198                "Expected Err(Debuggable)"
199            );
200        }
201    }
202
203    mod assert_err {
204        use super::{super::*, *};
205
206        #[test]
207        fn it_succeeds_on_err() {
208            let res: Result<Debuggable, NonDebuggable> = Err(NonDebuggable);
209            let target = res.assert_err();
210            assert!(
211                matches!(target, Err(NonDebuggable)),
212                "Expected Err(NonDebuggable)"
213            );
214        }
215
216        #[test]
217        #[should_panic(expected = "Expected Err(_), got Ok(Debuggable)")]
218        fn it_fails_on_ok() {
219            let res: Result<Debuggable, NonDebuggable> = Ok(Debuggable);
220            let _ = res.assert_err();
221            //          ^-- should panic here
222        }
223    }
224
225    mod debug_assert_err {
226        use super::{super::*, *};
227
228        #[test]
229        fn it_succeeds_on_err() {
230            let res: Result<Debuggable, NonDebuggable> = Err(NonDebuggable);
231            let target = res.debug_assert_err();
232            assert!(
233                matches!(target, Err(NonDebuggable)),
234                "Expected Err(NonDebuggable)"
235            );
236        }
237
238        #[test]
239        #[cfg_attr(
240            all(debug_assertions, not(feature = "passthrough")),
241            should_panic = "Expected Err(_), got Ok(Debuggable)"
242        )]
243        fn it_fails_on_ok_only_in_debug_mode() {
244            let res: Result<Debuggable, NonDebuggable> = Ok(Debuggable);
245            let target = res.debug_assert_err();
246            //               ^-- panic here only in debug builds
247            assert!(matches!(target, Ok(Debuggable)), "Expected Ok(Debuggable)");
248        }
249    }
250}