The nom custom error example gave me a bit of trouble until Geal was kind enough to point out a couple options.
tldr you need to implement ParseError
and From
for your type, then use .map_err(Err::convert)
because ?
on it's own doesn't work without type specialization.
Here's a custom error implementation.
#[derive(Debug, PartialEq)]pub enum MDXError<I> {MyError,Nom(I, ErrorKind),}impl<'a> From<(&'a [u8], ErrorKind)> for MDXError<&'a [u8]> {fn from((i, ek): (&'a [u8], ErrorKind)) -> Self {MDXError::Nom(i, ek)}}impl<I> ParseError<I> for MDXError<I> {fn from_error_kind(input: I, kind: ErrorKind) -> Self {MDXError::Nom(input, kind)}fn append(_: I, _: ErrorKind, other: Self) -> Self {other}}
And the program that uses it:
use nom::{bytes::complete,character::*,error::{ErrorKind, ParseError},Err::Error,IResult, *,};// The datatypes we're parsing into#[derive(Debug, PartialEq, Eq)]struct ATXHeading<'a> {level: usize,value: &'a [u8],}struct SEHeading {}enum Heading<'a> {ATXHeading(&'a ATXHeading<'a>),SEHeading(SEHeading),}// A couple of named parsers, built with macrosnamed!(hashtags, is_a!("#"));named!(alpha, take_while!(is_alphanumeric));named!(spaces, take_while!(is_space));// parsing Markdown ATX headings, for which too many #'s failsfn atx_heading(input: &[u8],) -> IResult<&[u8], ATXHeading, MDXError<&[u8]>> {let (input, hashes) =hashtags(input).map_err(Err::convert)?;if hashes.len() > 6 {return Err(Error(MDXError::MyError));}let (input, _) = spaces(input).map_err(Err::convert)?;let (input, val) = nom::bytes::complete::take_while(is_alphanumeric,)(input)?;Ok((input,ATXHeading {level: hashes.len(),value: val,},))}// a test to run to check if it's working#[test]fn parse_mdx() {assert_eq!(atx_heading(b"# boop"),Ok(("".as_bytes(),ATXHeading {level: 1,value: b"boop"})));}
Note specifically the use of the type signature for atx_heading
:
fn atx_heading(input: &[u8]) -> IResult<&[u8], ATXHeading, MDXError<&[u8]>> {
and the ability to return the custom error variant:
if hashes.len() > 6 {return Err(Error(MDXError::MyError));}