diff --git a/src/autorouter/autoroute.rs b/src/autorouter/autoroute.rs index 9cec6c8..23cfb78 100644 --- a/src/autorouter/autoroute.rs +++ b/src/autorouter/autoroute.rs @@ -1,15 +1,15 @@ //! Manages autorouting of ratlines in a layout, tracking status and processed //! routing steps. +use std::ops::ControlFlow; + use petgraph::graph::EdgeIndex; use crate::{ board::mesadata::AccessMesadata, drawing::{band::BandTermsegIndex, graph::PrimitiveIndex}, geometry::primitive::PrimitiveShape, - router::{ - navcord::NavcordStepper, navmesh::Navmesh, route::RouteStepper, Router, RouterStatus, - }, + router::{navcord::NavcordStepper, navmesh::Navmesh, route::RouteStepper, Router}, stepper::Step, }; @@ -19,29 +19,11 @@ use super::{ }; /// Represents the current status of the autoroute operation. -pub enum AutorouteStatus { +pub enum AutorouteContinueStatus { /// 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. @@ -87,17 +69,22 @@ impl AutorouteExecutionStepper { } } -impl Step, AutorouteStatus, ()> for AutorouteExecutionStepper { +impl Step, (), AutorouteContinueStatus> + for AutorouteExecutionStepper +{ type Error = AutorouterError; - fn step(&mut self, autorouter: &mut Autorouter) -> Result { + fn step( + &mut self, + autorouter: &mut Autorouter, + ) -> Result, AutorouterError> { let Some(curr_ratline) = self.curr_ratline else { - return Ok(AutorouteStatus::Finished); + return Ok(ControlFlow::Break(())); }; let Some(ref mut route) = self.route else { // Shouldn't happen. - return Ok(AutorouteStatus::Finished); + return Ok(ControlFlow::Break(())); }; let (source, target) = autorouter.ratline_endpoints(curr_ratline); @@ -106,8 +93,8 @@ impl Step, AutorouteStatus, ()> for AutorouteEx let mut router = Router::new(autorouter.board.layout_mut(), self.options.router_options); - let RouterStatus::Finished(band_termseg) = route.step(&mut router)? else { - return Ok(AutorouteStatus::Running); + let ControlFlow::Break(band_termseg) = route.step(&mut router)? else { + return Ok(ControlFlow::Continue(AutorouteContinueStatus::Running)); }; band_termseg }; @@ -139,7 +126,9 @@ impl Step, AutorouteStatus, ()> for AutorouteEx //return Ok(AutorouteStatus::Finished); } - Ok(AutorouteStatus::Routed(band_termseg)) + Ok(ControlFlow::Continue(AutorouteContinueStatus::Routed( + band_termseg, + ))) } } diff --git a/src/autorouter/compare_detours.rs b/src/autorouter/compare_detours.rs index 3c3011d..a8ba42f 100644 --- a/src/autorouter/compare_detours.rs +++ b/src/autorouter/compare_detours.rs @@ -1,6 +1,8 @@ //! Manages the comparison of detours between two ratlines, tracking their //! routing statuses and recording their lengths. +use std::ops::ControlFlow; + use petgraph::graph::EdgeIndex; use crate::{ @@ -13,28 +15,11 @@ use crate::{ }; use super::{ - autoroute::{AutorouteExecutionStepper, AutorouteStatus}, + autoroute::{AutorouteContinueStatus, AutorouteExecutionStepper}, invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles}, Autorouter, AutorouterError, AutorouterOptions, }; -pub enum CompareDetoursStatus { - Running, - Finished(f64, f64), -} - -impl TryInto<(f64, f64)> for CompareDetoursStatus { - type Error = (); - fn try_into(self) -> Result<(f64, f64), ()> { - match self { - CompareDetoursStatus::Running => Err(()), - CompareDetoursStatus::Finished(total_length1, total_length2) => { - Ok((total_length1, total_length2)) - } - } - } -} - pub struct CompareDetoursExecutionStepper { autoroute: AutorouteExecutionStepper, next_autoroute: Option, @@ -66,25 +51,22 @@ impl CompareDetoursExecutionStepper { // XXX: Do we really need this to be a stepper? We don't use at the moment, as sorting functions // aren't steppable either. It may be useful for debugging later on tho. -impl Step, CompareDetoursStatus, (f64, f64)> - for CompareDetoursExecutionStepper -{ +impl Step, (f64, f64)> for CompareDetoursExecutionStepper { type Error = AutorouterError; fn step( &mut self, autorouter: &mut Autorouter, - ) -> Result { + ) -> Result, AutorouterError> { if self.done { - return Ok(CompareDetoursStatus::Finished( - self.total_length1, - self.total_length2, - )); + return Ok(ControlFlow::Break((self.total_length1, self.total_length2))); } match self.autoroute.step(autorouter)? { - AutorouteStatus::Running => Ok(CompareDetoursStatus::Running), - AutorouteStatus::Routed(band_termseg) => { + ControlFlow::Continue(AutorouteContinueStatus::Running) => { + Ok(ControlFlow::Continue(())) + } + ControlFlow::Continue(AutorouteContinueStatus::Routed(band_termseg)) => { let length = band_termseg .ref_(autorouter.board.layout().drawing()) .length(); @@ -95,22 +77,19 @@ impl Step, CompareDetoursStatus, (f64, f64)> self.total_length2 += length; } - Ok(CompareDetoursStatus::Running) + Ok(ControlFlow::Continue(())) } - AutorouteStatus::Finished => { + ControlFlow::Break(()) => { if let Some(next_autoroute) = self.next_autoroute.take() { autorouter.undo_autoroute_ratlines(vec![self.ratline1, self.ratline2])?; self.autoroute = next_autoroute; - Ok(CompareDetoursStatus::Running) + Ok(ControlFlow::Continue(())) } else { self.done = true; autorouter.undo_autoroute_ratlines(vec![self.ratline2, self.ratline1])?; - Ok(CompareDetoursStatus::Finished( - self.total_length1, - self.total_length2, - )) + Ok(ControlFlow::Break((self.total_length1, self.total_length2))) } } } diff --git a/src/autorouter/execution.rs b/src/autorouter/execution.rs index df6f272..dc4f288 100644 --- a/src/autorouter/execution.rs +++ b/src/autorouter/execution.rs @@ -1,12 +1,14 @@ +use std::ops::ControlFlow; + use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; use crate::{board::mesadata::AccessMesadata, layout::via::ViaWeight, stepper::Step}; use super::{ - autoroute::{AutorouteExecutionStepper, AutorouteStatus}, - compare_detours::{CompareDetoursExecutionStepper, CompareDetoursStatus}, - invoker::{Invoker, InvokerError, InvokerStatus}, + autoroute::AutorouteExecutionStepper, + compare_detours::CompareDetoursExecutionStepper, + invoker::{Invoker, InvokerError}, measure_length::MeasureLengthExecutionStepper, place_via::PlaceViaExecutionStepper, remove_bands::RemoveBandsExecutionStepper, @@ -38,28 +40,25 @@ impl ExecutionStepper { fn step_catch_err( &mut self, autorouter: &mut Autorouter, - ) -> Result { + ) -> Result, InvokerError> { Ok(match self { ExecutionStepper::Autoroute(autoroute) => match autoroute.step(autorouter)? { - AutorouteStatus::Running => InvokerStatus::Running, - AutorouteStatus::Routed(..) => InvokerStatus::Running, - AutorouteStatus::Finished => { - InvokerStatus::Finished("finished autorouting".to_string()) - } + ControlFlow::Continue(..) => ControlFlow::Continue(()), + ControlFlow::Break(..) => ControlFlow::Break("finished autorouting".to_string()), }, ExecutionStepper::PlaceVia(place_via) => { place_via.doit(autorouter)?; - InvokerStatus::Finished("finished placing via".to_string()) + ControlFlow::Break("finished placing via".to_string()) } ExecutionStepper::RemoveBands(remove_bands) => { remove_bands.doit(autorouter)?; - InvokerStatus::Finished("finished removing bands".to_string()) + ControlFlow::Break("finished removing bands".to_string()) } ExecutionStepper::CompareDetours(compare_detours) => { match compare_detours.step(autorouter)? { - CompareDetoursStatus::Running => InvokerStatus::Running, - CompareDetoursStatus::Finished(total_length1, total_length2) => { - InvokerStatus::Finished(format!( + ControlFlow::Continue(()) => ControlFlow::Continue(()), + ControlFlow::Break((total_length1, total_length2)) => { + ControlFlow::Break(format!( "total detour lengths are {} and {}", total_length1, total_length2 )) @@ -68,24 +67,24 @@ impl ExecutionStepper { } ExecutionStepper::MeasureLength(measure_length) => { let length = measure_length.doit(autorouter)?; - InvokerStatus::Finished(format!("Total length of selected bands: {}", length)) + ControlFlow::Break(format!("Total length of selected bands: {}", length)) } }) } } -impl Step, InvokerStatus, ()> for ExecutionStepper { +impl Step, String> for ExecutionStepper { type Error = InvokerError; - fn step(&mut self, invoker: &mut Invoker) -> Result { + fn step(&mut self, invoker: &mut Invoker) -> Result, InvokerError> { match self.step_catch_err(&mut invoker.autorouter) { - Ok(InvokerStatus::Running) => Ok(InvokerStatus::Running), - Ok(InvokerStatus::Finished(msg)) => { + Ok(ControlFlow::Continue(())) => Ok(ControlFlow::Continue(())), + Ok(ControlFlow::Break(msg)) => { if let Some(command) = invoker.ongoing_command.take() { invoker.history.do_(command); } - Ok(InvokerStatus::Finished(msg)) + Ok(ControlFlow::Break(msg)) } Err(err) => { invoker.ongoing_command = None; diff --git a/src/autorouter/invoker.rs b/src/autorouter/invoker.rs index aa96d68..29bae45 100644 --- a/src/autorouter/invoker.rs +++ b/src/autorouter/invoker.rs @@ -1,6 +1,6 @@ //! Manages the execution of routing commands within the autorouting system. -use std::cmp::Ordering; +use std::{cmp::Ordering, ops::ControlFlow}; use contracts_try::debug_requires; use derive_getters::{Dissolve, Getters}; @@ -46,12 +46,6 @@ pub trait GetObstacles { fn obstacles(&self) -> &[PrimitiveIndex]; } -#[derive(Debug, Clone)] -pub enum InvokerStatus { - Running, - Finished(String), -} - #[derive(Error, Debug, Clone)] pub enum InvokerError { #[error(transparent)] @@ -60,16 +54,6 @@ pub enum InvokerError { Autorouter(#[from] AutorouterError), } -impl TryInto<()> for InvokerStatus { - type Error = (); - fn try_into(self) -> Result<(), ()> { - match self { - InvokerStatus::Running => Err(()), - InvokerStatus::Finished(..) => Ok(()), - } - } -} - #[derive(Getters, Dissolve)] pub struct Invoker { pub(super) autorouter: Autorouter, @@ -95,12 +79,9 @@ impl Invoker { let mut execute = self.execute_stepper(command)?; loop { - let status = match execute.step(self) { - Ok(status) => status, - Err(err) => return Err(err), - }; + let status = execute.step(self)?; - if let InvokerStatus::Finished(..) = status { + if let ControlFlow::Break(..) = status { self.history.set_undone(std::iter::empty()); return Ok(()); } @@ -183,7 +164,7 @@ impl Invoker { Err(err) => return Err(err), }; - if let InvokerStatus::Finished(..) = status { + if let ControlFlow::Break(..) = status { return Ok(self.history.redo()?); } } diff --git a/src/bin/topola-egui/activity.rs b/src/bin/topola-egui/activity.rs index a5e299e..2b809f7 100644 --- a/src/bin/topola-egui/activity.rs +++ b/src/bin/topola-egui/activity.rs @@ -1,10 +1,11 @@ +use std::ops::ControlFlow; + use thiserror::Error; use topola::{ autorouter::{ execution::ExecutionStepper, invoker::{ GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles, Invoker, InvokerError, - InvokerStatus, }, }, board::mesadata::AccessMesadata, @@ -14,49 +15,13 @@ use topola::{ stepper::{Abort, Step}, }; -use crate::interaction::{ - InteractionContext, InteractionError, InteractionStatus, InteractionStepper, -}; +use crate::interaction::{InteractionContext, InteractionError, InteractionStepper}; pub struct ActivityContext<'a, M: AccessMesadata> { pub interaction: InteractionContext, pub invoker: &'a mut Invoker, } -#[derive(Debug, Clone)] -pub enum ActivityStatus { - Running, - Finished(String), -} - -impl From for ActivityStatus { - fn from(status: InteractionStatus) -> Self { - match status { - InteractionStatus::Running => ActivityStatus::Running, - InteractionStatus::Finished(msg) => ActivityStatus::Finished(msg), - } - } -} - -impl From for ActivityStatus { - fn from(status: InvokerStatus) -> Self { - match status { - InvokerStatus::Running => ActivityStatus::Running, - InvokerStatus::Finished(msg) => ActivityStatus::Finished(msg), - } - } -} - -impl TryInto<()> for ActivityStatus { - type Error = (); - fn try_into(self) -> Result<(), ()> { - match self { - ActivityStatus::Running => Err(()), - ActivityStatus::Finished(..) => Ok(()), - } - } -} - #[derive(Error, Debug, Clone)] pub enum ActivityError { #[error(transparent)] @@ -70,15 +35,18 @@ pub enum ActivityStepper { Execution(ExecutionStepper), } -impl Step, ActivityStatus, ()> for ActivityStepper { +impl Step, String> for ActivityStepper { type Error = ActivityError; - fn step(&mut self, context: &mut ActivityContext) -> Result { + fn step( + &mut self, + context: &mut ActivityContext, + ) -> Result, ActivityError> { match self { ActivityStepper::Interaction(interaction) => { - Ok(interaction.step(&mut context.interaction)?.into()) + Ok(interaction.step(&mut context.interaction)?) } - ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?.into()), + ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?), } } } @@ -87,9 +55,11 @@ impl Abort> for ActivityStepper { fn abort(&mut self, context: &mut ActivityContext) { match self { ActivityStepper::Interaction(interaction) => { - Ok(interaction.abort(&mut context.interaction)) + interaction.abort(&mut context.interaction) } - ActivityStepper::Execution(execution) => execution.finish(context.invoker), // TODO. + ActivityStepper::Execution(execution) => { + execution.finish(context.invoker); + } // TODO. }; } } @@ -136,7 +106,7 @@ impl GetObstacles for ActivityStepper { pub struct ActivityStepperWithStatus { activity: ActivityStepper, - maybe_status: Option, + maybe_status: Option>, } impl ActivityStepperWithStatus { @@ -147,17 +117,18 @@ impl ActivityStepperWithStatus { } } - pub fn maybe_status(&self) -> Option { + pub fn maybe_status(&self) -> Option> { self.maybe_status.clone() } } -impl Step, ActivityStatus, ()> - for ActivityStepperWithStatus -{ +impl Step, String> for ActivityStepperWithStatus { type Error = ActivityError; - fn step(&mut self, context: &mut ActivityContext) -> Result { + fn step( + &mut self, + context: &mut ActivityContext, + ) -> Result, ActivityError> { let status = self.activity.step(context)?; self.maybe_status = Some(status.clone()); Ok(status.into()) @@ -166,7 +137,7 @@ impl Step, ActivityStatus, ()> impl Abort> for ActivityStepperWithStatus { fn abort(&mut self, context: &mut ActivityContext) { - self.maybe_status = Some(ActivityStatus::Finished(String::from("aborted"))); + self.maybe_status = Some(ControlFlow::Break(String::from("aborted"))); self.activity.abort(context); } } diff --git a/src/bin/topola-egui/interaction.rs b/src/bin/topola-egui/interaction.rs index 434152c..42bfe29 100644 --- a/src/bin/topola-egui/interaction.rs +++ b/src/bin/topola-egui/interaction.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use thiserror::Error; use topola::{ autorouter::invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles}, @@ -13,22 +15,6 @@ pub struct InteractionContext { // (we will need an additional struct to hold a reference to a `Board<...>`) } -#[derive(Debug, Clone)] -pub enum InteractionStatus { - Running, - Finished(String), -} - -impl TryInto<()> for InteractionStatus { - type Error = (); - fn try_into(self) -> Result<(), ()> { - match self { - InteractionStatus::Running => Err(()), - InteractionStatus::Finished(..) => Ok(()), - } - } -} - #[derive(Error, Debug, Clone)] pub enum InteractionError { #[error("nothing to interact with")] @@ -42,14 +28,14 @@ pub enum InteractionStepper { // - interactively moving a footprint. } -impl Step for InteractionStepper { +impl Step for InteractionStepper { type Error = InteractionError; fn step( &mut self, context: &mut InteractionContext, - ) -> Result { - Ok(InteractionStatus::Finished(String::from(""))) + ) -> Result, InteractionError> { + Ok(ControlFlow::Break(String::from(""))) } } diff --git a/src/bin/topola-egui/interactor.rs b/src/bin/topola-egui/interactor.rs index 25f41df..b06ec93 100644 --- a/src/bin/topola-egui/interactor.rs +++ b/src/bin/topola-egui/interactor.rs @@ -13,7 +13,7 @@ use topola::{ }; use crate::{ - activity::{ActivityContext, ActivityError, ActivityStatus, ActivityStepperWithStatus}, + activity::{ActivityContext, ActivityError, ActivityStepperWithStatus}, interaction::InteractionContext, }; @@ -68,8 +68,8 @@ impl Interactor { interaction: InteractionContext {}, invoker: &mut self.invoker, }) { - Ok(ActivityStatus::Running) => ControlFlow::Continue(()), - Ok(ActivityStatus::Finished(..)) => ControlFlow::Break(Ok(())), + Ok(ControlFlow::Continue(())) => ControlFlow::Continue(()), + Ok(ControlFlow::Break(msg)) => ControlFlow::Break(Ok(())), Err(err) => { self.activity = None; ControlFlow::Break(Err(err)) diff --git a/src/bin/topola-egui/menu_bar.rs b/src/bin/topola-egui/menu_bar.rs index 2fcd088..2c1e5f0 100644 --- a/src/bin/topola-egui/menu_bar.rs +++ b/src/bin/topola-egui/menu_bar.rs @@ -1,4 +1,4 @@ -use std::{path::Path, sync::mpsc::Sender}; +use std::{ops::ControlFlow, path::Path, sync::mpsc::Sender}; use topola::{ autorouter::{ @@ -11,7 +11,7 @@ use topola::{ use crate::{ action::{Action, Switch, Trigger}, - activity::{ActivityContext, ActivityStatus, ActivityStepperWithStatus}, + activity::{ActivityContext, ActivityStepperWithStatus}, app::{execute, handle_file}, interaction::InteractionContext, translator::Translator, @@ -130,7 +130,7 @@ impl MenuBar { .maybe_activity() .as_ref() .map_or(true, |activity| { - matches!(activity.maybe_status(), Some(ActivityStatus::Finished(..))) + matches!(activity.maybe_status(), Some(ControlFlow::Break(..))) }), None => false, }; diff --git a/src/bin/topola-egui/status_bar.rs b/src/bin/topola-egui/status_bar.rs index 6ac9692..a1f318d 100644 --- a/src/bin/topola-egui/status_bar.rs +++ b/src/bin/topola-egui/status_bar.rs @@ -1,8 +1,6 @@ -use crate::{ - activity::{ActivityStatus, ActivityStepperWithStatus}, - translator::Translator, - viewport::Viewport, -}; +use std::ops::ControlFlow; + +use crate::{activity::ActivityStepperWithStatus, translator::Translator, viewport::Viewport}; pub struct StatusBar {} @@ -25,7 +23,7 @@ impl StatusBar { let mut message = String::from(""); if let Some(activity) = maybe_activity { - if let Some(ActivityStatus::Finished(msg)) = activity.maybe_status() { + if let Some(ControlFlow::Break(msg)) = activity.maybe_status() { message = msg; } } diff --git a/src/bin/topola-egui/workspace.rs b/src/bin/topola-egui/workspace.rs index b0b5fe6..f83dfb5 100644 --- a/src/bin/topola-egui/workspace.rs +++ b/src/bin/topola-egui/workspace.rs @@ -10,7 +10,7 @@ use topola::{ }; use crate::{ - activity::{ActivityContext, ActivityStatus, ActivityStepperWithStatus}, + activity::{ActivityContext, ActivityStepperWithStatus}, error_dialog::ErrorDialog, interaction::InteractionContext, interactor::Interactor, diff --git a/src/router/astar.rs b/src/router/astar.rs index ca51fc4..cb98c2e 100644 --- a/src/router/astar.rs +++ b/src/router/astar.rs @@ -8,6 +8,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::{BinaryHeap, HashMap, VecDeque}; use std::hash::Hash; +use std::ops::ControlFlow; use petgraph::algo::Measure; use petgraph::visit::{EdgeRef, GraphBase, IntoEdgeReferences, IntoEdges}; @@ -138,44 +139,19 @@ where pub is_probing: bool, } +#[derive(Debug)] +pub enum AstarContinueStatus { + Probing, + Probed, + Visited, +} + #[derive(Error, Debug, Clone)] pub enum AstarError { #[error("A* search found no path")] NotFound, } -#[derive(Debug)] -pub enum AstarStatus -where - G: GraphBase, - G::NodeId: Eq + Hash, - for<'a> &'a G: IntoEdges + MakeEdgeRef, - K: Measure + Copy, -{ - Probing, - Probed, - Visited, - Finished(K, Vec, R), -} - -impl TryInto<(K, Vec, R)> for AstarStatus -where - G: GraphBase, - G::NodeId: Eq + Hash, - for<'a> &'a G: IntoEdges + MakeEdgeRef, - K: Measure + Copy, -{ - type Error = (); - fn try_into(self) -> Result<(K, Vec, R), ()> { - match self { - AstarStatus::Probing => Err(()), - AstarStatus::Probed => Err(()), - AstarStatus::Visited => Err(()), - AstarStatus::Finished(cost, path, result) => Ok((cost, path, result)), - } - } -} - impl Astar where G: GraphBase, @@ -203,7 +179,7 @@ where } } -impl> Step, (K, Vec, R)> +impl> Step, R), AstarContinueStatus> for Astar where G: GraphBase, @@ -213,7 +189,10 @@ where { type Error = AstarError; - fn step(&mut self, strategy: &mut S) -> Result, AstarError> { + fn step( + &mut self, + strategy: &mut S, + ) -> Result, R), AstarContinueStatus>, AstarError> { if let Some(curr_node) = self.maybe_curr_node { if self.is_probing { strategy.remove_probe(&self.graph); @@ -235,7 +214,7 @@ where // No need to add neighbors that we have already reached through a // shorter path than now. if *entry.get() <= next_score { - return Ok(AstarStatus::Probed); + return Ok(ControlFlow::Continue(AstarContinueStatus::Probed)); } entry.insert(next_score); } @@ -250,10 +229,10 @@ where self.visit_next.push(MinScored(next_estimate_score, next)); self.is_probing = true; - return Ok(AstarStatus::Probing); + return Ok(ControlFlow::Continue(AstarContinueStatus::Probing)); } - return Ok(AstarStatus::Probed); + return Ok(ControlFlow::Continue(AstarContinueStatus::Probed)); } self.maybe_curr_node = None; @@ -266,7 +245,7 @@ where if let Some(result) = strategy.is_goal(&self.graph, node, &self.path_tracker) { let path = self.path_tracker.reconstruct_path_to(node); let cost = self.scores[&node]; - return Ok(AstarStatus::Finished(cost, path, result)); + return Ok(ControlFlow::Break((cost, path, result))); } match self.estimate_scores.entry(node) { @@ -274,7 +253,7 @@ where // If the node has already been visited with an equal or lower score than // now, then we do not need to re-visit it. if *entry.get() <= estimate_score { - return Ok(AstarStatus::Visited); + return Ok(ControlFlow::Continue(AstarContinueStatus::Visited)); } entry.insert(estimate_score); } @@ -286,6 +265,6 @@ where self.maybe_curr_node = Some(node); self.edge_ids = self.graph.edges(node).map(|edge| edge.id()).collect(); - Ok(AstarStatus::Visited) + Ok(ControlFlow::Continue(AstarContinueStatus::Visited)) } } diff --git a/src/router/route.rs b/src/router/route.rs index b2e14e9..24eef0c 100644 --- a/src/router/route.rs +++ b/src/router/route.rs @@ -1,14 +1,16 @@ +use std::ops::ControlFlow; + use crate::{ drawing::{ band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules, }, geometry::primitive::PrimitiveShape, router::{ - astar::{Astar, AstarError, AstarStatus}, + astar::{Astar, AstarError}, navcord::NavcordStepper, navcorder::Navcorder, navmesh::{Navmesh, NavmeshError}, - Router, RouterAstarStrategy, RouterStatus, + Router, RouterAstarStrategy, }, stepper::Step, }; @@ -73,19 +75,20 @@ impl RouteStepper { } } -impl<'a, R: AccessRules> Step, RouterStatus, BandTermsegIndex> for RouteStepper { +impl<'a, R: AccessRules> Step, BandTermsegIndex> for RouteStepper { type Error = AstarError; - fn step(&mut self, router: &mut Router) -> Result { + fn step( + &mut self, + router: &mut Router, + ) -> Result, AstarError> { let navcorder = Navcorder::new(router.layout_mut()); let target = self.astar.graph.destination(); let mut strategy = RouterAstarStrategy::new(navcorder, &mut self.navcord, target); let result = match self.astar.step(&mut strategy)? { - AstarStatus::Probing | AstarStatus::Probed | AstarStatus::Visited => { - Ok(RouterStatus::Running) - } - AstarStatus::Finished(_cost, _path, band) => Ok(RouterStatus::Finished(band)), + ControlFlow::Continue(..) => Ok(ControlFlow::Continue(())), + ControlFlow::Break((_cost, _path, band)) => Ok(ControlFlow::Break(band)), }; self.ghosts = strategy.probe_ghosts; diff --git a/src/router/router.rs b/src/router/router.rs index 82abb71..5a20e4d 100644 --- a/src/router/router.rs +++ b/src/router/router.rs @@ -36,22 +36,6 @@ pub struct RouterOptions { pub squeeze_through_under_bands: bool, } -#[derive(Debug)] -pub enum RouterStatus { - Running, - Finished(BandTermsegIndex), -} - -impl TryInto for RouterStatus { - type Error = (); - fn try_into(self) -> Result { - match self { - RouterStatus::Running => Err(()), - RouterStatus::Finished(band_termseg) => Ok(band_termseg), - } - } -} - #[derive(Debug)] pub struct RouterAstarStrategy<'a, R: AccessRules> { pub navcorder: Navcorder<'a, R>, diff --git a/src/stepper.rs b/src/stepper.rs index 01a8218..e38cef3 100644 --- a/src/stepper.rs +++ b/src/stepper.rs @@ -1,11 +1,13 @@ -pub trait Step, O> { +use std::ops::ControlFlow; + +pub trait Step { type Error; - fn step(&mut self, context: &mut C) -> Result; + fn step(&mut self, context: &mut Ctx) -> Result, Self::Error>; - fn finish(&mut self, context: &mut C) -> Result { + fn finish(&mut self, context: &mut Ctx) -> Result { loop { - if let Ok(outcome) = self.step(context)?.try_into() { + if let ControlFlow::Break(outcome) = self.step(context)? { return Ok(outcome); } }