diff options
Diffstat (limited to 'subplotlib/src/step.rs')
-rw-r--r-- | subplotlib/src/step.rs | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/subplotlib/src/step.rs b/subplotlib/src/step.rs index bbea249..76b9193 100644 --- a/subplotlib/src/step.rs +++ b/subplotlib/src/step.rs @@ -10,6 +10,8 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use crate::scenario::{Scenario, ScenarioContext}; use crate::types::StepResult; +type StepFunc = dyn Fn(&ScenarioContext, bool) -> StepResult; + /// A ScenarioStep is one step in a scenario. /// /// In essence, a scenario step is a named closure. Its name can be used when @@ -23,12 +25,13 @@ use crate::types::StepResult; /// # use subplotlib::prelude::*; /// /// let step = ScenarioStep::new( -/// "when everything works".to_string(), |ctx, ok| Ok(()), |scen| () +/// "when everything works".to_string(), |ctx, ok| Ok(()), |scen| (), "unknown" /// ); /// ``` pub struct ScenarioStep { step_text: String, - func: Box<dyn Fn(&ScenarioContext, bool) -> StepResult>, + location: &'static str, + func: Box<StepFunc>, reg: Box<dyn Fn(&Scenario)>, } @@ -38,13 +41,14 @@ impl ScenarioStep { /// This is used to construct a scenario step from a function which /// takes the scenario context container. This will generally be /// called from the generated build method for the step. - pub fn new<F, R>(step_text: String, func: F, reg: R) -> Self + pub fn new<F, R>(step_text: String, func: F, reg: R, location: &'static str) -> Self where F: Fn(&ScenarioContext, bool) -> StepResult + 'static, R: Fn(&Scenario) + 'static, { Self { step_text, + location, func: Box::new(func), reg: Box::new(reg), } @@ -53,13 +57,13 @@ impl ScenarioStep { /// Attempt to render a message. /// If something panics with a type other than a static string or /// a formatted string then we won't be able to render it sadly. - fn render_panic(name: &str, err: Box<dyn Any + Send>) -> String { + fn render_panic(location: &str, name: &str, err: Box<dyn Any + Send>) -> String { if let Some(msg) = err.downcast_ref::<&str>() { - format!("step {} panic'd: {}", name, msg) + format!("{location}: step {name} panic'd: {msg}") } else if let Some(msg) = err.downcast_ref::<String>() { - format!("step {} panic'd: {}", name, msg) + format!("{location}: step {name} panic'd: {msg}") } else { - format!("step {} panic'd", name) + format!("{location}: step {name} panic'd") } } @@ -71,7 +75,7 @@ impl ScenarioStep { // subsequent step calls may not be sound. There's not a lot we can // do to ensure things are good except try. let func = AssertUnwindSafe(|| (*self.func)(context, defuse_poison)); - catch_unwind(func).map_err(|e| Self::render_panic(self.step_text(), e))? + catch_unwind(func).map_err(|e| Self::render_panic(self.location(), self.step_text(), e))? } /// Return the full text of this step @@ -83,4 +87,8 @@ impl ScenarioStep { pub(crate) fn register_contexts(&self, scenario: &Scenario) { (*self.reg)(scenario); } + + pub(crate) fn location(&self) -> &'static str { + self.location + } } |