use crate::func::context::*; use super::*; pub fn wrapped_origin<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>>( factory: A::Fctr, resolve: impl 'a + Fn() -> Resolution<'a, Ctx, A>, resolve_bytes: impl 'a + Fn() -> HashResolution<'a, Ctx>, ) -> Rc> { Rc::new(WrappedOrigin { w_factory: factory, w_resolve: Box::new(resolve), w_resolve_bytes: Box::new(resolve_bytes), }) } pub trait MappableOrigin<'a, Ctx: Context<'a>>: Origin<'a, Ctx> { fn map>( self: Rc, map_ok: impl 'a + Send + Sync + Clone + Fn(Rc) -> B, map_err: impl 'a + Send + Sync + Clone + Fn(ParseError<'a, Ctx, OFctr<'a, Ctx, Self>>) -> ParseError<'a, Ctx, B::Fctr>, map_factory: impl 'a + FnOnce(OFctr<'a, Ctx, Self>) -> B::Fctr, ) -> Rc> { let origin_r = self.clone(); let origin_rb = self.clone(); let origin: WrappedOrigin<'a, Ctx, B> = WrappedOrigin { w_factory: map_factory(self.factory()), w_resolve: Box::new(move || { let origin = origin_r.clone(); let map_ok = map_ok.clone(); let map_err = map_err.clone(); map_resolve(move || origin.clone().resolve(), map_ok, map_err) }), w_resolve_bytes: Box::new(move || origin_rb.clone().resolve_bytes()), }; Rc::new(origin) } } impl<'a, Ctx: Context<'a>, O: ?Sized + Origin<'a, Ctx>> MappableOrigin<'a, Ctx> for O {} fn map_resolve<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>, B: Mentionable<'a, Ctx>>( resolve: impl 'a + Fn() -> Resolution<'a, Ctx, A>, map_ok: impl 'a + Fn(Rc) -> B, map_err: impl 'a + Fn(ParseError<'a, Ctx, A::Fctr>) -> ParseError<'a, Ctx, B::Fctr>, ) -> Resolution<'a, Ctx, B> { Ctx::fmap(resolve(), move |resolved| match resolved { Ok(mentionable) => Ok(Rc::new(map_ok(mentionable))), Err(e) => Err(e.map_parse(map_err)), }) } struct WrappedOrigin<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> { w_factory: A::Fctr, w_resolve: Box Resolution<'a, Ctx, A>>, w_resolve_bytes: Box HashResolution<'a, Ctx>>, } impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx>> Origin<'a, Ctx> for WrappedOrigin<'a, Ctx, A> { type Mtbl = A; fn factory(&self) -> Fctr<'a, Ctx, Self::Mtbl> { self.w_factory.clone() } fn resolve(self: Rc) -> Resolution<'a, Ctx, A> { (self.w_resolve)() } fn resolve_bytes(self: Rc) -> HashResolution<'a, Ctx> { (self.w_resolve_bytes)() } }