konst/macros/
parsing_polymorphism_macros.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/// Parses a type that impls [`HasParser`] with the passed in [`Parser`].
///
/// # Example
///
/// This example demonstrates how you can use this macro to parse both
/// standard library and user-defined types.
///
/// ```rust
/// use konst::{parse_with, try_rebind, unwrap_ctx};
///
/// use konst::parsing::{HasParser, Parser, ParseValueResult};
///
/// const PAIR: (u32, Foo) = unwrap_ctx!(parse_pair(Parser::new("100,Baz"))).0;
///
/// assert_eq!(PAIR.0, 100);
/// assert_eq!(PAIR.1, Foo::Baz);
///
/// const fn parse_pair(mut parser: Parser<'_>) -> ParseValueResult<'_, (u32, Foo)> {
///     try_rebind!{(let left, parser) = parse_with!(parser, u32)}
///     try_rebind!{parser = parser.strip_prefix(',')}
///     try_rebind!{(let right, parser) = parse_with!(parser, Foo)}
///     
///     Ok(((left, right), parser))
/// }
///
///
/// #[derive(Debug, PartialEq)]
/// enum Foo {
///     Bar,
///     Baz,
///     Qux,
/// }
///
/// impl HasParser for Foo {
///     type Parser = Self;
/// }
///
/// impl Foo {
///     const fn parse_with(parser: Parser<'_>) -> ParseValueResult<'_, Self> {
///         // You can use the `parser_method` macro instead of this chain of if elses
///         if let Ok(parser) = parser.strip_prefix("Bar") {
///             Ok((Foo::Bar, parser))
///         } else if let Ok(parser) = parser.strip_prefix("Baz") {
///             Ok((Foo::Baz, parser))
///         } else if let Ok(parser) = parser.strip_prefix("Qux") {
///             Ok((Foo::Qux, parser))
///         } else {
///             Err(parser.into_other_error(&"expected one of `Bar`, `Baz`, or `Qux`"))
///         }
///     }
/// }
/// ```
///
/// [`Parser`]: ./parsing/struct.Parser.html
/// [`HasParser`]: ./parsing/trait.HasParser.html
#[macro_export]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "parsing")))]
macro_rules! parse_with {
    ($parser:expr, $type:ty $(,)*) => {
        match $parser {
            parser @ $crate::Parser { .. } => {
                let res: $crate::__::Result<_, _> =
                    <<$type as $crate::parsing::HasParser>::Parser>::parse_with(parser);
                res
            }
        }
    };
}