mirror of https://codeberg.org/topola/topola.git
87 lines
2.3 KiB
Rust
87 lines
2.3 KiB
Rust
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<Y, S> {
|
|
/// 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<S, Y> From<Poll<S>> for StepResult<Y, S> {
|
|
fn from(x: Poll<S>) -> StepResult<Y, S> {
|
|
match x {
|
|
Poll::Pending => StepResult::Pending,
|
|
Poll::Ready(y) => StepResult::Completed(y),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait Step<C, S, Y = Infallible> {
|
|
fn step(&mut self, context: &mut C) -> StepResult<Y, S>;
|
|
|
|
/// 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<C, S>: StepError {
|
|
fn poll_step(&mut self, context: &mut C) -> Poll<Result<S, Self::Error>>;
|
|
|
|
fn finish(&mut self, context: &mut C) -> Result<S, Self::Error> {
|
|
loop {
|
|
if let Poll::Ready(outcome) = self.poll_step(context) {
|
|
return outcome;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<C, S, Stepper: PollStep<C, S>> Step<C, Result<S, <Self as StepError>::Error>, Infallible>
|
|
for Stepper
|
|
{
|
|
#[inline]
|
|
fn step(
|
|
&mut self,
|
|
context: &mut C,
|
|
) -> StepResult<Infallible, Result<S, <Self as StepError>::Error>> {
|
|
self.poll_step(context).into()
|
|
}
|
|
}
|
|
|
|
pub trait Abort<C> {
|
|
fn abort(&mut self, context: &mut C);
|
|
}
|
|
|
|
/// Evaluations which don't modify the context
|
|
/// (basically calculating derived values)
|
|
pub trait EvalImmut<C, S> {
|
|
type Error;
|
|
|
|
fn eval(&self, context: &C) -> Result<S, Self::Error>;
|
|
}
|