esdl 0.6.0

Event-sourcing Schema Definition Language parser
Documentation
use nom::{
    branch::alt,
    character::complete::{multispace0, multispace1},
    combinator::{map, value},
    multi::many0,
    sequence::delimited,
};
use semver::Version;

use super::{
    aggregate::{parse_aggregate, Aggregate},
    event::{parse_event, Event},
    types::{parse_custom_type, CustomType},
    version::parse_version,
    IResult, Span,
};

#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Schema<'i> {
    pub versions: Vec<Version>,
    pub aggregates: Vec<Aggregate<'i>>,
    pub events: Vec<Event<'i>>,
    pub types: Vec<CustomType<'i>>,
}

#[derive(Clone, Debug, PartialEq)]
enum SchemaType<'i> {
    Aggregate(Aggregate<'i>),
    Event(Event<'i>),
    CustomType(CustomType<'i>),
    Version(Version),
    Noop,
}

pub fn parse_schema(input: Span) -> IResult<Span, Schema> {
    let (tail, schema_types) = delimited(
        multispace0,
        many0(alt((
            value(SchemaType::Noop, multispace1),
            map(parse_aggregate, SchemaType::Aggregate),
            map(parse_version, SchemaType::Version),
            map(parse_event, SchemaType::Event),
            map(parse_custom_type, SchemaType::CustomType),
        ))),
        multispace0,
    )(input)?;

    let schema = schema_types
        .into_iter()
        .fold(Schema::default(), |mut acc, item| {
            match item {
                SchemaType::Aggregate(aggregate) => acc.aggregates.push(aggregate),
                SchemaType::Event(event) => acc.events.push(event),
                SchemaType::CustomType(ty) => acc.types.push(ty),
                SchemaType::Version(version) => acc.versions.push(version),
                SchemaType::Noop => {}
            }

            acc
        });

    Ok((tail, schema))
}