chomp1 0.3.4

A fast monadic-style parser combinator designed to work on stable Rust.
Documentation
//! Support for the tendril type, this is probably a bad idea since it is
//! actually not a rope and will probably cause excessive reallocations while
//! parsing.

use std::mem;

use tendril::ByteTendril;

use crate::primitives::Guard;
use crate::types::{Buffer, Input};

// TODO: Impl for more than byte tendril
impl Input for ByteTendril {
    type Buffer = ByteTendril;
    type Marker = ByteTendril;
    type Token = u8;

    #[inline]
    fn _peek(&mut self, _g: Guard) -> Option<Self::Token> {
        self.as_ref().first().cloned()
    }

    #[inline]
    fn _pop(&mut self, _g: Guard) -> Option<Self::Token> {
        if self.len32() > 0 {
            let t = self.as_ref()[0];

            self.pop_front(1);

            Some(t)
        } else {
            None
        }
    }

    #[inline]
    fn _consume(&mut self, _g: Guard, n: usize) -> Option<Self::Buffer> {
        if n > self.len32() as usize {
            None
        } else {
            let b = self.subtendril(0, n as u32);

            self.pop_front(n as u32);

            Some(b)
        }
    }

    #[inline]
    fn _consume_while<F>(&mut self, g: Guard, mut f: F) -> Self::Buffer
    where
        F: FnMut(Self::Token) -> bool,
    {
        match self.iter().position(|c| !f(*c)) {
            Some(n) => {
                let b = self.subtendril(0, n as u32);

                self.pop_front(n as u32);

                b
            }
            None => self._consume_remaining(g),
        }
    }

    #[inline]
    fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer {
        // Just the tendril analogue of the slice version:
        m.subtendril(0, m.len32() - self.len32())
    }

    #[inline]
    fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer {
        let b = self.subtendril(0, 0);

        mem::replace(self, b)
    }

    #[inline]
    fn _mark(&self, _g: Guard) -> Self::Marker {
        self.clone()
    }

    #[inline]
    fn _restore(self, _g: Guard, m: Self::Marker) -> Self {
        m
    }
}

impl Buffer for ByteTendril {
    type Token = u8;

    fn fold<B, F>(self, init: B, f: F) -> B
    where
        F: FnMut(B, Self::Token) -> B,
    {
        (&self[..]).iter().cloned().fold(init, f)
    }

    fn iterate<F>(&self, mut f: F)
    where
        F: FnMut(Self::Token),
    {
        for i in (&self[..]).iter().cloned() {
            f(i)
        }
    }

    fn len(&self) -> usize {
        self.len32() as usize
    }

    #[cfg(feature = "std")]
    fn to_vec(&self) -> Vec<Self::Token> {
        (&self[..]).to_vec()
    }

    #[cfg(feature = "std")]
    fn into_vec(self) -> Vec<Self::Token> {
        (&self[..]).to_vec()
    }
}

#[cfg(test)]
mod test {
    use tendril::Tendril;

    #[test]
    fn basic() {
        use crate::ascii::decimal;
        use crate::primitives::IntoInner;

        assert_eq!(
            decimal(Tendril::from_slice(&b"123"[..])).into_inner(),
            (Tendril::from_slice(&b""[..]), Ok(123i32))
        );
    }

    #[test]
    fn primitives() {
        crate::types::test::run_primitives_test(Tendril::from_slice(&b"abc"[..]), |x| x);
    }
}