mirror of https://codeberg.org/topola/topola.git
stepper: turn Step into a tristate-producer (Pending, Yielded, Completed)
This commit is contained in:
parent
10d778c807
commit
f3864c9175
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
|
drawing::{band::BandTermsegIndex, graph::PrimitiveIndex},
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navmesh::Navmesh, route::RouteStepper, trace::TraceStepper, Router},
|
router::{navmesh::Navmesh, route::RouteStepper, trace::TraceStepper, Router},
|
||||||
stepper::{PollStep, Step, StepError},
|
stepper::{PollStep, Step, StepError, StepResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
@ -18,32 +18,6 @@ use super::{
|
||||||
Autorouter, AutorouterError, AutorouterOptions,
|
Autorouter, AutorouterError, AutorouterOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents the current status of the autoroute operation.
|
|
||||||
pub enum AutorouteStatus {
|
|
||||||
/// The autoroute is currently running and in progress.
|
|
||||||
Running,
|
|
||||||
/// A specific segment has been successfully routed.
|
|
||||||
Routed(BandTermsegIndex),
|
|
||||||
/// The autoroute process has completed successfully.
|
|
||||||
Finished,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryInto<()> for AutorouteStatus {
|
|
||||||
type Error = ();
|
|
||||||
/// Attempts to get the [`Result`] from the [`AutorouteStatus`].
|
|
||||||
///
|
|
||||||
/// This implementation allows transitioning from [`AutorouteStatus`] to a
|
|
||||||
/// [`Result`]. It returns success for the [`AutorouteStatus::Finished`] state
|
|
||||||
/// or an error for [`AutorouteStatus::Running`] or [`AutorouteStatus::Routed`] states.
|
|
||||||
fn try_into(self) -> Result<(), ()> {
|
|
||||||
match self {
|
|
||||||
AutorouteStatus::Running => Err(()),
|
|
||||||
AutorouteStatus::Routed(..) => Err(()),
|
|
||||||
AutorouteStatus::Finished => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Manages the autorouting process across multiple ratlines.
|
/// Manages the autorouting process across multiple ratlines.
|
||||||
pub struct AutorouteExecutionStepper {
|
pub struct AutorouteExecutionStepper {
|
||||||
/// An iterator over ratlines that tracks which segments still need to be routed.
|
/// An iterator over ratlines that tracks which segments still need to be routed.
|
||||||
|
|
@ -91,15 +65,20 @@ impl StepError for AutorouteExecutionStepper {
|
||||||
type Error = AutorouterError;
|
type Error = AutorouterError;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus> for AutorouteExecutionStepper {
|
impl<M: AccessMesadata> Step<Autorouter<M>, Result<(), AutorouterError>, BandTermsegIndex>
|
||||||
fn step(&mut self, autorouter: &mut Autorouter<M>) -> Result<AutorouteStatus, AutorouterError> {
|
for AutorouteExecutionStepper
|
||||||
|
{
|
||||||
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
autorouter: &mut Autorouter<M>,
|
||||||
|
) -> StepResult<BandTermsegIndex, Result<(), AutorouterError>> {
|
||||||
let Some(curr_ratline) = self.curr_ratline else {
|
let Some(curr_ratline) = self.curr_ratline else {
|
||||||
return Ok(AutorouteStatus::Finished);
|
return StepResult::Completed(Ok(()));
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(ref mut route) = self.route else {
|
let Some(ref mut route) = self.route else {
|
||||||
// Shouldn't happen.
|
// Shouldn't happen.
|
||||||
return Ok(AutorouteStatus::Finished);
|
return StepResult::Completed(Ok(()));
|
||||||
};
|
};
|
||||||
|
|
||||||
let (source, target) = autorouter.ratline_endpoints(curr_ratline);
|
let (source, target) = autorouter.ratline_endpoints(curr_ratline);
|
||||||
|
|
@ -109,9 +88,9 @@ impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus> for AutorouteExecut
|
||||||
Router::new(autorouter.board.layout_mut(), self.options.router_options);
|
Router::new(autorouter.board.layout_mut(), self.options.router_options);
|
||||||
|
|
||||||
match route.poll_step(&mut router) {
|
match route.poll_step(&mut router) {
|
||||||
Poll::Pending => return Ok(AutorouteStatus::Running),
|
Poll::Pending => return StepResult::Pending,
|
||||||
Poll::Ready(Ok(band_termseg)) => band_termseg,
|
Poll::Ready(Ok(band_termseg)) => band_termseg,
|
||||||
Poll::Ready(Err(err)) => return Err(err.into()),
|
Poll::Ready(Err(err)) => return StepResult::Completed(Err(err.into())),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -136,13 +115,16 @@ impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus> for AutorouteExecut
|
||||||
Router::new(autorouter.board.layout_mut(), self.options.router_options);
|
Router::new(autorouter.board.layout_mut(), self.options.router_options);
|
||||||
|
|
||||||
self.curr_ratline = Some(new_ratline);
|
self.curr_ratline = Some(new_ratline);
|
||||||
self.route = Some(router.route(source, target, 100.0)?);
|
self.route = Some(match router.route(source, target, 100.0) {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(err) => return StepResult::Completed(Err(err.into())),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
self.curr_ratline = None;
|
self.curr_ratline = None;
|
||||||
//return Ok(AutorouteStatus::Finished);
|
//return Ok(AutorouteStatus::Finished);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AutorouteStatus::Routed(band_termseg))
|
StepResult::Yielded(band_termseg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@ use crate::{
|
||||||
geometry::{primitive::PrimitiveShape, shape::MeasureLength},
|
geometry::{primitive::PrimitiveShape, shape::MeasureLength},
|
||||||
graph::MakeRef,
|
graph::MakeRef,
|
||||||
router::{navmesh::Navmesh, trace::TraceStepper},
|
router::{navmesh::Navmesh, trace::TraceStepper},
|
||||||
stepper::{PollStep, Step, StepError},
|
stepper::{PollStep, Step, StepError, StepResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::{AutorouteExecutionStepper, AutorouteStatus},
|
autoroute::AutorouteExecutionStepper,
|
||||||
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
|
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
|
||||||
Autorouter, AutorouterError, AutorouterOptions,
|
Autorouter, AutorouterError, AutorouterOptions,
|
||||||
};
|
};
|
||||||
|
|
@ -65,9 +65,9 @@ impl<M: AccessMesadata> PollStep<Autorouter<M>, (f64, f64)> for CompareDetoursEx
|
||||||
return Poll::Ready(Ok((self.total_length1, self.total_length2)));
|
return Poll::Ready(Ok((self.total_length1, self.total_length2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.autoroute.step(autorouter)? {
|
match self.autoroute.step(autorouter) {
|
||||||
AutorouteStatus::Running => Poll::Pending,
|
StepResult::Pending => Poll::Pending,
|
||||||
AutorouteStatus::Routed(band_termseg) => {
|
StepResult::Yielded(band_termseg) => {
|
||||||
let length = band_termseg
|
let length = band_termseg
|
||||||
.ref_(autorouter.board.layout().drawing())
|
.ref_(autorouter.board.layout().drawing())
|
||||||
.length();
|
.length();
|
||||||
|
|
@ -80,7 +80,8 @@ impl<M: AccessMesadata> PollStep<Autorouter<M>, (f64, f64)> for CompareDetoursEx
|
||||||
|
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
AutorouteStatus::Finished => {
|
StepResult::Completed(Err(err)) => return Poll::Ready(Err(err)),
|
||||||
|
StepResult::Completed(Ok(())) => {
|
||||||
if let Some(next_autoroute) = self.next_autoroute.take() {
|
if let Some(next_autoroute) = self.next_autoroute.take() {
|
||||||
autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2])?;
|
autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2])?;
|
||||||
self.autoroute = next_autoroute;
|
self.autoroute = next_autoroute;
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ use serde::{Deserialize, Serialize};
|
||||||
use crate::{
|
use crate::{
|
||||||
board::mesadata::AccessMesadata,
|
board::mesadata::AccessMesadata,
|
||||||
layout::via::ViaWeight,
|
layout::via::ViaWeight,
|
||||||
stepper::{EvalImmut, PollStep, Step, StepError},
|
stepper::{EvalImmut, PollStep, Step, StepError, StepResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::{AutorouteExecutionStepper, AutorouteStatus},
|
autoroute::AutorouteExecutionStepper,
|
||||||
compare_detours::CompareDetoursExecutionStepper,
|
compare_detours::CompareDetoursExecutionStepper,
|
||||||
invoker::{Invoker, InvokerError},
|
invoker::{Invoker, InvokerError},
|
||||||
measure_length::MeasureLength,
|
measure_length::MeasureLength,
|
||||||
|
|
@ -45,10 +45,11 @@ impl ExecutionStepper {
|
||||||
autorouter: &mut Autorouter<M>,
|
autorouter: &mut Autorouter<M>,
|
||||||
) -> Poll<Result<String, InvokerError>> {
|
) -> Poll<Result<String, InvokerError>> {
|
||||||
match self {
|
match self {
|
||||||
ExecutionStepper::Autoroute(autoroute) => match autoroute.step(autorouter)? {
|
ExecutionStepper::Autoroute(autoroute) => match autoroute.step(autorouter) {
|
||||||
AutorouteStatus::Running => Poll::Pending,
|
StepResult::Pending => Poll::Pending,
|
||||||
AutorouteStatus::Routed(..) => Poll::Pending,
|
StepResult::Yielded(..) => Poll::Pending,
|
||||||
AutorouteStatus::Finished => Poll::Ready("finished autorouting".to_string()),
|
StepResult::Completed(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||||
|
StepResult::Completed(Ok(())) => Poll::Ready("finished autorouting".to_string()),
|
||||||
},
|
},
|
||||||
ExecutionStepper::PlaceVia(place_via) => {
|
ExecutionStepper::PlaceVia(place_via) => {
|
||||||
place_via.doit(autorouter)?;
|
place_via.doit(autorouter)?;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use thiserror::Error;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::stepper::{Step, StepError};
|
use crate::stepper::{Step, StepError, StepResult};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct MinScored<K, T>(pub K, pub T);
|
pub struct MinScored<K, T>(pub K, pub T);
|
||||||
|
|
@ -144,36 +144,11 @@ pub enum AstarError {
|
||||||
NotFound,
|
NotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum AstarStatus<G, K, R>
|
pub enum AstarYield {
|
||||||
where
|
|
||||||
G: GraphBase,
|
|
||||||
G::NodeId: Eq + Hash,
|
|
||||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
|
||||||
K: Measure + Copy,
|
|
||||||
{
|
|
||||||
Probing,
|
Probing,
|
||||||
Probed,
|
Probed,
|
||||||
Visited,
|
Visited,
|
||||||
Finished(K, Vec<G::NodeId>, R),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<G, K, R> TryInto<(K, Vec<G::NodeId>, R)> for AstarStatus<G, K, R>
|
|
||||||
where
|
|
||||||
G: GraphBase,
|
|
||||||
G::NodeId: Eq + Hash,
|
|
||||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
|
||||||
K: Measure + Copy,
|
|
||||||
{
|
|
||||||
type Error = ();
|
|
||||||
fn try_into(self) -> Result<(K, Vec<G::NodeId>, R), ()> {
|
|
||||||
match self {
|
|
||||||
AstarStatus::Probing => Err(()),
|
|
||||||
AstarStatus::Probed => Err(()),
|
|
||||||
AstarStatus::Visited => Err(()),
|
|
||||||
AstarStatus::Finished(cost, path, result) => Ok((cost, path, result)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, K> Astar<G, K>
|
impl<G, K> Astar<G, K>
|
||||||
|
|
@ -213,14 +188,18 @@ where
|
||||||
type Error = AstarError;
|
type Error = AstarError;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G, K, R, S: AstarStrategy<G, K, R>> Step<S, AstarStatus<G, K, R>> for Astar<G, K>
|
impl<G, K, R, S: AstarStrategy<G, K, R>>
|
||||||
|
Step<S, Result<(K, Vec<G::NodeId>, R), AstarError>, AstarYield> for Astar<G, K>
|
||||||
where
|
where
|
||||||
G: GraphBase,
|
G: GraphBase,
|
||||||
G::NodeId: Eq + Hash,
|
G::NodeId: Eq + Hash,
|
||||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||||
K: Measure + Copy,
|
K: Measure + Copy,
|
||||||
{
|
{
|
||||||
fn step(&mut self, strategy: &mut S) -> Result<AstarStatus<G, K, R>, AstarError> {
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
strategy: &mut S,
|
||||||
|
) -> StepResult<AstarYield, Result<(K, Vec<G::NodeId>, R), AstarError>> {
|
||||||
if let Some(curr_node) = self.maybe_curr_node {
|
if let Some(curr_node) = self.maybe_curr_node {
|
||||||
if self.is_probing {
|
if self.is_probing {
|
||||||
strategy.remove_probe(&self.graph);
|
strategy.remove_probe(&self.graph);
|
||||||
|
|
@ -242,7 +221,7 @@ where
|
||||||
// No need to add neighbors that we have already reached through a
|
// No need to add neighbors that we have already reached through a
|
||||||
// shorter path than now.
|
// shorter path than now.
|
||||||
if *entry.get() <= next_score {
|
if *entry.get() <= next_score {
|
||||||
return Ok(AstarStatus::Probed);
|
return StepResult::Yielded(AstarYield::Probed);
|
||||||
}
|
}
|
||||||
entry.insert(next_score);
|
entry.insert(next_score);
|
||||||
}
|
}
|
||||||
|
|
@ -257,23 +236,23 @@ where
|
||||||
self.visit_next.push(MinScored(next_estimate_score, next));
|
self.visit_next.push(MinScored(next_estimate_score, next));
|
||||||
|
|
||||||
self.is_probing = true;
|
self.is_probing = true;
|
||||||
return Ok(AstarStatus::Probing);
|
return StepResult::Yielded(AstarYield::Probing);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(AstarStatus::Probed);
|
return StepResult::Yielded(AstarYield::Probed);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.maybe_curr_node = None;
|
self.maybe_curr_node = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(MinScored(estimate_score, node)) = self.visit_next.pop() else {
|
let Some(MinScored(estimate_score, node)) = self.visit_next.pop() else {
|
||||||
return Err(AstarError::NotFound);
|
return StepResult::Completed(Err(AstarError::NotFound));
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(result) = strategy.is_goal(&self.graph, node, &self.path_tracker) {
|
if let Some(result) = strategy.is_goal(&self.graph, node, &self.path_tracker) {
|
||||||
let path = self.path_tracker.reconstruct_path_to(node);
|
let path = self.path_tracker.reconstruct_path_to(node);
|
||||||
let cost = self.scores[&node];
|
let cost = self.scores[&node];
|
||||||
return Ok(AstarStatus::Finished(cost, path, result));
|
return StepResult::Completed(Ok((cost, path, result)));
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.estimate_scores.entry(node) {
|
match self.estimate_scores.entry(node) {
|
||||||
|
|
@ -281,7 +260,7 @@ where
|
||||||
// If the node has already been visited with an equal or lower score than
|
// If the node has already been visited with an equal or lower score than
|
||||||
// now, then we do not need to re-visit it.
|
// now, then we do not need to re-visit it.
|
||||||
if *entry.get() <= estimate_score {
|
if *entry.get() <= estimate_score {
|
||||||
return Ok(AstarStatus::Visited);
|
return StepResult::Yielded(AstarYield::Visited);
|
||||||
}
|
}
|
||||||
entry.insert(estimate_score);
|
entry.insert(estimate_score);
|
||||||
}
|
}
|
||||||
|
|
@ -293,6 +272,6 @@ where
|
||||||
self.maybe_curr_node = Some(node);
|
self.maybe_curr_node = Some(node);
|
||||||
self.edge_ids = self.graph.edges(node).map(|edge| edge.id()).collect();
|
self.edge_ids = self.graph.edges(node).map(|edge| edge.id()).collect();
|
||||||
|
|
||||||
Ok(AstarStatus::Visited)
|
StepResult::Yielded(AstarYield::Visited)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ use crate::{
|
||||||
},
|
},
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{
|
router::{
|
||||||
astar::{Astar, AstarError, AstarStatus},
|
astar::{Astar, AstarError},
|
||||||
navmesh::{Navmesh, NavmeshError},
|
navmesh::{Navmesh, NavmeshError},
|
||||||
trace::TraceStepper,
|
trace::TraceStepper,
|
||||||
tracer::Tracer,
|
tracer::Tracer,
|
||||||
Router, RouterAstarStrategy,
|
Router, RouterAstarStrategy,
|
||||||
},
|
},
|
||||||
stepper::{PollStep, Step, StepError},
|
stepper::{PollStep, Step, StepError, StepResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RouteStepper {
|
pub struct RouteStepper {
|
||||||
|
|
@ -85,9 +85,10 @@ impl<'a, R: AccessRules> PollStep<Router<'a, R>, BandTermsegIndex> for RouteStep
|
||||||
let target = self.astar.graph.destination();
|
let target = self.astar.graph.destination();
|
||||||
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target);
|
let mut strategy = RouterAstarStrategy::new(tracer, &mut self.trace, target);
|
||||||
|
|
||||||
let result = match self.astar.step(&mut strategy)? {
|
let result = match self.astar.step(&mut strategy) {
|
||||||
AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => Poll::Pending,
|
StepResult::Pending | StepResult::Yielded(_) => Poll::Pending,
|
||||||
AstarStatus::Finished(_cost, _path, band) => Poll::Ready(Ok(band)),
|
StepResult::Completed(Ok((_, _, band))) => Poll::Ready(Ok(band)),
|
||||||
|
StepResult::Completed(Err(err)) => Poll::Ready(Err(err.into())),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.ghosts = strategy.probe_ghosts;
|
self.ghosts = strategy.probe_ghosts;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,53 @@
|
||||||
|
use core::convert::Infallible;
|
||||||
use core::task::Poll;
|
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 {
|
pub trait StepError {
|
||||||
type Error;
|
type Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Step<C, S>: StepError {
|
|
||||||
fn step(&mut self, context: &mut C) -> Result<S, Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that PollStep's `S` is usually not the same as Step's `S`.
|
// Note that PollStep's `S` is usually not the same as Step's `S`.
|
||||||
pub trait PollStep<C, S>: StepError {
|
pub trait PollStep<C, S>: StepError {
|
||||||
fn poll_step(&mut self, context: &mut C) -> Poll<Result<S, Self::Error>>;
|
fn poll_step(&mut self, context: &mut C) -> Poll<Result<S, Self::Error>>;
|
||||||
|
|
@ -21,13 +61,15 @@ pub trait PollStep<C, S>: StepError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, S, Stepper: PollStep<C, S>> Step<C, Poll<S>> for Stepper {
|
impl<C, S, Stepper: PollStep<C, S>> Step<C, Result<S, <Self as StepError>::Error>, Infallible>
|
||||||
|
for Stepper
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn step(&mut self, context: &mut C) -> Result<Poll<S>, Self::Error> {
|
fn step(
|
||||||
Ok(match self.poll_step(context) {
|
&mut self,
|
||||||
Poll::Pending => Poll::Pending,
|
context: &mut C,
|
||||||
Poll::Ready(x) => Poll::Ready(x?),
|
) -> StepResult<Infallible, Result<S, <Self as StepError>::Error>> {
|
||||||
})
|
self.poll_step(context).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue