nom-errors 0.0.13

Strong-typed errors support for nom parser combinator library.
Documentation
#![feature(never_type)]

#![deny(warnings)]
#![allow(clippy::too_many_arguments)]

use nom::{self, IResult, InputLength};
use nom::error::ParseError;
use paste::paste;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum NomErr<E, F> {
    Error(E),
    Failure(F),
}

impl<E, F> NomErr<E, F> {
    pub fn map_err<X>(self, f: impl FnOnce(E) -> X) -> NomErr<X, F> {
        match self {
            NomErr::Error(e) => NomErr::Error(f(e)),
            NomErr::Failure(e) => NomErr::Failure(e),
        }
    }

    pub fn map_fail<X>(self, f: impl FnOnce(F) -> X) -> NomErr<E, X> {
        match self {
            NomErr::Error(e) => NomErr::Error(e),
            NomErr::Failure(e) => NomErr::Failure(f(e)),
        }
    }
}

impl<F> NomErr<!, F> {
    pub fn any_err<E>(self) -> NomErr<E, F> {
        self.map_err(|x| x)
    }
}

impl<E> NomErr<E, !> {
    pub fn any_fail<F>(self) -> NomErr<E, F> {
        self.map_fail(|x| x)
    }
}

impl<E> NomErr<E, E> {
    pub fn fail(self) -> NomErr<!, E> {
        match self {
            NomErr::Error(e) => NomErr::Failure(e),
            NomErr::Failure(e) => NomErr::Failure(e),
        }
    }
}

impl<I, E, F> ParseError<I> for NomErr<E, F> {
    fn from_error_kind(_input: I, _kind: nom::error::ErrorKind) -> Self { panic!() }

    fn append(_input: I, _kind: nom::error::ErrorKind, _other: Self) -> Self { panic!() }

    fn or(self, _other: Self) -> Self { panic!() }

    fn from_char(_input: I, _: char) -> Self { panic!() }
}

pub type NomRes<I, O, E, F> = IResult<I, O, NomErr<E, F>>;

pub fn parser_from_result<I, O, E, F>(r: Result<(I, O), NomErr<E, F>>) -> NomRes<I, O, E, F> {
    match r {
        Ok((i, o)) => Ok((i, o)),
        Err(NomErr::Error(e)) => Err(nom::Err::Error(NomErr::Error(e))),
        Err(NomErr::Failure(f)) => Err(nom::Err::Failure(NomErr::Failure(f))),
    }
}

pub fn result_from_parser<I, O, E, F>(r: NomRes<I, O, E, F>) -> Result<(I, O), NomErr<E, F>> {
    match r {
        Ok((i, o)) => Ok((i, o)),
        Err(nom::Err::Error(NomErr::Error(e))) => Err(NomErr::Error(e)),
        Err(nom::Err::Failure(NomErr::Failure(e))) => Err(NomErr::Failure(e)),
        _ => panic!()
    }
}

pub fn map_err<I: Clone, O, E, F, X>(
    mut parser: impl FnMut(I) -> NomRes<I, O, E, F>,
    mut f: impl FnMut(E, I) -> X
) -> impl FnMut(I) -> NomRes<I, O, X, F> {
    move |input: I| {
        parser_from_result(result_from_parser(parser(input.clone())).map_err(|e| e.map_err(|e| f(e, input))))
    }
}

pub fn any_err<I: Clone, O, F, X>(
    mut parser: impl FnMut(I) -> NomRes<I, O, !, F>,
) -> impl FnMut(I) -> NomRes<I, O, X, F> {
    move |input: I| parser_from_result(result_from_parser(parser(input)).map_err(|e| e.any_err()))
}

pub fn uni_err_no_fail<I, O>(
    mut parser: impl FnMut(I) -> IResult<I, O, ()>
) -> impl FnMut(I) -> NomRes<I, O, (), !> {
    move |input: I| parser_from_result(match parser(input) {
        Ok((i, o)) => Ok((i, o)),
        Err(nom::Err::Error(())) => Err(NomErr::Error(())),
        _ => panic!(),
    })
}

pub fn seq_2<I, O1, O2, E, F>(
    mut a: impl FnMut(I) -> NomRes<I, O1, E, F>,
    mut b: impl FnMut(I) -> NomRes<I, O2, E, F>,
) -> impl FnMut(I) -> NomRes<I, (O1, O2), E, F> {
    move |input: I| parser_from_result(match result_from_parser(a(input)) {
        Err(e) => Err(e),
        Ok((input, a)) => result_from_parser(b(input)).map(|(i, b)| (i, (a, b)))
    })
}

macro_rules! seq_n {
    (
        $n:literal; $m:literal: $($i:literal),+
    ) => {
        paste! {
            pub fn [< seq_ $n >] <I, $( [< O $i >] , )+ [< O $n >] , E, F>(
                $(
                    [< parser_ $i >] : impl FnMut(I) -> NomRes<I, [< O $i >] , E, F>,
                )+
                [< parser_ $n >] : impl FnMut(I) -> NomRes<I, [< O $n >] , E, F>,
            ) -> impl FnMut(I) -> NomRes<I, ($( [< O $i >], )+ [< O $n >] ), E, F> {
                map(
                    seq_2( [< seq_ $m >] ($( [< parser_ $i >] ),+), [< parser_ $n >] ),
                    |(($( [< r $i >] ),+), [< r $n >] )| ($( [< r $i >] ,)+ [< r $n >] )
                )
            }
        }
    };
}

seq_n!(3; 2: 1, 2);
seq_n!(4; 3: 1, 2, 3);
seq_n!(5; 4: 1, 2, 3, 4);
seq_n!(6; 5: 1, 2, 3, 4, 5);
seq_n!(7; 6: 1, 2, 3, 4, 5, 6);
seq_n!(8; 7: 1, 2, 3, 4, 5, 6, 7);
seq_n!(9; 8: 1, 2, 3, 4, 5, 6, 7, 8);
seq_n!(10; 9: 1, 2, 3, 4, 5, 6, 7, 8, 9);
seq_n!(11; 10: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
seq_n!(12; 11: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
seq_n!(13; 12: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
seq_n!(14; 13: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
seq_n!(15; 14: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

pub fn alt_2<I: Clone, O, E, F, X1>(
    mut parser_1: impl FnMut(I) -> NomRes<I, O, X1, F>,
    mut parser: impl FnMut(I) -> NomRes<I, O, E, F>,
) -> impl FnMut(I) -> NomRes<I, O, E, F> {
    move |input: I| parser_from_result(match result_from_parser(parser_1(input.clone())) {
        Ok(r) => Ok(r),
        Err(NomErr::Failure(f)) => Err(NomErr::Failure(f)),
        Err(NomErr::Error(_)) => result_from_parser(parser(input)),
    })
}

macro_rules! alt_n {
    (
        $n:literal; $m:literal: $($i:literal),+
    ) => {
        paste! {
            pub fn [< alt_ $n >] <I: Clone, O, E, F, $( [< X $i >]),+>(
                $(
                    [< parser_ $i >] : impl FnMut(I) -> NomRes<I, O, [< X $i >], F>,
                )+
                parser: impl FnMut(I) -> NomRes<I, O, E, F>,
            ) -> impl FnMut(I) -> NomRes<I, O, E, F> {
                alt_2( [< alt_ $m >] ($( [< parser_ $i >] ),+), parser)
            }
        }
    };
}

alt_n!(3; 2: 1, 2);
alt_n!(4; 3: 1, 2, 3);
alt_n!(5; 4: 1, 2, 3, 4);
alt_n!(6; 5: 1, 2, 3, 4, 5);
alt_n!(7; 6: 1, 2, 3, 4, 5, 6);
alt_n!(8; 7: 1, 2, 3, 4, 5, 6, 7);
alt_n!(9; 8: 1, 2, 3, 4, 5, 6, 7, 8);
alt_n!(10; 9: 1, 2, 3, 4, 5, 6, 7, 8, 9);
alt_n!(11; 10: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
alt_n!(12; 11: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
alt_n!(13; 12: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
alt_n!(14; 13: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
alt_n!(15; 14: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

pub fn many0<I: Clone + InputLength, O, E, F>(
    mut parser: impl FnMut(I) -> NomRes<I, O, E, F>
) -> impl FnMut(I) -> NomRes<I, Vec<O>, !, F> {
    move |mut input: I| parser_from_result({
        let mut r = Vec::new();
        loop {
            if input.input_len() == 0 { break Ok(()); }
            match result_from_parser(parser(input.clone())) {
                Ok((i, o)) => {
                    assert_ne!(i.input_len(), input.input_len(), "invalid many0 parser");
                    input = i;
                    r.push(o);
                },
                Err(NomErr::Failure(f)) => break Err(NomErr::Failure(f)),
                Err(NomErr::Error(_)) => break Ok(()),
            }
        }.map(|()| (input, r))
    })
}

pub fn map<I, O, E, F, X>(
    mut parser: impl FnMut(I) -> NomRes<I, O, E, F>,
    mut f: impl FnMut(O) -> X
) -> impl FnMut(I) -> NomRes<I, X, E, F> {
    move |input: I| parser_from_result(result_from_parser(parser(input)).map(|(i, r)| (i, f(r))))
}

pub fn map_res<I, O, E, F, X>(
    mut parser: impl FnMut(I) -> NomRes<I, O, E, F>,
    mut f: impl FnMut(O) -> Result<X, E>
) -> impl FnMut(I) -> NomRes<I, X, E, F> {
    move |input: I| parser_from_result(result_from_parser(parser(input)).and_then(|(i, r)|
        f(r).map_err(NomErr::Error).map(|r| (i, r))
    ))
}

pub fn all_consuming<I: InputLength, O, E, F>(
    mut parser: impl FnMut(I) -> NomRes<I, O, E, F>,
    mut f: impl FnMut(I) -> NomErr<E, F>,
) -> impl FnMut(I) -> NomRes<I, O, E, F> {
    move |input: I| parser_from_result(result_from_parser(parser(input)).and_then(|(i, r)|
        if i.input_len() == 0 { Ok((i, r)) } else { Err(f(i)) }
    ))
}

pub fn flat_map<I, O1, O2, E, F, P: FnMut(I) -> NomRes<I, O2, E, F>>(
    mut parser: impl FnMut(I) -> NomRes<I, O1, E, F>,
    mut f: impl FnMut(O1) -> P,
) -> impl FnMut(I) -> NomRes<I, O2, E, F> {
    move |input: I| parser_from_result(match result_from_parser(parser(input)) {
        Err(e) => Err(e),
        Ok((i, r1)) => result_from_parser(f(r1)(i))
    })
}

pub fn count<I: Clone + PartialEq, O, E, F>(
    mut parser: impl FnMut(I) -> NomRes<I, O, E, F>,
    count: usize
) -> impl FnMut(I) -> NomRes<I, Vec<O>, E, F> {
    move |mut input: I| parser_from_result((|| {
        let mut r = Vec::new();
        for _ in 0 .. count {
            let (i, o) = result_from_parser(parser(input.clone()))?;
            input = i;
            r.push(o);
        }
        Ok((input, r))
    })())
}

pub mod bytes {
    use super::*;
    use nom::{Compare, InputIter, InputLength, InputTake, Slice};
    use std::ops::RangeFrom;

    pub fn le_u8<I: Slice<RangeFrom<usize>> + InputIter<Item=u8> + InputLength>() -> impl FnMut(I) -> NomRes<I, u8, (), !> {
        uni_err_no_fail(nom::number::complete::le_u8)
    }

    pub fn le_u16<I: Slice<RangeFrom<usize>> + InputIter<Item=u8> + InputLength>() -> impl FnMut(I) -> NomRes<I, u16, (), !> {
        uni_err_no_fail(nom::number::complete::le_u16)
    }

    pub fn le_u32<I: Slice<RangeFrom<usize>> + InputIter<Item=u8> + InputLength>() -> impl FnMut(I) -> NomRes<I, u32, (), !> {
        uni_err_no_fail(nom::number::complete::le_u32)
    }

    pub fn le_i8<I: Slice<RangeFrom<usize>> + InputIter<Item=u8> + InputLength>() -> impl FnMut(I) -> NomRes<I, i8, (), !> {
        uni_err_no_fail(nom::number::complete::le_i8)
    }

    pub fn le_i16<I: Slice<RangeFrom<usize>> + InputIter<Item=u8> + InputLength>() -> impl FnMut(I) -> NomRes<I, i16, (), !> {
        uni_err_no_fail(nom::number::complete::le_i16)
    }

    pub fn le_i32<I: Slice<RangeFrom<usize>> + InputIter<Item=u8> + InputLength>() -> impl FnMut(I) -> NomRes<I, i32, (), !> {
        uni_err_no_fail(nom::number::complete::le_i32)
    }

    pub fn tag<T: Clone + InputLength, I: InputTake + Compare<T>>(
        tag: T
    ) -> impl FnMut(I) -> NomRes<I, I, (), !> {
        uni_err_no_fail(nom::bytes::complete::tag(tag))
    }

    pub fn take<I: InputIter + InputTake>(
        count: usize
    ) -> impl FnMut(I) -> NomRes<I, I, (), !> {
        uni_err_no_fail(nom::bytes::complete::take(count))
    }

    pub fn take_all<I: InputLength + InputTake>() -> impl FnMut(I) -> NomRes<I, I, !, !> {
        move |input: I| {
            let input_len = input.input_len();
            Ok(input.take_split(input_len))
        }
    }
}