use edfsm::{impl_fsm, Fsm, Input};
struct Idle;
struct Running;
enum State {
Idle(Idle),
Running(Running),
}
struct Start;
struct Stop;
enum Command {
Start(Start),
Stop(Stop),
}
struct Started;
struct Stopped;
enum Event {
Started(Started),
Stopped(Stopped),
}
struct EffectHandlers {
started: u32,
stopped: u32,
transitioned_stopped_to_started: u32,
}
impl EffectHandlers {
pub fn start_something(&mut self) {
self.started += 1;
}
pub fn stop_something(&mut self) {
self.stopped += 1;
}
pub fn enter_running(&mut self) {
self.transitioned_stopped_to_started += 1;
}
}
struct MyFsm;
#[impl_fsm]
impl Fsm for MyFsm {
type S = State;
type C = Command;
type E = Event;
type SE = EffectHandlers;
state!(Running / entry);
command!(Idle => Start => Started => Running);
command!(Running => Stop => Stopped => Idle);
ignore_command!(Idle => Stop);
ignore_command!(Running => Start);
}
impl MyFsm {
fn on_entry_running(_to_s: &Running, se: &mut EffectHandlers) {
se.enter_running()
}
fn for_running_stop(_s: &Running, _c: Stop, se: &mut EffectHandlers) -> Option<Stopped> {
se.stop_something();
Some(Stopped)
}
fn on_running_stopped(_s: &Running, _e: &Stopped) -> Option<Idle> {
Some(Idle)
}
fn for_idle_start(_s: &Idle, _c: Start, se: &mut EffectHandlers) -> Option<Started> {
se.start_something();
Some(Started)
}
fn on_idle_started(_s: &Idle, _e: &Started) -> Option<Running> {
Some(Running)
}
}
#[test]
fn main() {
let mut se = EffectHandlers {
started: 0,
stopped: 0,
transitioned_stopped_to_started: 0,
};
let e = MyFsm::step(
&mut State::Idle(Idle),
Input::Command(Command::Start(Start)),
&mut se,
);
assert!(matches!(e, Some(Event::Started(Started))));
assert_eq!(se.started, 1);
assert_eq!(se.stopped, 0);
assert_eq!(se.transitioned_stopped_to_started, 1);
let e = MyFsm::step(
&mut State::Running(Running),
Input::Command(Command::Start(Start)),
&mut se,
);
assert!(e.is_none());
assert_eq!(se.started, 1);
assert_eq!(se.stopped, 0);
assert_eq!(se.transitioned_stopped_to_started, 1);
let e = MyFsm::step(
&mut State::Running(Running),
Input::Command(Command::Stop(Stop)),
&mut se,
);
assert!(matches!(e, Some(Event::Stopped(Stopped))));
assert_eq!(se.started, 1);
assert_eq!(se.stopped, 1);
assert_eq!(se.transitioned_stopped_to_started, 1);
let e = MyFsm::step(
&mut State::Idle(Idle),
Input::Command(Command::Stop(Stop)),
&mut se,
);
assert!(e.is_none());
assert_eq!(se.started, 1);
assert_eq!(se.stopped, 1);
assert_eq!(se.transitioned_stopped_to_started, 1);
}