chasa 0.5.0

A parser combinator focused on rollback/commit, streaming inputs, and composable method chains.
Documentation
use crate::back::{Back, Front};
use crate::input::{Counter, Input, SeqInput};

pub struct WithCounter<I, C> {
    pub input: I,
    pub counter: C,
}

impl<I, C> WithCounter<I, C> {
    pub fn inner(&self) -> &I {
        &self.input
    }

    pub fn inner_mut(&mut self) -> &mut I {
        &mut self.input
    }

    pub fn counter(&self) -> &C {
        &self.counter
    }
}

impl<I, C> Back for WithCounter<I, C>
where
    I: Input,
    C: Counter<I::Item>,
{
    type Checkpoint = (I::Checkpoint, C::Checkpoint);

    fn checkpoint(&mut self) -> Self::Checkpoint {
        (self.input.checkpoint(), self.counter.checkpoint())
    }

    fn rollback(&mut self, checkpoint: Self::Checkpoint) {
        self.input.rollback(checkpoint.0);
        self.counter.rollback(checkpoint.1);
    }
}

impl<I, C> Input for WithCounter<I, C>
where
    I: Input,
    C: Counter<I::Item>,
{
    type Item = I::Item;
    type Pos = C::Pos;

    fn index(&self) -> u64 {
        self.input.index()
    }

    fn pos(&self) -> Self::Pos {
        self.counter.pos()
    }

    fn next(&mut self) -> Option<Self::Item> {
        let item = self.input.next()?;
        self.counter.feed(item.clone());
        Some(item)
    }

    fn commit(&mut self) {
        self.input.commit();
    }
}

impl<I, C> SeqInput for WithCounter<I, C>
where
    I: SeqInput,
    C: Counter<I::Item>,
{
    type Seq = I::Seq;

    fn seq(start: Self::Checkpoint, end: Self::Checkpoint) -> I::Seq {
        I::seq(start.0, end.0)
    }
}

impl<I, C> Front for WithCounter<I, C>
where
    I: Input + Front,
    C: Counter<I::Item> + Front,
{
}