winnow::combinator

Macro seq

Source
macro_rules! seq {
    ($($name: ident)::* { $($fields: tt)* }) => { ... };
    ($($name: ident)::* ( $($elements: tt)* )) => { ... };
    (( $($elements: tt)* )) => { ... };
    ($($elements: tt)*) => { ... };
}
Expand description

Initialize a struct or tuple out of a sequences of parsers

Unlike normal struct initialization syntax:

  • _ fields can exist to run a parser but ignore the result
  • Parse results for a field can later be referenced using the field name

Unlike normal tuple initialization syntax:

  • Struct-style initialization ({ 0: _, 1: _}) is not supported
  • _: <parser> fields can exist to run a parser but ignore the result

ยงExample

use winnow::combinator::seq;

#[derive(Default, Debug, PartialEq)]
struct Field {
    namespace: u32,
    name: Vec<u8>,
    value: Vec<u8>,
    point: (u32, u32),
    metadata: Vec<u8>,
}

// Parse into structs / tuple-structs
fn field(input: &mut &[u8]) -> PResult<Field> {
    seq!{Field {
        namespace: empty.value(5),
        name: alphanumeric1.map(|s: &[u8]| s.to_owned()),
        // `_` fields are ignored when building the struct
        _: (space0, b':', space0),
        value: alphanumeric1.map(|s: &[u8]| s.to_owned()),
        _: (space0, b':', space0),
        point: point,
        // default initialization also works
        ..Default::default()
    }}.parse_next(input)
}

// Or parse into tuples
fn point(input: &mut &[u8]) -> PResult<(u32, u32)> {
    let num = dec_uint::<_, u32, ContextError>;
    seq!(num, _: (space0, b',', space0), num).parse_next(input)
}

assert_eq!(
    field.parse_peek(&b"test: data: 123 , 4"[..]),
    Ok((
        &b""[..],
        Field {
            namespace: 5,
            name: b"test"[..].to_owned(),
            value: b"data"[..].to_owned(),
            point: (123, 4),
            metadata: Default::default(),
        },
    )),
);