recovery_cycle/
recovery_cycle.rs1#![allow(clippy::print_stdout, clippy::enum_glob_use)]
8
9use ready_active_safe::prelude::*;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12enum Mode {
13 Ready,
14 Active,
15 Safe,
16}
17
18impl core::fmt::Display for Mode {
19 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20 write!(f, "{self:?}")
21 }
22}
23
24#[derive(Debug)]
25enum Event {
26 Activate,
27 Fault,
28 RecoveryComplete,
29}
30
31#[derive(Debug, PartialEq)]
32enum Command {
33 StartWork,
34 EnterSafeState,
35 ResetHardware,
36}
37
38struct RecoverableSystem;
39
40impl Machine for RecoverableSystem {
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(&self, mode: &Mode, event: &Event) -> Decision<Mode, Command> {
50 use Command::*;
51 use Event::*;
52 use Mode::*;
53
54 match (mode, event) {
55 (Ready, Activate) => transition(Active).emit(StartWork),
56 (Active, Fault) => transition(Safe).emit(EnterSafeState),
57 (Safe, RecoveryComplete) => transition(Ready).emit(ResetHardware),
58 _ => ignore(),
59 }
60 }
61}
62
63fn main() {
64 let system = RecoverableSystem;
65 let mut runner = Runner::new(&system);
66 let max_recoveries: u32 = 3;
67 let mut recovery_count: u32 = 0;
68
69 println!("Starting in {:?}", runner.mode());
70
71 loop {
73 runner.feed_and_dispatch(&Event::Activate, |cmd| {
75 println!(" dispatch: {cmd:?}");
76 });
77 println!("Mode: {:?}", runner.mode());
78
79 runner.feed_and_dispatch(&Event::Fault, |cmd| {
81 println!(" dispatch: {cmd:?}");
82 });
83 println!("Mode: {:?} (fault!)", runner.mode());
84
85 recovery_count = recovery_count.saturating_add(1);
86 println!("Recovery #{recovery_count}");
87
88 if recovery_count >= max_recoveries {
89 println!("Max recoveries ({max_recoveries}) reached, staying in Safe.");
90 break;
91 }
92
93 runner.feed_and_dispatch(&Event::RecoveryComplete, |cmd| {
95 println!(" dispatch: {cmd:?}");
96 });
97 println!("Mode: {:?} (recovered)", runner.mode());
98 }
99
100 println!(
101 "Final mode: {:?}, total recoveries: {recovery_count}",
102 runner.mode()
103 );
104 assert_eq!(runner.mode(), &Mode::Safe);
105 assert_eq!(recovery_count, max_recoveries);
106}