Diffstat (limited to 'src/walk.rs')
| -rw-r--r-- | src/walk.rs | 66 |
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(()) }) } |