diff --git a/src/macros/seq.rs b/src/macros/seq.rs index c38ab78f..390bf0cb 100644 --- a/src/macros/seq.rs +++ b/src/macros/seq.rs @@ -22,7 +22,10 @@ /// // Parse into structs / tuple-structs /// fn field(input: &mut &[u8]) -> PResult { /// seq!{Field { -/// namespace: empty.value(5), +/// // `#[temp]` fields can be referenced later +/// // but they are ignored when building the struct +/// #[temp] ten: empty.value(10), +/// namespace: empty.value(ten / 2), /// name: alphanumeric1.map(|s: &[u8]| s.to_owned()), /// // `_` fields are ignored when building the struct /// _: (space0, b':', space0), @@ -119,13 +122,14 @@ macro_rules! seq_parse_struct_fields { }; ( $input: ident; - $head_field: ident : $head_parser: expr, $($fields: tt)* + $(#[temp])? $head_field: ident : $head_parser: expr, $($fields: tt)* ) => { let $head_field = $head_parser.parse_next($input)?; $crate::seq_parse_struct_fields!($input; $($fields)*) }; ( $input: ident; + // `#[temp]` in the last field makes no sense $head_field: ident : $head_parser: expr ) => { let $head_field = $head_parser.parse_next($input)?; @@ -192,6 +196,14 @@ macro_rules! seq_init_struct_fields { ) => { $crate::seq_init_struct_fields!( (); $name ; $($inits)* ) }; + ( + (#[temp] $head_field: ident : $head_parser: expr, $($fields: tt)*); + $name: ident; + $($inits: tt)* + ) => + { + $crate::seq_init_struct_fields!( ( $($fields)* ) ; $name ; $($inits)* ) + }; ( ($head_field: ident : $head_parser: expr, $($fields: tt)*); $name: ident; diff --git a/src/macros/test.rs b/src/macros/test.rs index 17601bc3..abc0e120 100644 --- a/src/macros/test.rs +++ b/src/macros/test.rs @@ -119,6 +119,46 @@ fn seq_struct_default_init() { ); } +#[test] +fn seq_struct_referring_elided() { + #[derive(Debug, PartialEq, Default)] + struct Point { + x: u32, + y: u32, + } + + fn parser(input: &mut &str) -> PResult { + seq! { + Point { + #[temp] half_x: dec_uint::<_, u32, _>, + x: empty.value(half_x * 2), + _: ',', + #[temp] half_y: dec_uint::<_, u32, _>, + y: empty.value(half_y * 2), + } + } + .parse_next(input) + } + assert_eq!( + parser.parse_peek("123,4 remaining"), + Ok((" remaining", Point { x: 246, y: 8 },)), + ); + assert_eq!( + parser.parse_peek("123, remaining"), + Err(ErrMode::Backtrack(ParserError::from_error_kind( + &" remaining", + ErrorKind::Fail + ))) + ); + assert_eq!( + parser.parse_peek(""), + Err(ErrMode::Backtrack(ParserError::from_error_kind( + &"", + ErrorKind::Fail + ))) + ); +} + #[test] fn seq_struct_trailing_comma_elided() { #![allow(dead_code)]