use std::marker::PhantomData; use super::*; pub trait Mode { type ParseResult; type ExtensionResult; fn map_err( result: Self::ParseResult, f: impl FnOnce(E0) -> E1, ) -> Self::ParseResult; fn bind( result: Self::ParseResult, f: impl FnOnce(A0) -> Result, ) -> Self::ParseResult; fn seal(result: Self::ParseResult) -> Result; fn xmap_err( result: Self::ExtensionResult, f: impl FnOnce(E0) -> E1, ) -> Self::ExtensionResult; fn xbind( result: Self::ExtensionResult, f: impl FnOnce(A0) -> Result, ) -> Self::ExtensionResult; } pub trait ParseMode { type Mode: ?Sized + Mode; } pub trait WithParseMode: ParseMode { type WithMode: ?Sized; } impl WithParseMode for T { type WithMode = WithMode::Mode>; } pub struct WithMode(PhantomData, T); pub trait FactoryProxy<'a, Ctx: Context<'a>> { type F: FactoryBase<'a, Ctx> + ParseMode; fn pdeserialize(f: &Self::F, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self::F>; fn pextend( f: &Self::F, mentionable: Mtbl<'a, Ctx, Self::F>, tail: &[u8], ) -> ParseResult<'a, Ctx, Self::F>; } impl<'a, Ctx: Context<'a>, F: FactoryBase<'a, Ctx> + WithParseMode> FactoryParse<'a, Ctx> for F where F::WithMode: FactoryProxy<'a, Ctx, F = Self>, { fn deserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self> { >::pdeserialize(self, inctx) } fn extend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self> { >::pextend(self, mentionable, tail) } } impl<'a, Ctx: Context<'a>, F: FactoryParse<'a, Ctx> + WithParseMode> Factory<'a, Ctx> for F where F::Mtbl: MentionableTop<'a, Ctx>, { type _Mtbl = Self::Mtbl; } pub struct RegularMode; impl Mode for RegularMode { type ParseResult = Result; type ExtensionResult = Result; fn map_err( result: Self::ParseResult, f: impl FnOnce(E0) -> E1, ) -> Self::ParseResult { result.map_err(f) } fn bind( result: Self::ParseResult, f: impl FnOnce(A0) -> Result, ) -> Self::ParseResult { result.and_then(f) } fn seal(result: Self::ParseResult) -> Result { result } fn xmap_err( result: Self::ExtensionResult, f: impl FnOnce(E0) -> E1, ) -> Self::ExtensionResult { result.map_err(f) } fn xbind( result: Self::ExtensionResult, f: impl FnOnce(A0) -> Result, ) -> Self::ExtensionResult { result.and_then(f) } } pub trait RegularFactory<'a, Ctx: Context<'a>>: FactoryBase<'a, Ctx> + ParseMode { fn rdeserialize(&self, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self>; fn rextend(&self, mentionable: Self::Mtbl, tail: &[u8]) -> ParseResult<'a, Ctx, Self>; } impl<'a, Ctx: Context<'a>, F: RegularFactory<'a, Ctx>> FactoryProxy<'a, Ctx> for WithMode { type F = F; fn pdeserialize(f: &Self::F, inctx: impl InCtx<'a, Ctx>) -> ParseResult<'a, Ctx, Self::F> { f.rdeserialize(inctx) } fn pextend( f: &Self::F, mentionable: Mtbl<'a, Ctx, Self::F>, tail: &[u8], ) -> ParseResult<'a, Ctx, Self::F> { f.rextend(mentionable, tail) } }