#[rust_sfsm]Expand description
§Rust-SFSM Attribute Macro.
SFSM stands for Static Finite State Machine.
This macro must be used on struct’s and implements
the boilerplate for any type that has a state-like behavior.
§Example
use rust_sfsm::{StateBehavior, StateMachine, rust_sfsm};
/// List of protocol states.
#[derive(Clone, Copy, Default, PartialEq)]
enum States {
#[default]
Init,
Opened,
Closed,
Locked,
}
/// List of protocol events.
enum Events {
Create,
Open,
Close,
Lock,
Unlock,
}
/// Protocol state machine context (data shared between states).
#[derive(Default)]
struct Context {
lock_counter: u16,
}
impl StateBehavior for States {
type State = Self;
type Event<'a> = Events;
type Context = Context;
fn enter(&self, _context: &mut Self::Context) {
if self == &States::Locked {
_context.lock_counter += 1
}
}
fn handle_event(
&self,
event: &Self::Event<'_>,
_context: &mut Self::Context,
) -> Option<Self::State> {
match (self, event) {
(&States::Init, &Events::Create) => Some(States::Opened),
(&States::Opened, &Events::Close) => Some(States::Closed),
(&States::Closed, &Events::Open) => Some(States::Opened),
(&States::Closed, &Events::Lock) => Some(States::Locked),
(&States::Locked, &Events::Unlock) => Some(States::Closed),
_ => None,
}
}
}
#[rust_sfsm(states = States, context = Context)]
struct Protocol {}
impl Protocol {
fn new() -> Self {
Self {
current_state: Default::default(),
context: Default::default(),
}
}
}§Macro Expansion
The rust_sfsm macro expands to this:
struct Protocol {
current_state: States,
context: Context,
}
impl ::rust_sfsm::StateMachine<States> for Protocol {
fn current_state(&self) -> <States as ::rust_sfsm::StateBehavior>::State {
self.current_state
}
fn handle_event(
&mut self,
event: &<States as ::rust_sfsm::StateBehavior>::Event<'_>,
) {
if let Some(next_state) = self
.current_state
.handle_event(event, &mut self.context)
{
self.transit(next_state)
}
}
fn transit(&mut self, new_state: <States as ::rust_sfsm::StateBehavior>::State) {
self.current_state.exit(&mut self.context);
self.current_state = new_state;
self.current_state.enter(&mut self.context);
}
fn force_state(&mut self, new_state: <States as ::rust_sfsm::StateBehavior>::State) {
self.current_state = new_state;
}
}