use core::convert::Infallible; use core::task::Poll; /// Result of a single stepper "step". /// /// This is like a mix of [`ControlFlow`](core::ops::ControlFlow) and [`Poll`]. #[must_use] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum StepResult { /// The stepper didn't produce any additional result yet, /// try again later (e.g. next frame). /// /// This can be used to display intermediate context states to the user /// to visualize stepper progress Pending, /// The stepper suspended with a value (produced an intermediate result), /// this can be used to indicate a kind of progress. Yielded(Y), /// The stepper completed. Completed(S), } impl From> for StepResult { fn from(x: Poll) -> StepResult { match x { Poll::Pending => StepResult::Pending, Poll::Ready(y) => StepResult::Completed(y), } } } pub trait Step { fn step(&mut self, context: &mut C) -> StepResult; /// Run a stepper to completion. fn finish(&mut self, context: &mut C) -> S { loop { if let StepResult::Completed(outcome) = self.step(context) { return outcome; } } } } pub trait StepError { type Error; } // Note that PollStep's `S` is usually not the same as Step's `S`. pub trait PollStep: StepError { fn poll_step(&mut self, context: &mut C) -> Poll>; fn finish(&mut self, context: &mut C) -> Result { loop { if let Poll::Ready(outcome) = self.poll_step(context) { return outcome; } } } } impl> Step::Error>, Infallible> for Stepper { #[inline] fn step( &mut self, context: &mut C, ) -> StepResult::Error>> { self.poll_step(context).into() } } pub trait Abort { fn abort(&mut self, context: &mut C); } /// Evaluations which don't modify the context /// (basically calculating derived values) pub trait EvalImmut { type Error; fn eval(&self, context: &C) -> Result; }