Macro konst::parse_any[][src]

macro_rules! parse_any {
    ($place : expr, find_skip ; $($branches : tt) *) => { ... };
    ($place : expr, rfind_skip ; $($branches : tt) *) => { ... };
    ($place : expr, strip_prefix ; $($branches : tt) *) => { ... };
    ($place : expr, strip_suffix ; $($branches : tt) *) => { ... };
    ($place : expr, trim_start_matches ; $($branches : tt) *) => { ... };
    ($place : expr, trim_end_matches ; $($branches : tt) *) => { ... };
    ($place : expr, $unknown_method : ident ; $($branches : tt) *) => { ... };
}
This is supported on crate feature parsing only.
Expand description

Calls a Parser method with many alternative string literals.

If any of the literals match, the parser is mutated accordingly, otherwise it keeps the unparsed bytes to parse them again.

Syntax

The general syntax for this macro is parse_any!{ <parser_expression> , <method_name> => <branches> }

Where <parser_expression> is an expression (of Parser type) that can be assigned into.

Where <method_name> is the name of one of the Parser methods usable in this macro:

Where <branches> can be either of these, depending on the <method_name>:

  • A match-like syntax: A comma separated sequence of <patterns> => <expression> branches, the last branch must be _ => <expression>.

  • Just the patterns: <patterns>.

Where <patterns> can be be any amount of |-separated string literals (constants don’t work here), or _. Note that passing a macro that expands to a literal doesn’t work here, concat and stringify are special cased to work.

Example

Parsing enum

use konst::{
    parsing::{Parser, ParseValueResult},
    parse_any, unwrap_ctx,
};

#[derive(Debug, PartialEq)]
enum Color {
    Red,
    Blue,
    Green,
}

impl Color {
    pub const fn try_parse(mut parser: Parser<'_>) -> ParseValueResult<'_, Color> {
        parse_any!{parser, strip_prefix;
            "Red"|"red" => Ok((Color::Red, parser)),
            "Blue"|"blue" => Ok((Color::Blue, parser)),
            "Green"|"green" => Ok((Color::Green, parser)),
            _ => Err(parser.into_other_error()),
        }
    }
}

const COLORS: [Color; 4] = {
    let parser = Parser::from_str("BlueRedGreenGreen");
    let (c0, parser) = unwrap_ctx!(Color::try_parse(parser));
    let (c1, parser) = unwrap_ctx!(Color::try_parse(parser));
    let (c2, parser) = unwrap_ctx!(Color::try_parse(parser));
    let (c3, _     ) = unwrap_ctx!(Color::try_parse(parser));
     
    [c0, c1, c2, c3]
};

assert_eq!(COLORS, [Color::Blue, Color::Red, Color::Green, Color::Green])

find_skip

use konst::{
    parsing::{Parser, ParseValueResult},
    parse_any, unwrap_ctx,
};

{
    let mut parser = Parser::from_str("baz_foo_bar_foo");

    fn find(parser: &mut Parser<'_>) -> u32 {
        let before = parser.bytes();
        parse_any!{*parser, find_skip;
            "foo" => 0,
            "bar" => 1,
            "baz" => 2,
            _ => {
                assert_eq!(before, parser.bytes());
                3
            }
        }
    }

    assert_eq!(find(&mut parser), 2);
    assert_eq!(parser.bytes(), "_foo_bar_foo".as_bytes());
     
    assert_eq!(find(&mut parser), 0);
    assert_eq!(parser.bytes(), "_bar_foo".as_bytes());
     
    assert_eq!(find(&mut parser), 1);
    assert_eq!(parser.bytes(), "_foo".as_bytes());
     
    assert_eq!(find(&mut parser), 0);
    assert_eq!(parser.bytes(), "".as_bytes());
     
    assert_eq!(find(&mut parser), 3);
    assert_eq!(parser.bytes(), "".as_bytes());
}
{
    let mut parser = Parser::from_str("foo_bar_foo_baz");

    fn rfind(parser: &mut Parser<'_>) -> u32 {
        parse_any!{*parser, rfind_skip;
            "foo" => 0,
            "bar" => 1,
            "baz" => 2,
            _ => 3,
        }
    }

    assert_eq!(rfind(&mut parser), 2);
    assert_eq!(parser.bytes(), "foo_bar_foo_".as_bytes());
     
    assert_eq!(rfind(&mut parser), 0);
    assert_eq!(parser.bytes(), "foo_bar_".as_bytes());
     
    assert_eq!(rfind(&mut parser), 1);
    assert_eq!(parser.bytes(), "foo_".as_bytes());
     
    assert_eq!(rfind(&mut parser), 0);
    assert_eq!(parser.bytes(), "".as_bytes());
     
    assert_eq!(rfind(&mut parser), 3);
    assert_eq!(parser.bytes(), "".as_bytes());
}


Trimming

use konst::{
    parsing::{Parser, ParseValueResult},
    parse_any, unwrap_ctx,
};

{
    let mut parser = Parser::from_str("foobarhellofoobar");
    parse_any!{parser, trim_start_matches; "foo" | "bar" }
    assert_eq!(parser.bytes(), "hellofoobar".as_bytes());
}
{
    let mut parser = Parser::from_str("foobarhellofoobar");
    parse_any!{parser, trim_end_matches; "foo" | "bar" }
    assert_eq!(parser.bytes(), "foobarhello".as_bytes());
}
{
    let mut parser = Parser::from_str("foobar");
    // Empty string literals make trimming finish when the previous patterns didn't match,
    // so the "bar" pattern doesn't do anything here
    parse_any!{parser, trim_start_matches; "foo" | "" | "bar" }
    assert_eq!(parser.bytes(), "bar".as_bytes());
}