Open ryo33 opened 3 weeks ago
#[narrative::story("a sample story")]
trait SampleStory {
#[step("aaaa")]
fn aaaa();
#[sub_story("do the following steps")]
fn run_substory<T: MySubStory>(a: MySubStory);
}
impl SampleStory for MyEnv {
type Error = ();
fn aaaa(&mut self) -> Result<(), Self::Error> {
todo!()
}
type MySubStory = MySubStoryEnv; // where MySubStory: MySubStory<Error = Into<Self::Error>>
// default implementation is provided automatically but overridable.
// fn run_substory(a: Self::MySubStory) -> Result<(), Self::Error> {
// Ok(a.run_all()?)
// }
}
Steps in the sub-story are flattened with other normal steps in the story context API. The caller can refer to the parent step by calling a Step::parent_step(&self) -> Option<Step>
in the Step
trait.
Compared to the Step::sub_steps(&self) -> &[Step]
approach, it prevents users from forgetting to run steps in the substory. Users can still know the hierarchy by calling step.parent_step()
. Or it may be an option to have a dedicated new API for users who want to know the hierarchy.
To preserve the run_all
functionality, we need to identify a concrete implementation for each sub story in a implementation of the super story.
Should we treat nestable stories as special to prevent misuse by users? (e.g. making it impossible to implement the story as a regular story)