use ironstate::prelude::*;
#[derive(Clone, Debug, Default, PartialEq)]
struct Reviewer(String);
#[derive(StateMachine, Clone, Debug, PartialEq)]
#[state_machine(initial = Draft, terminal = [Archived])]
enum Article {
Draft,
Review {
by: Reviewer,
rounds: u32,
},
Rejected(Reviewer),
Archived,
}
#[derive(Event, Clone, Debug, PartialEq)]
enum Edit {
Submit,
Assign(Reviewer),
Reject { reason: u32 },
Archive,
}
impl TransitionRules for Article {
type Event = Edit;
fn transition(&self, event: &Edit) -> Option<Article> {
match (self, event) {
(Article::Draft, Edit::Submit) => Some(Article::Review {
by: Reviewer::default(),
rounds: 0,
}),
(Article::Review { by, .. }, Edit::Reject { .. }) => {
Some(Article::Rejected(by.clone()))
}
(Article::Rejected(_), Edit::Archive) => Some(Article::Archived),
_ => None,
}
}
}
ironstate::analyze!(Article);
#[test]
fn data_carrying_variants_need_default_only_on_their_payloads() {
let mut machine = Machine::<Article>::new();
assert_eq!(machine.state(), &Article::Draft);
machine.apply(Edit::Submit).expect("Draft -> Review");
assert!(matches!(machine.state(), Article::Review { .. }));
}