Skip to main content

ParserUntil

Trait ParserUntil 

Source
pub trait ParserUntil: Sized {
    // Required method
    fn parser_until<'a, P>(
        delimiter: P,
    ) -> impl Parser<&'a str, Self, ErrMode<ContextError>>
       where P: Parser<&'a str, &'a str, ErrMode<ContextError>>;

    // Provided methods
    fn parser_until_eof(input: &mut &str) -> ModalResult<Self> { ... }
    fn parser_until_line_ending(input: &mut &str) -> ModalResult<Self> { ... }
}
Expand description

A trait for types that can be parsed until a given delimiter parser matches.

Allows wrapping non-delimiter-aware type parsers, to make them delimiter-aware for inline usage in file parsers. Type parsers, such as PackageVersion, do not have any knowledge about the surrounding file format or context during parsing. This trait allows type parsers to stay pure and agnostic to the surrounding format, while allowing file format parsers to specify a delimiter, such as \n or ,, providing the necessary context to parse the type inside the format in question.

The ParserUntil trait is auto-implemented for every type implementing AlpmParser.

The ParserUntilInclusive trait is auto-implemented for every type implementing ParserUntil and provides functions to also consume the specified delimiter.

§Note

Produced parsers are expected to NOT consume the delimiter. To properly enforce this constraint several conventions must be upheld:

  • Delimiters must not be part of the allowed set of tokens. Otherwise there’s no way to distinguish between delimiter and content.
  • In the case that a file format supports escaping, that file format must implement their own escaping-aware variants of parsers for the affected types.

§Examples

use alpm_parsers::traits::{AlpmParser, ParserUntil};
use winnow::{
    ModalResult,
    Parser,
    error::{ContextError, ErrMode, StrContext},
    token::take_while,
};

#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
struct Alphanumeric(String);

// Implementing `AlpmParser` automatically implements `ParserUntil`.
impl AlpmParser for Alphanumeric {
    fn parser(input: &mut &str) -> ModalResult<Self> {
        take_while(1.., |c: char| c.is_alphanumeric())
            .map(|s: &str| Alphanumeric(s.to_string()))
            .parse_next(input)
    }

    fn delimiter_error_context<'a, O, P>(
        parser: P,
    ) -> impl Parser<&'a str, O, ErrMode<ContextError>>
    where
        P: Parser<&'a str, O, ErrMode<ContextError>>,
    {
        parser.context(StrContext::Label("alphanumeric characters"))
    }
}

// The parser succeeds with a alphanumeric string that is followed by a newline.
assert_eq!(
    Alphanumeric::parser_until_line_ending.parse_peek("abc123\nnext"),
    Ok(("\nnext", Alphanumeric("abc123".to_string())))
);

// An alphanumeric string followed by a non-alphanumeric character that isn't a
// newline will fail.
assert!(matches!(
    Alphanumeric::parser_until_line_ending.parse_peek("abc123{\nnext"),
    Err(_),
));

// If we expect it to be a `{` though, it works just as expected.
assert_eq!(
    Alphanumeric::parser_until("{").parse_peek("abc123{\nnext"),
    Ok(("{\nnext", Alphanumeric("abc123".to_string())))
);

// Parsing the full string with `parser_until_eof` works as expected.
assert_eq!(
    Alphanumeric::parser_until_eof.parse_peek("abc123"),
    Ok(("", Alphanumeric("abc123".to_string())))
);

// If there's anything but the end of the input, the parser fails.
assert!(matches!(
    Alphanumeric::parser_until_eof.parse_peek("abc123_"),
    Err(_)
));

Required Methods§

Source

fn parser_until<'a, P>( delimiter: P, ) -> impl Parser<&'a str, Self, ErrMode<ContextError>>
where P: Parser<&'a str, &'a str, ErrMode<ContextError>>,

Returns a [Parser] that parses Self until the given delimiter parser matches.

§Note

Does not consume the delimiter.

Provided Methods§

Source

fn parser_until_eof(input: &mut &str) -> ModalResult<Self>

Returns a [Parser] that parses an entire input.

Delegates to Self::parser_until with the [eof] delimiter.

§Note

The returned [Parser] is required to fully consume input.

Source

fn parser_until_line_ending(input: &mut &str) -> ModalResult<Self>

Returns a [Parser] that parses until the end of line or [eof].

Delegates to Self::parser_until with the [line_ending] or [eof] delimiter. A line ending is either \n or \r\n.

§Note

The line ending is not consumed.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§