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}