parsr 1.0.4

a libary for simple parsing
use crate::{
    input::{Input, InvalidUtf8, ReadError},
    parse::{IsParse, Parse, ParseError},
    trim::Trim,
};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ParseIterError<E> {
    InvalidUtf8(InvalidUtf8),
    Error(E),
}

impl<E> From<InvalidUtf8> for ParseIterError<E> {
    #[inline(always)]
    fn from(value: InvalidUtf8) -> Self {
        ParseIterError::InvalidUtf8(value)
    }
}

impl<E> ParseIterError<E> {
    #[inline(always)]
    pub const fn new(err: E) -> Self {
        ParseIterError::Error(err)
    }
}

#[derive(Debug)]
pub struct ParseIter<'a, I: ?Sized + Input, T: Trim, P: Parse> {
    input: &'a mut I,
    trimmer: T,
    parser: P,
}

impl<'a, I: ?Sized + Input, T: Trim + Clone, P: Parse> ParseIter<'a, I, T, P> {
    #[inline(always)]
    pub fn new(input: &'a mut I, trimmer: T, parser: P) -> Result<Self, InvalidUtf8> {
        if let Err(ReadError::InvalidUtf8(err)) = trimmer.clone().trim(input) {
            return Err(err);
        }

        Ok(Self {
            input,
            trimmer,
            parser,
        })
    }
}

impl<
    'a,
    I: ?Sized + Input,
    T: Trim + Clone,
    P: for<'s> IsParse<'s, Output = O, Error = E> + Clone,
    O,
    E,
> Iterator for ParseIter<'a, I, T, P>
{
    type Item = Result<O, ParseIterError<E>>;

    fn next(&mut self) -> Option<Result<O, ParseIterError<E>>> {
        if self.input.is_eof() {
            return None;
        }

        let output = match self.parser.clone().parse(self.input) {
            Ok(output) => output,
            Err(ParseError::ReadError(ReadError::EOF)) => return None,
            Err(ParseError::ReadError(ReadError::InvalidUtf8(err))) => {
                return Some(Err(ParseIterError::InvalidUtf8(err)));
            }
            Err(ParseError::Error(err)) => return Some(Err(ParseIterError::Error(err))),
        };

        if let Err(ReadError::InvalidUtf8(err)) = self.trimmer.clone().trim(self.input) {
            return Some(Err(ParseIterError::InvalidUtf8(err)));
        }

        Some(Ok(output))
    }
}