#![allow(clippy::print_stdout, clippy::enum_glob_use)]
use ready_active_safe::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq)]
enum Mode {
Ready,
Active,
Safe,
}
impl core::fmt::Display for Mode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{self:?}")
}
}
#[derive(Debug)]
enum Event {
Initialize,
Start,
Fault,
}
#[derive(Debug, PartialEq)]
enum Command {
RunDiagnostics,
BeginProcessing,
FlushBuffers,
NotifyOperator,
}
struct Controller;
impl Machine for Controller {
type Mode = Mode;
type Event = Event;
type Command = Command;
fn initial_mode(&self) -> Mode {
Mode::Ready
}
fn on_event(
&self,
mode: &Self::Mode,
event: &Self::Event,
) -> Decision<Self::Mode, Self::Command> {
use Command::*;
use Event::*;
use Mode::*;
match (mode, event) {
(Ready, Initialize) => stay().emit(RunDiagnostics),
(Ready, Start) => transition(Active).emit(BeginProcessing),
(Active, Fault) => transition(Safe).emit_all([FlushBuffers, NotifyOperator]),
_ => ignore(),
}
}
}
fn main() {
let controller = Controller;
let mut mode = controller.initial_mode();
let events = [Event::Initialize, Event::Start, Event::Fault];
for event in &events {
let decision = controller.decide(&mode, event);
println!("{mode:?} + {event:?} => {decision}");
let (next_mode, commands) = decision.apply(mode);
if !commands.is_empty() {
println!(" commands: {commands:?}");
}
mode = next_mode;
}
assert_eq!(mode, Mode::Safe);
}