1#![cfg_attr(feature = "no_std", no_std)]
2
3use core::fmt::{Debug, Display};
4
5pub trait OptionOrPanic<T> {
6 #[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 #[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; let v = r.or_panic(msg_int);
93 assert_eq!(v, "yay");
94 }
95}