# Machine
A pure function from `(mode, event)` to [`Decision`](decision.md).
`Machine` is the central trait of the lifecycle engine. Implementations define
how the system responds to events in each mode. The trait is deliberately minimal:
no `self` mutation, no time parameter, no I/O.
## Associated Types
- `Mode` — the set of lifecycle phases (e.g. Ready, Active, Safe)
- `Event` — external stimuli the system can receive
- `Command` — instructions for the runtime to execute
## Example
```rust
use ready_active_safe::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq)]
enum Mode { Ready, Active, Safe }
#[derive(Debug)]
enum Event { Start, Stop, Fault }
#[derive(Debug, Clone, PartialEq, Eq)]
enum Command { Initialize, Shutdown }
struct System;
impl Machine for System {
type Mode = Mode;
type Event = Event;
type Command = Command;
fn initial_mode(&self) -> Mode { Mode::Ready }
fn on_event(&self, mode: &Mode, event: &Event) -> Decision<Mode, Command> {
match (mode, event) {
(Mode::Ready, Event::Start) => transition(Mode::Active).emit(Command::Initialize),
(Mode::Active, Event::Stop | Event::Fault) => transition(Mode::Safe).emit(Command::Shutdown),
_ => ignore(),
}
}
}
let system = System;
assert_eq!(system.initial_mode(), Mode::Ready);
```
## `decide` — alias for `on_event`
```rust
# use ready_active_safe::prelude::*;
# #[derive(Debug, Clone, PartialEq, Eq)]
# enum Mode { Ready, Active, Safe }
# #[derive(Debug)]
# enum Event { Start, Stop, Fault }
# #[derive(Debug, Clone, PartialEq, Eq)]
# enum Command { Initialize, Shutdown }
# struct System;
# impl Machine for System {
# type Mode = Mode;
# type Event = Event;
# type Command = Command;
# fn initial_mode(&self) -> Mode { Mode::Ready }
# fn on_event(&self, mode: &Mode, event: &Event) -> Decision<Mode, Command> {
# match (mode, event) {
# (Mode::Ready, Event::Start) => transition(Mode::Active).emit(Command::Initialize),
# (Mode::Active, Event::Stop | Event::Fault) => transition(Mode::Safe).emit(Command::Shutdown),
# _ => ignore(),
# }
# }
# }
let system = System;
let d = system.decide(&Mode::Ready, &Event::Start);
assert_eq!(d.target_mode(), Some(&Mode::Active));
```
## `step` — decide + apply in one call
```rust
# use ready_active_safe::prelude::*;
# #[derive(Debug, Clone, PartialEq, Eq)]
# enum Mode { Ready, Active, Safe }
# #[derive(Debug)]
# enum Event { Start, Stop, Fault }
# #[derive(Debug, Clone, PartialEq, Eq)]
# enum Command { Initialize, Shutdown }
# struct System;
# impl Machine for System {
# type Mode = Mode;
# type Event = Event;
# type Command = Command;
# fn initial_mode(&self) -> Mode { Mode::Ready }
# fn on_event(&self, mode: &Mode, event: &Event) -> Decision<Mode, Command> {
# match (mode, event) {
# (Mode::Ready, Event::Start) => transition(Mode::Active).emit(Command::Initialize),
# (Mode::Active, Event::Stop | Event::Fault) => transition(Mode::Safe).emit(Command::Shutdown),
# _ => ignore(),
# }
# }
# }
let system = System;
let (mode, commands) = system.step(Mode::Ready, &Event::Start);
assert_eq!(mode, Mode::Active);
assert_eq!(commands, vec![Command::Initialize]);
```
## `step_checked` — decide + apply with policy
```rust
# use ready_active_safe::prelude::*;
# #[derive(Debug, Clone, PartialEq, Eq)]
# enum Mode { Ready, Active, Safe }
# #[derive(Debug)]
# enum Event { Start, Stop, Fault }
# #[derive(Debug, Clone, PartialEq, Eq)]
# enum Command { Initialize, Shutdown }
# struct System;
# impl Machine for System {
# type Mode = Mode;
# type Event = Event;
# type Command = Command;
# fn initial_mode(&self) -> Mode { Mode::Ready }
# fn on_event(&self, mode: &Mode, event: &Event) -> Decision<Mode, Command> {
# match (mode, event) {
# (Mode::Ready, Event::Start) => transition(Mode::Active).emit(Command::Initialize),
# (Mode::Active, Event::Stop | Event::Fault) => transition(Mode::Safe).emit(Command::Shutdown),
# _ => ignore(),
# }
# }
# }
let system = System;
// Allowed
let (mode, cmds) = system.step_checked(Mode::Ready, &Event::Start, &AllowAll)?;
assert_eq!(mode, Mode::Active);
// Denied
let err = system.step_checked(Mode::Ready, &Event::Start, &DenyAll).unwrap_err();
assert!(matches!(err, LifecycleError::TransitionDenied { .. }));
# Ok::<(), LifecycleError<Mode>>(())
```
## See Also
- [`Decision`](decision.md) — the return type of `on_event`
- [`Policy`](policy.md) — transition guards used by `step_checked`
- [`Runner`](runner.md) — owns mode and feeds events in a loop