Module winnow::_tutorial::chapter_7

source ·
Available on crate feature unstable-doc only.
Expand description

Chapter 7: Integrating the Parser

So far, we’ve highlighted how to incrementally parse, but how do we bring this all together into our application?

Parsers we’ve been working with look like:

pub fn parser<'s>(input: &mut &'s str) -> PResult<&'s str> {
    // ...
}

type PResult<O> = Result<
    O,
    ErrMode<ContextError>
>;
  1. We have to decide what to do about the “remainder” of the input.
  2. The ErrMode<ContextError> is not compatible with the rest of the Rust ecosystem. Normally, Rust applications want errors that are std::error::Error + Send + Sync + 'static meaning:
    • They implement the std::error::Error trait
    • They can be sent across threads
    • They are safe to be referenced across threads
    • They do not borrow

winnow provides Parser::parse to help with this:

use winnow::Parser;

#[derive(Debug, PartialEq, Eq)]
pub struct Hex(usize);

impl std::str::FromStr for Hex {
    type Err = String;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        parse_digits
            .map(Hex)
            .parse(input)
            .map_err(|e| e.to_string())
    }
}

// ...

fn main() {
    let input = "0x1a2b";
    assert_eq!(input.parse::<Hex>().unwrap(), Hex(0x1a2b));

    let input = "0x1a2b Hello";
    assert!(input.parse::<Hex>().is_err());
    let input = "ghiHello";
    assert!(input.parse::<Hex>().is_err());
}

Re-exports