const_util/result.rs
1//! Functions for unwrapping [`Result`]s
2
3/// # Safety
4/// The matchee must be passed by value
5macro_rules! expect_variant {
6 ($ex:expr, $variant:path, $msg:expr) => {{
7 let val = ::core::mem::ManuallyDrop::new($ex);
8 let val = $crate::mem::man_drop_ref(&val);
9 let $variant(val) = val else {
10 panic!("{}", $msg);
11 };
12 // SAFETY: ManuallyDrop holds the pointee by value and is not used afterwards
13 ::core::ptr::read(val)
14 }};
15}
16
17/// Const version of [`Result::expect`] without the [`Debug`] formatting.
18///
19/// Can also be used in combination with [`Result::is_ok`] to match the result.
20///
21/// # Example
22/// ```
23/// use const_util::result::expect_ok;
24/// const fn double<E>(res: Result<i32, E>) -> Result<i32, E> {
25/// if res.is_ok() {
26/// Ok(2 * expect_ok(res, "Unreachable"))
27/// } else {
28/// res
29/// }
30/// }
31/// assert_eq!(double(Ok::<_, String>(1)), Ok(2));
32/// ```
33#[track_caller]
34pub const fn expect_ok<T, E>(res: Result<T, E>, message: &str) -> T {
35 // SAFETY: `res` is passed by value
36 unsafe { expect_variant!(res, Ok, message) }
37}
38/// Const version of [`Result::unwrap`] without the [`Debug`] formatting.
39///
40/// Can also be used in combination with [`Result::is_ok`] to match the result.
41///
42/// # Example
43/// ```
44/// use const_util::result::unwrap_ok;
45/// const fn double<E>(res: Result<i32, E>) -> Result<i32, E> {
46/// if res.is_ok() {
47/// Ok(2 * unwrap_ok(res))
48/// } else {
49/// res
50/// }
51/// }
52/// assert_eq!(double(Ok::<_, String>(1)), Ok(2));
53/// ```
54#[track_caller]
55pub const fn unwrap_ok<T, E>(res: Result<T, E>) -> T {
56 expect_ok(res, "Attempted to call `unwrap_ok` on an `Err` variant")
57}
58/// Const version of [`Result::expect_err`] without the [`Debug`] formatting.
59///
60/// Can also be used in combination with [`Result::is_err`] to match the result.
61///
62/// # Example
63/// ```
64/// use const_util::result::expect_err;
65/// const fn double<T>(res: Result<T, i32>) -> Result<T, i32> {
66/// if res.is_err() {
67/// Err(2 * expect_err(res, "Unreachable"))
68/// } else {
69/// res
70/// }
71/// }
72/// assert_eq!(double(Err::<String, _>(1)), Err(2));
73/// ```
74#[track_caller]
75pub const fn expect_err<T, E>(res: Result<T, E>, message: &str) -> E {
76 // SAFETY: `res` is passed by value
77 unsafe { expect_variant!(res, Err, message) }
78}
79/// Const version of [`Result::unwrap_err`] without the [`Debug`] formatting.
80///
81/// Can also be used in combination with [`Result::is_err`] to match the result.
82///
83/// # Example
84/// ```
85/// use const_util::result::unwrap_err;
86/// const fn double<T>(res: Result<T, i32>) -> Result<T, i32> {
87/// if res.is_err() {
88/// Err(2 * unwrap_err(res))
89/// } else {
90/// res
91/// }
92/// }
93/// assert_eq!(double(Err::<String, _>(1)), Err(2));
94/// ```
95#[track_caller]
96pub const fn unwrap_err<T, E>(res: Result<T, E>) -> E {
97 expect_err(res, "Attempted to call `unwrap_err` on an `Ok` variant")
98}