Macro konst::try_

source ·
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 fns because as of Rust 1.65.0 trait methods don’t work in const fns.

§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 {}