1#![allow(clippy::print_stdout, clippy::enum_glob_use)]
7
8use ready_active_safe::prelude::*;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11enum Mode {
12 Ready,
13 Active,
14 Safe,
15}
16
17impl core::fmt::Display for Mode {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 write!(f, "{self:?}")
20 }
21}
22
23#[derive(Debug)]
24enum Event {
25 Initialize,
26 Start,
27 Fault,
28}
29
30#[derive(Debug, PartialEq)]
31enum Command {
32 RunDiagnostics,
33 BeginProcessing,
34 FlushBuffers,
35 NotifyOperator,
36}
37
38struct Controller;
39
40impl Machine for Controller {
41 type Mode = Mode;
42 type Event = Event;
43 type Command = Command;
44
45 fn initial_mode(&self) -> Mode {
46 Mode::Ready
47 }
48
49 fn on_event(
50 &self,
51 mode: &Self::Mode,
52 event: &Self::Event,
53 ) -> Decision<Self::Mode, Self::Command> {
54 use Command::*;
55 use Event::*;
56 use Mode::*;
57
58 match (mode, event) {
59 (Ready, Initialize) => stay().emit(RunDiagnostics),
60 (Ready, Start) => transition(Active).emit(BeginProcessing),
61 (Active, Fault) => transition(Safe).emit_all([FlushBuffers, NotifyOperator]),
62 _ => ignore(),
63 }
64 }
65}
66
67fn main() {
68 let controller = Controller;
69 let mut mode = controller.initial_mode();
70
71 let events = [Event::Initialize, Event::Start, Event::Fault];
72
73 for event in &events {
74 let decision = controller.decide(&mode, event);
75 println!("{mode:?} + {event:?} => {decision}");
76
77 let (next_mode, commands) = decision.apply(mode);
78 if !commands.is_empty() {
79 println!(" commands: {commands:?}");
80 }
81
82 mode = next_mode;
83 }
84
85 assert_eq!(mode, Mode::Safe);
86}