manger 0.1.1

A performant, low-level, lightweight and intuitive combinatoric parser library
Documentation
use crate::Consumable;
use crate::ConsumeError;

impl<T: Consumable> Consumable for Option<T> {
    fn consume_from(source: &str) -> Result<(Option<T>, &str), ConsumeError> {
        Ok(match <T>::consume_from(source) {
            Err(_) => (None, source),
            Ok((item, unconsumed)) => (Some(item), unconsumed),
        })
    }
}

impl<T: Consumable> Consumable for Box<T> {
    fn consume_from(s: &str) -> Result<(Box<T>, &str), ConsumeError> {
        <T>::consume_from(s).map(|(item, unconsumed)| (Box::new(item), unconsumed))
    }
}

impl<T: Consumable> Consumable for Vec<T> {
    fn consume_from(s: &str) -> Result<(Vec<T>, &str), ConsumeError> {
        let mut sequence = Vec::new();
        let mut last_unconsumed = s;

        while let Ok((extra_coordinate_pair, unconsumed)) = T::consume_from(last_unconsumed) {
            sequence.push(extra_coordinate_pair);
            last_unconsumed = unconsumed;
        }

        Ok((sequence, last_unconsumed))
    }
}

use crate::ConsumeSource;

macro_rules! consume_concat {
    ( $( $type_ident:ident ),+ ) => {
        impl<$( $type_ident ),+> Consumable for ($( $type_ident ),+)
        where
            $( $type_ident: Consumable ),+
        {
            fn consume_from(source: &str) -> Result<(Self, &str), ConsumeError> {
                let mut unconsumed = source;
                let mut offset = 0;

                Ok(
                    (
                        (
                            $(
                                unconsumed
                                    .mut_consume_by::<$type_ident>()
                                    .map_err( |err| { err.offset(offset) } )
                                    .map( |(item, by)| { offset += by; item } )?
                            ),+
                        ),
                        unconsumed
                    )
                )
            }
        }
    };
}

consume_concat!(A, B);
consume_concat!(A, B, C);
consume_concat!(A, B, C, D);
consume_concat!(A, B, C, D, E);
consume_concat!(A, B, C, D, E, F);
consume_concat!(A, B, C, D, E, F, G);
consume_concat!(A, B, C, D, E, F, G, H);
consume_concat!(A, B, C, D, E, F, G, H, I);
consume_concat!(A, B, C, D, E, F, G, H, I, J);