Macro iter_str_context

Source
macro_rules! iter_str_context {
    ($iter:expr) => { ... };
}
Expand description

Take an array of dyn Iterator<Item = &'static str> and return a closure that flattens the outer array to map the inner values onto [winnow::error::StrContextValue::StringLiteral].

ยงExample

use alpm_parsers::iter_str_context;
use winnow::{
    ModalResult,
    Parser,
    combinator::{alt, cut_err},
};
/// A parser with a single list of keywords
fn parser_single<'a>(input: &mut &'a str) -> ModalResult<&'a str> {
    let first_list = ["first", "second", "third"];
    alt(first_list)
        .context_with(iter_str_context!([first_list]))
        .parse_next(input)
}

const FIRST_LIST: [&str; 3] = ["first", "second", "third"];
const SECOND_LIST: [&str; 2] = ["fourth", "fifth"];

fn first_parser<'a>(input: &mut &'a str) -> ModalResult<&'a str> {
    alt(FIRST_LIST).parse_next(input)
}

fn second_parser<'a>(input: &mut &'a str) -> ModalResult<&'a str> {
    alt(SECOND_LIST).parse_next(input)
}

/// Can be used like this on static arrays of varying length.
fn parser_multi<'a>(input: &mut &'a str) -> ModalResult<&'a str> {
    cut_err(alt((first_parser, second_parser)))
        .context_with(iter_str_context!([
            FIRST_LIST.to_vec(),
            SECOND_LIST.to_vec()
        ]))
        .parse_next(input)
}

/// And as follows on local arrays of varying length.
fn parser_multi_alt<'a>(input: &mut &'a str) -> ModalResult<&'a str> {
    let first_list = ["first", "second", "third"];
    let second_list = ["fourth", "fifth"];
    alt((first_parser, second_parser))
        .context_with(iter_str_context!([
            first_list.to_vec(),
            second_list.to_vec()
        ]))
        .parse_next(input)
}

assert!(parser_single.parse("second").is_ok());
assert!(parser_multi.parse("fourth").is_ok());
assert!(parser_multi_alt.parse("fourth").is_ok());