konst/macros/unwrapping.rs
1/// For unwrapping `Result`s in const contexts, with a default value when it's an error.
2#[deprecated(
3 since = "0.2.1",
4 note = "Use `konst::result::unwrap_or`, or `konst::result::unwrap_or_else` instead"
5)]
6#[macro_export]
7macro_rules! unwrap_res_or {
8 ($e:expr, |$($pati:pat)?| $v:expr) => {
9 match $e {
10 $crate::__::Ok(x) => x,
11 $crate::__::Err{$(0: $pati,)? ..} => $v,
12 }
13 };
14 ($e:expr, $v:expr) => {{
15 let value = $v;
16 match $e {
17 $crate::__::Ok(x) => x,
18 $crate::__::Err(_) => value,
19 }
20 }};
21}
22
23/// For unwrapping `Option`s in const contexts, with a default value when it's a `None`.
24#[deprecated(
25 since = "0.2.1",
26 note = "Use `konst::option::unwrap_or`, or `konst::option::unwrap_or_else` instead"
27)]
28#[macro_export]
29macro_rules! unwrap_opt_or {
30 ($e:expr, || $v:expr) => {
31 match $e {
32 $crate::__::Some(x) => x,
33 $crate::__::None => $v,
34 }
35 };
36 ($e:expr, |_| $v:expr) => {
37 match $e {
38 $crate::__::Some(x) => x,
39 $crate::__::None => $v,
40 }
41 };
42 ($e:expr, $v:expr) => {{
43 let value = $v;
44 match $e {
45 $crate::__::Some(x) => x,
46 $crate::__::None => value,
47 }
48 }};
49}
50
51/// `?`-like macro, which allows optionally mapping errors.
52///
53/// `?` currently doesn't work in `const fn`s because as of Rust 1.51.0
54/// trait methods don't work in `const fn`s.
55///
56/// # Examples
57///
58/// ### Basic
59///
60/// ```rust
61/// use konst::try_;
62///
63/// const OK: Result<&str, u8> = expect_no_whitespace("hello");
64/// assert_eq!(OK, Ok("hello"));
65///
66/// const ERR: Result<&str, u8> = expect_no_whitespace("hello world");
67/// assert_eq!(ERR, Err(b' '));
68///
69///
70/// const fn expect_no_whitespace(string: &str) -> Result<&str, u8> {
71/// let bytes = string.as_bytes();
72/// konst::for_range!{i in 0..bytes.len() =>
73/// try_!(assert_not_whitespace(bytes[i]));
74/// }
75/// Ok(string)
76/// }
77///
78/// const fn assert_not_whitespace(byte: u8) -> Result<(), u8> {
79/// if matches!(byte, b'\t' | b'\n' | b'\r' | b' ') {
80/// Err(byte)
81/// } else {
82/// Ok(())
83/// }
84/// }
85///
86/// ```
87///
88/// ### Mapping errors
89///
90/// ```rust
91/// use konst::try_;
92///
93/// const EVENS: Result<[Even; 4], u32> =
94/// array_to_even([0, 2, 4, 6]);
95///
96/// let new = |n| Even::new(n).unwrap();
97/// assert_eq!(EVENS, Ok([new(0), new(2), new(4), new(6)]));
98///
99///
100/// const UNEVEN: Result<[Even; 4], u32> =
101/// array_to_even([0, 2, 5, 6]);
102///
103/// assert_eq!(UNEVEN, Err(5));
104///
105///
106/// const fn array_to_even(arr: [u32; 4]) -> Result<[Even; 4], u32> {
107/// let mut ret = [Even::ZERO; 4];
108///
109/// konst::for_range!{i in 0..4 =>
110/// ret[i] = try_!(Even::new(arr[i]), map_err = |e| e.get() );
111/// }
112///
113/// Ok(ret)
114/// }
115///
116/// #[derive(Debug, PartialEq)]
117/// pub struct Even(u32);
118///
119/// impl Even {
120/// const ZERO: Even = Even(0);
121///
122/// pub const fn new(number: u32) -> Result<Self, NotEven> {
123/// if number % 2 == 0 {
124/// Ok(Even(number))
125/// } else {
126/// Err(NotEven(number))
127/// }
128/// }
129/// }
130///
131/// #[derive(Debug, PartialEq)]
132/// pub struct NotEven(u32);
133///
134/// impl NotEven {
135/// pub const fn get(&self) -> u32 {
136/// self.0
137/// }
138/// }
139///
140/// use std::fmt::{self, Display};
141///
142/// impl Display for NotEven {
143/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144/// fmt::Debug::fmt(self, f)
145/// }
146/// }
147///
148/// impl std::error::Error for NotEven {}
149///
150/// ```
151///
152#[macro_export]
153macro_rules! try_ {
154 ($e:expr, map_err = |$($pati:pat)?| $v:expr $(,)*) => {
155 match $e {
156 $crate::__::Ok(x) => x,
157 $crate::__::Err{$(0: $pati,)? ..} => return $crate::__::Err($v),
158 }
159 };
160 ($e:expr $(,)*) => {{
161 match $e {
162 $crate::__::Ok(x) => x,
163 $crate::__::Err(e) => return $crate::__::Err(e),
164 }
165 }};
166}
167
168/// `?`-like macro for `Option`s.
169///
170/// # Example
171///
172/// ```rust
173/// use konst::try_opt;
174///
175/// const SOME: Option<u8> = sum_u8s(&[3, 5, 8, 13]);
176/// assert_eq!(SOME, Some(29));
177///
178/// const NONE: Option<u8> = sum_u8s(&[3, 5, 8, 13, 240]);
179/// assert_eq!(NONE, None);
180///
181/// const fn sum_u8s(mut nums: &[u8]) -> Option<u8> {
182/// let mut sum = 0_u8;
183/// while let [first, rem @ ..] = nums {
184/// nums = rem;
185/// # sum = try_opt!(checked_add(sum, *first));
186/// # /*
187/// sum = try_opt!(sum.checked_add(*first));
188/// # */
189/// }
190/// Some(sum)
191/// }
192///
193/// # const fn checked_add(l: u8, r: u8) -> Option<u8> {
194/// # let (res, overflowed) = l.overflowing_add(r);
195/// # if overflowed { None } else { Some(res) }
196/// # }
197/// ```
198///
199#[macro_export]
200macro_rules! try_opt {
201 ($opt:expr $(,)*) => {
202 match $opt {
203 $crate::__::Some(x) => x,
204 $crate::__::None => return $crate::__::None,
205 }
206 };
207}