Diffstat (limited to 'src/protocol/visitor/value.rs')
| -rw-r--r-- | src/protocol/visitor/value.rs | 96 |
1 files changed, 56 insertions, 40 deletions
diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index a0c435c..8e7902c 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -2,23 +2,23 @@ //! //! In some sense, this is the most basic protocol. -use core::ops::ControlFlow; - use crate::{ any::{TypeName, TypeNameable}, effect::{Effect, Future}, higher_ranked_type, hkt::AnySend, nameable, - protocol::walker::hint::HintMeta, + never::Never, + protocol::{walker::hint::HintMeta, Visitor}, + Flow, }; +use super::Status; + /// Trait object for the [`Value`] protocol. /// /// Types implementing the [`Value`] protocol will implement this trait. -pub trait Value<'a, 'ctx: 'a, T> { - type Effect: Effect<'ctx>; - +pub trait Value<'a, 'ctx: 'a, T, E: Effect<'ctx>> { /// Visit a value of type `T`. /// /// Use this to give a value to a visitor. Its expected that a walker @@ -28,21 +28,21 @@ pub trait Value<'a, 'ctx: 'a, T> { /// If a [`ControlFlow::Break`] is returned then the walker /// should stop walking as soon as possible as there has likely been /// and error. - fn visit(&'a mut self, value: T) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect> - where - Self: 'a; + fn visit(&'a mut self, value: T) -> Future<'a, 'ctx, Flow, E>; } +pub type DynValue<'a, 'ctx, T, E> = dyn Value<'a, 'ctx, T, E> + Send + 'a; + nameable! { pub struct Name['a, 'ctx, T, E]; - impl [T::Name, E] for dyn Value<'a, 'ctx, T, Effect = E> + 'a where { + impl [T::Name, E] for DynValue<'a, 'ctx, T, E> where { T: TypeNameable<'a, 'ctx> + ?Sized, E: Effect<'ctx>, 'ctx: 'a, } - impl [T, E] where dyn Value<'a, 'ctx, T::Nameable, Effect = E> + 'a { + impl [T, E] where DynValue<'a, 'ctx, T::Nameable, E> { T: TypeName<'a, 'ctx> + ?Sized, E: Effect<'ctx>, 'ctx: 'a, @@ -54,12 +54,36 @@ higher_ranked_type! { } // This enrolls the Value protocol into the walker hint system. -impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'ctx> for dyn Value<'a, 'ctx, T, Effect = E> + 'a { +impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'ctx> for DynValue<'a, 'ctx, T, E> { type Known = Known<'ctx>; type Hint = (); } +pub fn visit_value<'a, 'ctx, T: TypeNameable<'a, 'ctx>, E: Effect<'ctx>>( + visitor: Visitor<'a, 'ctx>, + value: T, +) -> Future<'a, 'ctx, Status, E> { + if let Some(object) = visitor.upcast_mut::<DynValue<'_, 'ctx, T, E>>() { + // Allow the visitor to give a hint if it wants. + E::map(object.visit(value), |flow| match flow { + Flow::Continue => { + // The visitor wants the walker to continue to it's normal + // walking. + Status::Continue + } + Flow::Break | Flow::Done => { + // The visitor is done (either because of an error or because + // it already used a hint). + Status::Break + } + }) + } else { + // If the visitor doesn't support request hint then we continue. + E::ready(Status::Skipped) + } +} + #[cfg(test)] mod test { use core::{marker::PhantomData, ops::ControlFlow}; @@ -79,44 +103,40 @@ mod test { fn visit() { struct Visitor<E>(Option<i32>, PhantomData<fn() -> E>); - impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, OwnedStatic<i32>> for Visitor<E> + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, OwnedStatic<i32>, E> for Visitor<E> where E: Effect<'ctx>, { - type Effect = E; - fn visit( &'a mut self, OwnedStatic(value): OwnedStatic<i32>, - ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + ) -> Future<'a, 'ctx, Flow, E> { E::wrap(async move { self.0 = Some(value); - ControlFlow::Continue(()) + Flow::Continue }) } } - impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, i32>> for Visitor<E> + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, E> for Visitor<E> where E: Effect<'ctx>, { - type Effect = E; - fn visit( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, i32>, - ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + ) -> Future<'a, 'ctx, Flow, E> { E::wrap(async { self.0 = Some(*value); - ControlFlow::Continue(()) + Flow::Continue }) } } any_trait! { impl['a, 'ctx, E] Visitor<E> = [ - dyn Value<'a, 'ctx, OwnedStatic<i32>, Effect = E> + 'a, - dyn Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, Effect = E> + 'a, + DynValue<'a, 'ctx, OwnedStatic<i32>, E>, + DynValue<'a, 'ctx, BorrowedStatic<'ctx, i32>, E>, ] where E: Effect<'ctx>, } @@ -124,7 +144,7 @@ mod test { let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; Spin::block_on( object - .upcast_mut::<dyn Value<'_, '_, OwnedStatic<i32>, Effect = Blocking>>() + .upcast_mut::<DynValue<'_, '_, OwnedStatic<i32>, Blocking>>() .unwrap() .visit(OwnedStatic(42)), ); @@ -134,7 +154,7 @@ mod test { let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; Spin::block_on( object - .upcast_mut::<dyn Value<'_, '_, BorrowedStatic<'_, i32>, Effect = Blocking>>() + .upcast_mut::<DynValue<'_, '_, BorrowedStatic<'_, i32>, Blocking>>() .unwrap() .visit(BorrowedStatic(&101)), ); @@ -146,27 +166,25 @@ mod test { fn visit_borrowed() { struct Visitor<'ctx, E>(Option<&'ctx mut String>, PhantomData<fn() -> E>); - impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>> for Visitor<'ctx, E> + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, E> for Visitor<'ctx, E> where E: Effect<'ctx>, { - type Effect = E; - fn visit( &'a mut self, BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>, - ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + ) -> Future<'a, 'ctx, Flow, E> { E::wrap(async { self.0 = Some(value); - ControlFlow::Continue(()) + Flow::Continue }) } } any_trait! { impl['a, 'ctx, E] Visitor<'ctx, E> = [ - dyn Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, Effect = E> + 'a, + DynValue<'a, 'ctx, BorrowedMutStatic<'ctx, String>, E>, ] where E: Effect<'ctx> } @@ -176,7 +194,7 @@ mod test { let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; Spin::block_on( object - .upcast_mut::<dyn Value<'_, '_, _, Effect = Blocking>>() + .upcast_mut::<DynValue<'_, '_, _, Blocking>>() .unwrap() .visit(BorrowedMutStatic(&mut y)), ); @@ -189,26 +207,24 @@ mod test { fn visit_borrowed_unsized() { struct Visitor<'ctx, E>(Option<&'ctx str>, PhantomData<fn() -> E>); - impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, str>> for Visitor<'ctx, E> + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, str>, E> for Visitor<'ctx, E> where E: Effect<'ctx>, { - type Effect = E; - fn visit( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, str>, - ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + ) -> Future<'a, 'ctx, Flow, E> { E::wrap(async { self.0 = Some(value); - ControlFlow::Continue(()) + Flow::Continue }) } } any_trait! { impl['a, 'ctx, E] Visitor<'ctx, E> = [ - dyn Value<'a, 'ctx, BorrowedStatic<'ctx, str>, Effect = E> + 'a, + DynValue<'a, 'ctx, BorrowedStatic<'ctx, str>, E>, ] where E: Effect<'ctx> } @@ -218,7 +234,7 @@ mod test { let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; Spin::block_on( object - .upcast_mut::<dyn Value<'_, '_, BorrowedStatic<'_, str>, Effect = Blocking> + '_>() + .upcast_mut::<DynValue<'_, '_, BorrowedStatic<'_, str>, Blocking>>() .unwrap() .visit(BorrowedStatic(&y)), ); |