esdl 0.6.0

Event-sourcing Schema Definition Language parser
Documentation
use std::ops::RangeFrom;

use nom::{
    branch::alt,
    character::complete::{char, multispace0, newline, space0, space1},
    combinator::map,
    error::ParseError,
    multi::separated_list0,
    sequence::{delimited, pair, preceded, separated_pair, tuple},
    AsChar, IResult, InputIter, InputLength, InputTakeAtPosition, Parser, Slice,
};
use nom_supreme::tag::complete::tag;

use super::{
    event::{parse_field, Field},
    ident::parse_camel_ident,
    Span,
};

pub fn multinewline1<T, E: ParseError<T>>(input: T) -> IResult<T, (T, char, T), E>
where
    T: InputTakeAtPosition + InputIter + Slice<RangeFrom<usize>> + Clone,
    <T as InputTakeAtPosition>::Item: AsChar + Clone,
    <T as InputIter>::Item: AsChar + Clone,
{
    tuple((space0, newline, multispace0))(input)
}

pub fn delimited_multiline_list0<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
    first: impl Fn() -> F,
    second: G,
    third: impl Fn() -> H,
) -> impl FnMut(I) -> IResult<I, Vec<O2>, E>
where
    I: InputTakeAtPosition + InputIter + InputLength + Slice<RangeFrom<usize>> + Clone,
    <I as InputTakeAtPosition>::Item: AsChar + Clone,
    <I as InputIter>::Item: AsChar + Clone,
    F: Parser<I, O1, E>,
    G: Parser<I, O2, E>,
    H: Parser<I, O3, E>,
{
    alt((
        map(tuple((first(), multispace0, third())), |_| Vec::new()),
        delimited(
            pair(first(), multinewline1),
            separated_list0(multinewline1, second),
            pair(multinewline1, third()),
        ),
    ))
}

pub fn keyword_ident_structure<'i>(
    keyword: &'static str,
) -> impl FnMut(Span<'i>) -> super::IResult<Span<'i>, (Span<'i>, Vec<Field<'i>>)> {
    let ident_parser = preceded(pair(tag(keyword), space1), parse_camel_ident);
    let fields_parser = delimited_multiline_list0(|| char('{'), parse_field, || char('}'));

    separated_pair(ident_parser, multispace0, fields_parser)
}