parsr 1.0.4

a libary for simple parsing
use crate::input::{Input, ReadError};

mod parse_iter;
mod parse_mut_borrowed_iter;
mod parse_mut_iter;
pub use parse_iter::{ParseIter, ParseIterError};
pub use parse_mut_borrowed_iter::ParseMutBorrowedIter;
pub use parse_mut_iter::ParseMutIter;

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

impl ParseError<!> {
    #[inline(always)]
    pub fn unwrap_infallible(self) -> ReadError {
        match self {
            ParseError::ReadError(err) => err,
        }
    }
}

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

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

pub trait IsParse<'a> {
    type Output;
    type Error;

    fn __parse<I: ?Sized + Input>(
        self,
        input: &'a mut I,
    ) -> Result<Self::Output, ParseError<Self::Error>>;
}

pub trait Parse: for<'a> IsParse<'a> + Sized {
    #[inline(always)]
    fn parse<'a, I: ?Sized + Input>(
        self,
        input: &'a mut I,
    ) -> Result<ParseOutput<'a, Self>, ParseError<ParseErrorOutput<'a, Self>>> {
        self.__parse(input)
    }
}
impl<P: for<'a> IsParse<'a>> Parse for P {}

pub type ParseOutput<'a, P> = <P as IsParse<'a>>::Output;
pub type ParseErrorOutput<'a, P> = <P as IsParse<'a>>::Error;

pub trait ParseExt: Parse {
    #[inline(always)]
    fn mapped<M: Mapping<Self>>(self, mapping: M) -> MappedParse<Self, M> {
        MappedParse {
            parse: self,
            mapping,
        }
    }

    #[inline(always)]
    fn mapped_mut<M: MappingMut<Self>>(self, mapping: M) -> MappedMutParse<Self, M> {
        MappedMutParse {
            parse: self,
            mapping,
        }
    }
}
impl<P: Parse> ParseExt for P {}

pub trait IsMapping<'a, P: IsParse<'a>> {
    type Output;

    fn __map(self, output: ParseOutput<'a, P>) -> Self::Output;
}

impl<'a, P: IsParse<'a>, F: FnOnce(ParseOutput<'a, P>) -> O, O> IsMapping<'a, P> for F {
    type Output = O;

    #[inline(always)]
    fn __map(self, output: ParseOutput<'a, P>) -> Self::Output {
        self(output)
    }
}

pub trait Mapping<P: Parse>: for<'a> IsMapping<'a, P> + Sized {
    #[inline(always)]
    fn map<'a>(self, output: ParseOutput<'a, P>) -> MappingOutput<'a, P, Self> {
        self.__map(output)
    }
}
impl<P: Parse, M: for<'a> IsMapping<'a, P>> Mapping<P> for M {}

pub type MappingOutput<'a, P, M> = <M as IsMapping<'a, P>>::Output;

#[derive(Debug, Clone, Copy)]
pub struct MappedParse<P: Parse, M: Mapping<P>> {
    pub parse: P,
    pub mapping: M,
}

impl<'a, P: Parse, M: Mapping<P>> IsParse<'a> for MappedParse<P, M> {
    type Output = MappingOutput<'a, P, M>;
    type Error = ParseErrorOutput<'a, P>;

    #[inline(always)]
    fn __parse<I: ?Sized + Input>(
        self,
        input: &'a mut I,
    ) -> Result<Self::Output, ParseError<Self::Error>> {
        self.parse
            .parse(input)
            .map(|output| self.mapping.map(output))
    }
}

pub trait IsMappingMut<'a, P: IsParse<'a>> {
    type Output;

    fn __map_mut(&mut self, output: ParseOutput<'a, P>) -> Self::Output;
}

impl<'a, P: IsParse<'a>, F: FnMut(ParseOutput<'a, P>) -> O, O> IsMappingMut<'a, P> for F {
    type Output = O;

    #[inline(always)]
    fn __map_mut(&mut self, output: ParseOutput<'a, P>) -> Self::Output {
        self(output)
    }
}

pub trait MappingMut<P: Parse>: for<'a> IsMappingMut<'a, P> + Sized {
    #[inline(always)]
    fn map_mut<'a>(&mut self, output: ParseOutput<'a, P>) -> MappingMutOutput<'a, P, Self> {
        self.__map_mut(output)
    }
}
impl<P: Parse, M: for<'a> IsMappingMut<'a, P>> MappingMut<P> for M {}

pub type MappingMutOutput<'a, P, M> = <M as IsMappingMut<'a, P>>::Output;

#[derive(Debug)]
pub struct MappedMutParse<P: Parse, M: MappingMut<P>> {
    pub parse: P,
    pub mapping: M,
}

impl<'a, P: Parse, M: MappingMut<P>> IsParse<'a> for MappedMutParse<P, M> {
    type Output = MappingMutOutput<'a, P, M>;
    type Error = ParseErrorOutput<'a, P>;

    #[inline(always)]
    fn __parse<I: ?Sized + Input>(
        mut self,
        input: &'a mut I,
    ) -> Result<Self::Output, ParseError<Self::Error>> {
        self.parse
            .parse(input)
            .map(|output| self.mapping.map_mut(output))
    }
}

impl<'a, P: Parse + Clone, M: MappingMut<P>> IsParse<'a> for &mut MappedMutParse<P, M> {
    type Output = MappingMutOutput<'a, P, M>;
    type Error = ParseErrorOutput<'a, P>;

    #[inline(always)]
    fn __parse<I: ?Sized + Input>(
        self,
        input: &'a mut I,
    ) -> Result<Self::Output, ParseError<Self::Error>> {
        self.parse
            .clone()
            .parse(input)
            .map(|output| self.mapping.map_mut(output))
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        core::{parse::SplitUpTo, trim::TrimWhitespace},
        input::{Entry, Input},
        parse::{ParseExt, ParseIter, ParseMutIter},
    };

    #[allow(unused)]
    fn test_iter_typing<I: ?Sized + Input>(input: &mut I) {
        let mapped = SplitUpTo::new(|c| !char::is_whitespace(c)).mapped(|mut entry: Entry| {
            let ret = entry.get().to_string();
            entry.consume();
            ret
        });

        for i in ParseIter::new(input, TrimWhitespace, mapped).unwrap() {
            println!("{}", i.unwrap());
        }
    }

    #[allow(unused)]
    fn test_iter_mut_typing<I: ?Sized + Input>(input: &mut I) {
        let mut total_len = 0u32;

        let parser = SplitUpTo::new(|c| !char::is_whitespace(c));

        let mapped = parser.mapped_mut(|mut entry: Entry| {
            total_len += entry.get().len() as u32;
            let ret = entry.get().contains('!');
            entry.consume();
            ret
        });

        for i in ParseMutIter::new(input, TrimWhitespace, mapped).unwrap() {
            println!("{}", i.unwrap());
        }
    }
}