Reputation: 143
I am writing a nom parser combinator that consumes bytes and returns an Option<&[u8]>
. The parser combinator should follow the following rules:
s
)s
is -1, return None
s
is not -1, read s
bits and return Some
Here is my parser combinator:
fn parse(i: &[u8]) -> nom::IResult<&[u8], Option<&[u8]>> {
nom::combinator::flat_map(be_i16, |s: i16| {
match s {
-1 => nom::combinator::success(None),
_ => nom::combinator::map(take(s as u16), Some)
}
})(i)
}
However I am seeing the following error:
error[E0308]: `match` arms have incompatible types
--> src/main.rs:15:18
|
13 | / match s {
14 | | -1 => nom::combinator::success(None),
| | ------------------------------ this is found to be of type `impl Fn<(_,)>`
15 | | _ => nom::combinator::map(take(s as u16), Some)
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
16 | | }
| |_________- `match` arms have incompatible types
|
::: /Users/dfarr/.cargo/registry/src/github.com-1ecc6299db9ec823/nom-6.0.1/src/combinator/mod.rs:74:64
|
74 | pub fn map<I, O1, O2, E, F, G>(mut first: F, mut second: G) -> impl FnMut(I) -> IResult<I, O2, E>
| ---------------------------------- the found opaque type
|
= note: expected type `impl Fn<(_,)>`
found opaque type `impl FnMut<(_,)>`
= note: distinct uses of `impl Trait` result in different opaque types
I can see that nom::combinator::success
does indeed have a return type of impl Fn(I) -> ...
, and nom::combinator::map
returns impl FnMut(I) -> ...
. Is there a more idiomatic way of using nom where these combinators can be used together in this manner?
Upvotes: 4
Views: 488
Reputation: 2821
This may do the trick (it compiles). Here, nom::combinator::map
applies the transform to the successful result value and re-wraps it in the Ok
variant. Incidentally, there is also a nom::Parser<T>::map
which seems to implement the Map
iterator.
use nom::combinator::map;
use nom::number::complete::be_i16;
fn parse(i: &[u8]) -> nom::IResult<&[u8], Option<i16>> {
let f = |s: i16| if s == -1 { None } else { Some(s) };
map(be_i16, f)(i)
}
Upvotes: 1