Read binary u32 using nom

Viewed 343

I'm having a hard time finding any useful examples of how to use nom to parse a binary file, since it seems that the documentation is heavily biased towards &str input parsers.

I just want to make a function here that will read 4 bytes, turn it into a u32 and return it as a result. Here is my function:

fn take_u32(input: &[u8]) -> IResult<&[u8], u32> {
    map_res(
        take(4),
        |bytes| Ok(u32::from_be_bytes(bytes))
    )(input)
}

I'm getting the following error:

error[E0277]: the trait bound `[u8; 4]: From<u8>` is not satisfied
  --> src\main.rs:16:9
   |
16 |         take(4),
   |         ^^^^ the trait `From<u8>` is not implemented for `[u8; 4]`
   | 
  ::: C:\Users\cmbas\.cargo\registry\src\github.com-1ecc6299db9ec823\nom-7.1.0\src\bits\complete.rs:39:6
   |
39 |   O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
   |      -------- required by this bound in `nom::complete::take`

What is the canonical way to do what I'm attempting?

1 Answers

take() return Self aka your input, In your case slice &[u8].

map_res() is used to map a Result, from_be_bytes() doesn't return a result, the doc also contains an example using TryInto::try_into.

To make your code compile you need to use map_opt() and use try_into() to transform the slice to array:

fn take_u32(input: &[u8]) -> IResult<&[u8], u32> {
    map_opt(
        take(4),
        |bytes| int_bytes.try_into().map(u32::from_be_bytes)
    )(input)
}

That said nom already have such basic conbinator be_u32

Related