Diffstat (limited to 'src/walk.rs')
| -rw-r--r-- | src/walk.rs | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/src/walk.rs b/src/walk.rs index a119965..32232fd 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -8,7 +8,7 @@ use crate::{ }; /// A type that can be walked. -pub trait Walk<'ctx>: WalkerTypes<'ctx> + Sized { +pub trait Walk<'ctx>: WalkerTypes + Sized { /// The walker for the type. type Walker<E: Effect<'ctx>>: Walker< 'ctx, @@ -20,7 +20,7 @@ pub trait Walk<'ctx>: WalkerTypes<'ctx> + Sized { fn into_walker<E: Effect<'ctx>>(self) -> Self::Walker<E>; } -pub trait WalkerTypes<'ctx> { +pub trait WalkerTypes { type Error: Send; /// An arbitrary type the walker is left with after walking. @@ -38,7 +38,7 @@ pub trait WalkerTypes<'ctx> { /// - 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<'ctx> + Send { +pub trait Walker<'ctx>: WalkerTypes + Send { type Effect: Effect<'ctx>; /// Walk the value. @@ -52,7 +52,7 @@ pub trait Walker<'ctx>: WalkerTypes<'ctx> + Send { Self: 'a; } -pub trait DynWalker<'ctx>: Send { +pub trait WalkerObjSafe<'ctx>: Send { type Effect: Effect<'ctx>; fn walk<'a>( @@ -61,15 +61,20 @@ pub trait DynWalker<'ctx>: Send { ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect> where Self: 'a; + + fn skip(&mut self); } -enum DynWalkerState<'ctx, W: WalkerTypes<'ctx>> { +pub type DynWalker<'a, 'ctx, E> = &'a mut (dyn WalkerObjSafe<'ctx, Effect = E> + Send + 'a); + +enum DynWalkerState<W: WalkerTypes> { + Skipped, Walking, Pending(W), Done(Result<W::Output, W::Error>), } -pub enum DynWalkerError<'ctx, W: WalkerTypes<'ctx>> { +pub enum DynWalkerError<W: WalkerTypes> { NeverWalked(W), /// This can only happen if a panic happens furing the walk and is then caught before calling @@ -79,27 +84,28 @@ pub enum DynWalkerError<'ctx, W: WalkerTypes<'ctx>> { Walker(W::Error), } -pub struct DynWalkerAdapter<'ctx, W: WalkerTypes<'ctx>> { - state: DynWalkerState<'ctx, W>, +pub struct DynWalkerAdapter<W: WalkerTypes> { + state: DynWalkerState<W>, } -impl<'ctx, W: WalkerTypes<'ctx>> DynWalkerAdapter<'ctx, W> { +impl<W: WalkerTypes> DynWalkerAdapter<W> { pub fn new(walker: W) -> Self { Self { state: DynWalkerState::Pending(walker), } } - pub fn finish(self) -> Result<W::Output, DynWalkerError<'ctx, W>> { + pub fn finish(self) -> Result<Option<W::Output>, DynWalkerError<W>> { match self.state { + DynWalkerState::Skipped => Ok(None), DynWalkerState::Walking => Err(DynWalkerError::WalkNeverFinished), DynWalkerState::Pending(walker) => Err(DynWalkerError::NeverWalked(walker)), - DynWalkerState::Done(result) => result.map_err(DynWalkerError::Walker), + DynWalkerState::Done(result) => result.map(Some).map_err(DynWalkerError::Walker), } } } -impl<'ctx, W: Walker<'ctx>> DynWalker<'ctx> for DynWalkerAdapter<'ctx, W> { +impl<'ctx, W: Walker<'ctx>> WalkerObjSafe<'ctx> for DynWalkerAdapter<W> { type Effect = W::Effect; fn walk<'a>( @@ -121,4 +127,8 @@ impl<'ctx, W: Walker<'ctx>> DynWalker<'ctx> for DynWalkerAdapter<'ctx, W> { ControlFlow::Continue(()) }) } + + fn skip(&mut self) { + self.state = DynWalkerState::Skipped; + } } |