Skip to content

Prefer parse implementation from Parse trait #69

@mauricelam

Description

@mauricelam

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions