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}