Diffstat (limited to 'src/walk.rs')
-rw-r--r--src/walk.rs66
1 files changed, 31 insertions, 35 deletions
diff --git a/src/walk.rs b/src/walk.rs
index 32232fd..0dbccee 100644
--- a/src/walk.rs
+++ b/src/walk.rs
@@ -1,23 +1,17 @@
pub mod walkers;
-use core::ops::ControlFlow;
-
use crate::{
effect::{Effect, Future},
protocol::Visitor,
+ Flow,
};
/// A type that can be walked.
-pub trait Walk<'ctx>: WalkerTypes + Sized {
+pub trait Walk<'ctx, M, E: Effect<'ctx>>: WalkerTypes + Sized {
/// The walker for the type.
- type Walker<E: Effect<'ctx>>: Walker<
- 'ctx,
- Error = Self::Error,
- Output = Self::Output,
- Effect = E,
- >;
-
- fn into_walker<E: Effect<'ctx>>(self) -> Self::Walker<E>;
+ type Walker: Walker<'ctx, E, Error = Self::Error, Output = Self::Output>;
+
+ fn into_walker(self) -> Self::Walker;
}
pub trait WalkerTypes {
@@ -38,40 +32,34 @@ pub trait WalkerTypes {
/// - Call [From::from()] with a value to be walked to make a walker.
/// - Call [Self::walk()] to walk the value. Data will be sent to the provided
/// visitor.
-pub trait Walker<'ctx>: WalkerTypes + Send {
- type Effect: Effect<'ctx>;
-
+pub trait Walker<'ctx, E: Effect<'ctx>>: WalkerTypes + Send {
/// Walk the value.
///
/// The walker should send data to the `visitor` as it walks the value.
fn walk<'a>(
self,
visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
+ ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
where
Self: 'a;
}
-pub trait WalkerObjSafe<'ctx>: Send {
- type Effect: Effect<'ctx>;
-
- fn walk<'a>(
- &'a mut self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
+pub trait WalkerObjSafe<'ctx, E: Effect<'ctx>>: Send {
+ fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>
where
Self: 'a;
fn skip(&mut self);
}
-pub type DynWalker<'a, 'ctx, E> = &'a mut (dyn WalkerObjSafe<'ctx, Effect = E> + Send + 'a);
+pub type DynWalker<'a, 'ctx, E> = &'a mut (dyn WalkerObjSafe<'ctx, E> + Send + 'a);
enum DynWalkerState<W: WalkerTypes> {
Skipped,
Walking,
Pending(W),
- Done(Result<W::Output, W::Error>),
+ Done(W::Output),
+ Err(W::Error),
}
pub enum DynWalkerError<W: WalkerTypes> {
@@ -100,31 +88,39 @@ impl<W: WalkerTypes> DynWalkerAdapter<W> {
DynWalkerState::Skipped => Ok(None),
DynWalkerState::Walking => Err(DynWalkerError::WalkNeverFinished),
DynWalkerState::Pending(walker) => Err(DynWalkerError::NeverWalked(walker)),
- DynWalkerState::Done(result) => result.map(Some).map_err(DynWalkerError::Walker),
+ DynWalkerState::Done(value) => Ok(Some(value)),
+ DynWalkerState::Err(err) => Err(DynWalkerError::Walker(err)),
}
}
}
-impl<'ctx, W: Walker<'ctx>> WalkerObjSafe<'ctx> for DynWalkerAdapter<W> {
- type Effect = W::Effect;
-
- fn walk<'a>(
- &'a mut self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
+impl<'ctx, W: Walker<'ctx, E>, E: Effect<'ctx>> WalkerObjSafe<'ctx, E> for DynWalkerAdapter<W> {
+ fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>
where
Self: 'a,
{
- Self::Effect::wrap(async {
+ E::wrap(async {
if let DynWalkerState::Pending(walker) =
core::mem::replace(&mut self.state, DynWalkerState::Walking)
{
// Walk the walker.
- self.state = DynWalkerState::Done(walker.walk(visitor).await);
+ match walker.walk(visitor).await {
+ Ok(value) => {
+ self.state = DynWalkerState::Done(value);
+ Flow::Continue
+ }
+ Err(err) => {
+ self.state = DynWalkerState::Err(err);
+
+ // Signal that control flow should stop as soon as possible as we
+ // are in an error state.
+ Flow::Break
+ }
+ }
} else {
// Can't do anything if the walker has already been walked.
+ Flow::Continue
}
- ControlFlow::Continue(())
})
}