# Free Functions
Convenience wrappers that make `match` arms read like sentences.
## `stay()` — remain in the current mode
```rust
use ready_active_safe::prelude::*;
let d: Decision<&str, ()> = stay();
assert!(d.is_stay());
assert!(d.target_mode().is_none());
assert!(d.commands().is_empty());
```
## `transition(target)` — move to a new mode
```rust
use ready_active_safe::prelude::*;
let d: Decision<&str, ()> = transition("active");
assert!(d.is_transition());
assert_eq!(d.target_mode(), Some(&"active"));
```
## `ignore()` — deliberate no-op
Semantically identical to `stay()`, but communicates intent. Use in catch-all
arms to signal that silence is by design, not an oversight.
```rust
use ready_active_safe::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq)]
enum Mode { Ready, Active }
#[derive(Debug)]
enum Event { Start, Ping }
struct System;
impl Machine for System {
type Mode = Mode;
type Event = Event;
type Command = ();
fn initial_mode(&self) -> Mode { Mode::Ready }
fn on_event(&self, mode: &Mode, event: &Event) -> Decision<Mode, ()> {
match (mode, event) {
(Mode::Ready, Event::Start) => transition(Mode::Active),
_ => ignore(), // deliberate: these events need no response
}
}
}
let system = System;
let d = system.decide(&Mode::Active, &Event::Ping);
assert!(d.is_stay());
```
## `apply_decision(current_mode, decision)` — consume and apply
```rust
use ready_active_safe::prelude::*;
let decision: Decision<&str, &str> = transition("active").emit("init");
let (mode, commands) = apply_decision("ready", decision);
assert_eq!(mode, "active");
assert_eq!(commands, vec!["init"]);
```
Stay decisions return the current mode unchanged:
```rust
use ready_active_safe::prelude::*;
let decision: Decision<&str, ()> = stay();
let (mode, commands) = apply_decision("ready", decision);
assert_eq!(mode, "ready");
assert!(commands.is_empty());
```
## `apply_decision_checked(current_mode, decision, policy)` — apply with guard
```rust
use ready_active_safe::prelude::*;
let decision: Decision<&str, &str> = transition("active").emit("go");
let (mode, commands) = apply_decision_checked("ready", decision, &AllowAll)?;
assert_eq!(mode, "active");
assert_eq!(commands, vec!["go"]);
let decision: Decision<&str, &str> = transition("active");
let err = apply_decision_checked("ready", decision, &DenyAll).unwrap_err();
assert!(matches!(err, LifecycleError::TransitionDenied { .. }));
# Ok::<(), LifecycleError<&str>>(())
```
## See Also
- [`Decision`](decision.md) — the type these functions create
- [`Machine`](machine.md) — uses these in `on_event` match arms