use anyhow::{ensure, Result}; use derive_more::From; use rand::Rng; use serde::{Deserialize, Serialize}; use step_machine::{Engine, State}; type StepResult = Result>; fn main() -> Result<()> { env_logger::init(); let init_state = FirstToss.into(); let mut engine = Engine::::new(init_state)?.restore()?; engine.drop_error()?; engine.run()?; Ok(()) } #[derive(Debug, Serialize, Deserialize, PartialEq)] enum Coin { Heads, Tails, } impl Coin { fn toss() -> Self { if rand::thread_rng().gen::() { Coin::Heads } else { Coin::Tails } } } #[derive(Debug, Serialize, Deserialize, From)] enum Machine { FirstToss(FirstToss), SecondToss(SecondToss), } impl State for Machine { type Error = anyhow::Error; fn next(self) -> StepResult { match self { Machine::FirstToss(state) => state.next(), Machine::SecondToss(state) => state.next(), } } } #[derive(Debug, Serialize, Deserialize)] struct FirstToss; impl FirstToss { fn next(self) -> StepResult { let first_coin = Coin::toss(); println!("First coin: {:?}", first_coin); Ok(Some(SecondToss { first_coin }.into())) } } #[derive(Debug, Serialize, Deserialize)] struct SecondToss { first_coin: Coin, } impl SecondToss { fn next(self) -> StepResult { let second_coin = Coin::toss(); println!("Second coin: {:?}", second_coin); ensure!(second_coin == self.first_coin, "Coins landed differently"); println!("Coins match"); Ok(None) } }