Diffstat (limited to 'src/protocol/visitor/value.rs')
-rw-r--r--src/protocol/visitor/value.rs96
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)),
);