use effectful::{ bound::Dynamic, effective::{Effective, Canonical}, environment::{Environment}, DynBind, SendSync, }; use crate::{ any::{BorrowedStatic, OwnedStatic, TempBorrowedStatic}, protocol::{ visitor::{visit_value, EffectiveVisitExt as _, VisitResult}, DynVisitor, }, Never, }; /// A very basic walker that uses the [`Value`][crate::protocol::visitor::value::Value] protocol. /// /// Primitive types use this walker as their main walker. /// This walker doesn't consider it an error if the visitor doesn't have the protocol. #[derive(Debug, SendSync)] pub struct ValueWalker(Dynamic); impl ValueWalker { /// Create walker from a value. #[inline(always)] pub fn new(value: T) -> Self { Self(Dynamic(value)) } } impl From for ValueWalker { #[inline(always)] fn from(value: T) -> Self { Self::new(value) } } impl From<&T> for ValueWalker { #[inline(always)] fn from(value: &T) -> Self { Self::new(*value) } } impl<'ctx, T: 'static, E: Environment> crate::Walker<'ctx, E> for ValueWalker where Dynamic: DynBind, Dynamic>: DynBind, { type Error = Never; type Output = (); #[inline(always)] fn walk<'b: 'c, 'd: 'c, 'c>( self, visitor: DynVisitor<'b, 'd, 'ctx, E>, ) -> Canonical<'c, Result, E> { // Attempt to visit using the value protocol. visit_value::, E>(visitor, OwnedStatic(self.0 .0)) .map((), |_, _| Ok(())) .cast() } } /// Borrowed form of [`ValueWalker`]. /// /// This walker supports values borrowed for `'ctx` or longer. #[derive(SendSync)] pub struct BorrowWalker<'ctx, T: ?Sized>(Dynamic<&'ctx T>); impl<'ctx, T: ?Sized> BorrowWalker<'ctx, T> { /// Create walker from a value. #[inline(always)] pub fn new(value: &'ctx T) -> Self { Self(Dynamic(value)) } } impl<'ctx, T: ?Sized + 'static, E: Environment> crate::Walker<'ctx, E> for BorrowWalker<'ctx, T> where Dynamic<&'ctx T>: DynBind, Dynamic>: DynBind, for<'a> Dynamic>: DynBind, { type Error = Never; type Output = Dynamic<&'ctx T>; #[inline(always)] fn walk<'b: 'c, 'd: 'c, 'c>( self, visitor: DynVisitor<'b, 'd, 'ctx, E>, ) -> Canonical<'c, Result, E> { // Attempt to visit using the value protocol. E::value((self, visitor)) .update_map((), |_, (this, visitor)| { visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.0 .0)) .map((), |_, x| VisitResult::unit_skipped(x)) .cast() }) .if_skipped((), |_, (this, visitor)| { visit_value::<_, E>(visitor.cast(), TempBorrowedStatic(this.0 .0)) .map((), |_, x| VisitResult::unit_skipped(x)) .cast() }) .map((), |_, ((this, _), _)| Ok(this.0)) .cast() } }