konst/macros/
unwrapping.rs

1/// `?`-like macro, which allows optionally mapping errors.
2///
3/// `?` currently doesn't work in `const fn`s because as of Rust 1.65.0
4/// trait methods don't work in `const fn`s.
5///
6/// # Examples
7///
8/// ### Basic
9///
10/// ```rust
11/// use konst::try_;
12///
13/// const OK: Result<&str, u8> = expect_no_whitespace("hello");
14/// assert_eq!(OK, Ok("hello"));
15///
16/// const ERR: Result<&str, u8> = expect_no_whitespace("hello world");
17/// assert_eq!(ERR, Err(b' '));
18///
19///
20/// const fn expect_no_whitespace(string: &str) -> Result<&str, u8> {
21///     let bytes = string.as_bytes();
22///     konst::for_range!{i in 0..bytes.len() =>
23///         try_!(assert_not_whitespace(bytes[i]));
24///     }
25///     Ok(string)
26/// }
27///
28/// const fn assert_not_whitespace(byte: u8) -> Result<(), u8> {
29///     if matches!(byte, b'\t' | b'\n' | b'\r' | b' ') {
30///         Err(byte)
31///     } else {
32///         Ok(())
33///     }
34/// }
35///
36/// ```
37///
38/// ### Mapping errors
39///
40/// ```rust
41/// use konst::try_;
42///
43/// const EVENS: Result<[Even; 4], u32> =
44///     array_to_even([0, 2, 4, 6]);
45///
46/// let new = |n| Even::new(n).unwrap();
47/// assert_eq!(EVENS, Ok([new(0), new(2), new(4), new(6)]));
48///
49///
50/// const UNEVEN: Result<[Even; 4], u32> =
51///     array_to_even([0, 2, 5, 6]);
52///
53/// assert_eq!(UNEVEN, Err(5));
54///
55///
56/// const fn array_to_even(arr: [u32; 4]) -> Result<[Even; 4], u32> {
57///     let mut ret = [Even::ZERO; 4];
58///     
59///     konst::for_range!{i in 0..4 =>
60///         ret[i] = try_!(Even::new(arr[i]), map_err = |e| e.get() );
61///     }
62///     
63///     Ok(ret)
64/// }
65///
66/// #[derive(Debug, PartialEq)]
67/// pub struct Even(u32);
68///
69/// impl Even {
70///     const ZERO: Even = Even(0);
71///     
72///     pub const fn new(number: u32) -> Result<Self, NotEven> {
73///         if number % 2  == 0 {
74///             Ok(Even(number))
75///         } else {
76///             Err(NotEven(number))
77///         }
78///     }
79/// }
80///
81/// #[derive(Debug, PartialEq)]
82/// pub struct NotEven(u32);
83///
84/// impl NotEven {
85///     pub const fn get(&self) -> u32 {
86///         self.0
87///     }
88/// }
89///
90/// use std::fmt::{self, Display};
91///
92/// impl Display for NotEven {
93///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94///         fmt::Debug::fmt(self, f)
95///     }
96/// }
97///
98/// impl std::error::Error for NotEven {}
99///
100/// ```
101///
102#[macro_export]
103macro_rules! try_ {
104    ($e:expr, map_err = |$($pati:pat_param)?| $v:expr $(,)*) => {
105        match $e {
106            $crate::__::Ok(x) => x,
107            $crate::__::Err{$(0: $pati,)? ..} => return $crate::__::Err($v),
108        }
109    };
110    ($e:expr $(,)*) => {{
111        match $e {
112            $crate::__::Ok(x) => x,
113            $crate::__::Err(e) => return $crate::__::Err(e),
114        }
115    }};
116}
117
118/// `?`-like macro for `Option`s.
119///
120/// # Example
121///
122/// ```rust
123/// use konst::try_opt;
124///
125/// const SOME: Option<u8> = sum_u8s(&[3, 5, 8, 13]);
126/// assert_eq!(SOME, Some(29));
127///
128/// const NONE: Option<u8> = sum_u8s(&[3, 5, 8, 13, 240]);
129/// assert_eq!(NONE, None);
130///
131/// const fn sum_u8s(mut nums: &[u8]) -> Option<u8> {
132///     let mut sum = 0_u8;
133///     while let [first, rem @ ..] = nums {
134///         nums = rem;
135/// #       sum = try_opt!(checked_add(sum, *first));
136/// # /*
137///         sum = try_opt!(sum.checked_add(*first));
138/// # */
139///     }
140///     Some(sum)
141/// }
142///
143/// # const fn checked_add(l: u8, r: u8) -> Option<u8> {
144/// #   let (res, overflowed) = l.overflowing_add(r);
145/// #   if overflowed { None } else { Some(res) }
146/// # }
147/// ```
148///
149#[macro_export]
150macro_rules! try_opt {
151    ($opt:expr $(,)*) => {
152        match $opt {
153            $crate::__::Some(x) => x,
154            $crate::__::None => return $crate::__::None,
155        }
156    };
157}