-
Notifications
You must be signed in to change notification settings - Fork 18
Description
If a type both implements the Parse trait, and has another parse function implemented directly, the generated code in nom-derive seems to prefer the direct parse function, even if the signature of it doesn't match.
Context
I was trying to parse a value-only enum, but with a twist that the remaining values should all go into an Unassigned enum that stores the value. I am using the Selector derived parse, but also provide a nom_derive::Parse trait implementation. The code looks roughly like the following:
#[derive(Nom, Debug, PartialEq, Eq)]
#[nom(Selector = "u32")]
#[repr(u32)]
pub enum DatalinkType {
#[nom(Selector = "1001")]
UnencapsulatedHci = 1001,
#[nom(Selector = "1002")]
HciUart = 1002,
#[nom(Selector = "1005..=u32::MAX")]
Unassigned(u32),
}
impl<'a> Parse<&'a [u8]> for DatalinkType {
fn parse(i: &'a [u8]) -> nom::IResult<&'a [u8], Self, nom::error::Error<&'a [u8]>> {
u32::parse_be(i)
.and_then(|(rem, value)| DatalinkType::parse(i, value).map(|(_, dlt)| (rem, dlt)))
}
}However, when nesting this inside another struct, the generated code fails, because the parse function it found expects two arguments, instead of one, even though I implemented the Parse trait that has the correct signature.
#[derive(Nom, Debug)]
pub struct FileHeader<'a> {
#[nom(Verify = "*version == 1")]
pub version: u32,
/// The datalink type for the packet records that follow.
pub datalink_type: DatalinkType,
}I had to add #[nom(Parse = "<DatalinkType as Parse<_>>::parse")] to get it to use the parse trait. Not sure if you would consider that a bug, but that behavior felt surprising to me, and I think it would be nice if it prefers the implementation from the Parse trait rather than trying to use an incompatible one.
My complete code is here: https://github.com/mauricelam/btsnoop-rs/pull/12/files