Conditionally parsing an array based on previous elements with nom

2

I need to parse an array of 32 bit ints (little endian), from an array of u8s, however the next int only exists if the 31st bit of the current int is set. If the rest don't exist then the rest of the array should be set to zeroes. I'm not sure how to go about conditionally parsing the next element.

Lets say the field is 4 bytes long. Then the result of the parse_field function would be that the 4 bytes would be parsed with le_u32, and that would be the first element in the [u32; 8] array. If however, this field's 31st bit is set. Then there exists another 4 bytes that is also like this field and it goes in the next element in the array. If it is not set then the function must return, the array with the rest of the elements set to zero. And this continue for each existing field.

For example for the following input:

0x8000000a
0x8000000b
...

You would get [0x8000000a, 0x8000000b, 0, 0, 0, 0, 0, 0]

But if the input is

0x8000000a
0x8000000b
0x8000000c
0x8000000d
0x8000000e
....

Then you would get [0x8000000a, 0x8000000b, 0x8000000c, 0x8000000d, 0x8000000e, 0, 0, 0]

extern crate nom;

use nom::*;

#[derive(Clone, Copy, Debug)]
struct Derp {
    field: [u32; 8]
}

named!(parse_field<[u32; 8]>,

    // what do I do here

);


named!(parse_derp<Derp>,
    do_parse!(
        field: parse_field >>
        (Derp {
            field: field
        })
    )
);

fn main() {
    let temp = [0x0a, 0x00, 0x00, 0x80, 0x0b, 0x00, 0x00, 0x80];
    println!("{:?}", parse_derp(&temp));
}

Also is it possibly better to use a Vec here?

parsing
rust
nom
asked on Stack Overflow Apr 6, 2018 by Ross MacArthur • edited Apr 7, 2018 by Ross MacArthur

1 Answer

1

Here is a parser that matches the last u32 of your input:

named!(last_u32<u32>,
  verify!(le_u32, |n:u32| (n & 0b1) != 0) // Matches iff the 31st bit is set
);

you can then use it like this:

named!(parse_field<Vec<u32>>,
  map!(
    many_till!(le_u32, last_u32),
    |(mut v,n)| { v.push(n); v } // Add the last u32 to the vector
  ) 
);
answered on Stack Overflow Jun 3, 2018 by Valentin Lorentz

User contributions licensed under CC BY-SA 3.0