nom-derive
now generates an implementation of the Parse
trait when possible (when there are no selector or extra args).
The methods parse_be
and parse_le
are both generated (unless endianness is fixed), and will recursively call
similarly named methods in child objects.
There are two possibilities:
- the object can be represented (and parsed) differently, depending on the endianness
- the object always have the same representation, and does not depend on the endianness (most common case)
If the object always have the same parsing, then the endianness should be fixed. This can be done by using the NomBE
or NomLE
custom derive instead of Nom
, or by applying the BigEndian
or LittleEndian
top-level attributes.
If the object can has different representations, then the Nom
custom derive should be used.
Additionally, calling the parsing methods requires the Parse
trait, so callers must import it:
use nom_derive::Parse;
If you have manually implemented or called parse
methods, you should convert them to implementations of the Parse
trait.
There are two possibilities:
- object does not depend on endianness: only the
parse
method of the trait should be implemented - object has different representations: both
parse_be
andparse_le
should be implemented
For example:
impl OspfLinkStateAdvertisement {
pub fn parse(input: &[u8]) -> IResult<&[u8], OspfLinkStateAdvertisement> {
...
}
}
An OSPF packet is always represented as big-endian, so this becomes:
impl<'a> Parse<&'a [u8]> for OspfLinkStateAdvertisement {
fn parse(input: &'a [u8]) -> IResult<&'a [u8], OspfLinkStateAdvertisement> {
...
}
}
In most cases, that means only changing the impl
statement and removing the pub
keyword.
The trait Parse
has been introduced in 0.8.0. This trait is used to provide a common interface, and default implementations for primitive types.
As a consequence, it must be imported as well as the custom derive attribute:
use nom_derive::Nom
now often becomes use nom_derive::{Nom, Parse}
or use nom_derive::*
.
nom-derive
will now apply attributes in order of appearance to build a parse tree.
For example, if specifying both Count
and Cond
attributes:
Count="4", Cond(a > 0)
is built asCount(4, Cond(a> 0, T::Parse))
, which means a typeVec<Option<T>>
is expectedCond(a > 0), Count="4"
is built asCond(a> 0, Count(4, T::Parse))
, which means a typeOption<Vec<T>>
is expected