macro_rules! try_ { ($e:expr, map_err = |$($pati:pat_param)?| $v:expr $(,)*) => { ... }; ($e:expr $(,)*) => { ... }; }
Expand description
?
-like macro, which allows optionally mapping errors.
?
currently doesn’t work in const fn
s because as of Rust 1.65.0
trait methods don’t work in const fn
s.
§Examples
§Basic
use konst::try_;
const OK: Result<&str, u8> = expect_no_whitespace("hello");
assert_eq!(OK, Ok("hello"));
const ERR: Result<&str, u8> = expect_no_whitespace("hello world");
assert_eq!(ERR, Err(b' '));
const fn expect_no_whitespace(string: &str) -> Result<&str, u8> {
let bytes = string.as_bytes();
konst::for_range!{i in 0..bytes.len() =>
try_!(assert_not_whitespace(bytes[i]));
}
Ok(string)
}
const fn assert_not_whitespace(byte: u8) -> Result<(), u8> {
if matches!(byte, b'\t' | b'\n' | b'\r' | b' ') {
Err(byte)
} else {
Ok(())
}
}
§Mapping errors
use konst::try_;
const EVENS: Result<[Even; 4], u32> =
array_to_even([0, 2, 4, 6]);
let new = |n| Even::new(n).unwrap();
assert_eq!(EVENS, Ok([new(0), new(2), new(4), new(6)]));
const UNEVEN: Result<[Even; 4], u32> =
array_to_even([0, 2, 5, 6]);
assert_eq!(UNEVEN, Err(5));
const fn array_to_even(arr: [u32; 4]) -> Result<[Even; 4], u32> {
let mut ret = [Even::ZERO; 4];
konst::for_range!{i in 0..4 =>
ret[i] = try_!(Even::new(arr[i]), map_err = |e| e.get() );
}
Ok(ret)
}
#[derive(Debug, PartialEq)]
pub struct Even(u32);
impl Even {
const ZERO: Even = Even(0);
pub const fn new(number: u32) -> Result<Self, NotEven> {
if number % 2 == 0 {
Ok(Even(number))
} else {
Err(NotEven(number))
}
}
}
#[derive(Debug, PartialEq)]
pub struct NotEven(u32);
impl NotEven {
pub const fn get(&self) -> u32 {
self.0
}
}
use std::fmt::{self, Display};
impl Display for NotEven {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl std::error::Error for NotEven {}