or_panic/
lib.rs

1#![cfg_attr(feature = "no_std", no_std)]
2
3use core::fmt::{Debug, Display};
4
5pub trait OptionOrPanic<T> {
6    /// Unwrap the [`Option`] or panic with a message.
7    ///
8    /// Results:
9    /// `Some(T)` -> `T`
10    /// [`None`] -> [`panic`] with custom message
11    #[track_caller]
12    fn or_panic<M: Display>(self, msg: M) -> T;
13}
14
15impl<T> OptionOrPanic<T> for Option<T> {
16    #[track_caller]
17    fn or_panic<M: Display>(self, msg: M) -> T {
18        self.unwrap_or_else(|| panic!("{msg}"))
19    }
20}
21
22pub trait ResultOrPanic<T> {
23    /// Unwrap the [`Result`] or panic with a message.
24    ///
25    /// Results:
26    /// Ok(T) -> `T`
27    /// Err(E) -> [`panic`] with custom message
28    ///
29    /// NOTE: The error type of your [`Result`] must implement [`Debug`].
30    #[track_caller]
31    fn or_panic<M: Display>(self, msg: M) -> T;
32}
33
34impl<T, E: Debug> ResultOrPanic<T> for Result<T, E> {
35    #[track_caller]
36    fn or_panic<M: Display>(self, msg: M) -> T {
37        self.unwrap_or_else(|err| panic!("{msg}.\nCaused by: {err:?}"))
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn option_or_panic_returns_value() {
47        let x = Some(42).or_panic("should not panic");
48        assert_eq!(x, 42);
49    }
50
51    #[test]
52    #[should_panic(expected = "option is missing")]
53    fn option_or_panic_panics_on_none() {
54        let x: Option<i32> = None;
55        x.or_panic("option is missing");
56    }
57
58    #[test]
59    #[should_panic(expected = "error 123")]
60    fn option_or_panic_handles_display_types() {
61        let x: Option<i32> = None;
62        let code = 123;
63        x.or_panic(format!("error {code}"));
64    }
65
66    #[test]
67    fn result_or_panic_returns_ok_value() {
68        let r: Result<i32, &str> = Ok(7);
69        let x = r.or_panic("no panic expected");
70        assert_eq!(x, 7);
71    }
72
73    #[test]
74    #[should_panic(expected = "explicit failure.\nCaused by: \"boom\"")]
75    fn result_or_panic_panics_on_err() {
76        let r: Result<i32, &str> = Err("boom");
77        r.or_panic("explicit failure");
78    }
79
80    #[test]
81    #[should_panic(expected = "Bad stuff.\nCaused by: 404")]
82    fn result_or_panic_works_with_display_formatting() {
83        let r: Result<i32, i32> = Err(404);
84        r.or_panic("Bad stuff");
85    }
86
87    #[test]
88    fn result_or_panic_allows_non_string_message_types() {
89        let r: Result<&str, &str> = Ok("yay");
90        let msg_int = 999; // i32 implements Display
91
92        let v = r.or_panic(msg_int);
93        assert_eq!(v, "yay");
94    }
95}