Macro statemachine
statemachine!() { /* proc-macro */ }
Expand description
Defines a state machine’s initial state and its allowed transitions. Optionally, a state machine enum type can be generated. Example:
statemachine!(
() => A,
A => B,
B => [C, A],
C => A
);
Example using generics and lifetimes:
statemachine!(
() => A<T>,
A<T> => B<'a, T2>,
B<'a, T2> => [A<T>, C]
);
If a generic parameter is supplied for a particular state, an identical parameter must be
supplied for all other instances of that state. E.g. a single state machine may not include
both A<T>
and A<T2>
as states.
Example to also generate optional enum type:
statemachine!(
#derive(Debug, PartialEq)
pub enum Client,
() => A,
A => B,
B => [C, A],
C => A
);
The following enum will be generated for this example:
#derive(Debug, PartialEq)
pub enum Client {
A(State<A>),
B(State<B>),
C(State<C>),
}
// From impls are also generated to wrap states in the generate enum.
impl From<State<A>> for Client {
...
}
If a state machine enum is generated, additional enums for state transitions are generated. This is particularly useful to keep state transition and business logic separated, example:
fn authenticate(auth: AuthHdr) -> AuthenticatingTransition {
if auth.result == ResultCode::SUCCESS {
...
AuthenticatingTransition::ToAuthenticated(data)
} else {
...
AuthenticatingTransition::ToIdle(data)
}
}
fn on_mac_frame(state: States, frame: Frame) -> Sates {
...
let transition = authenticate(auth);
let next_state = state.apply(transition);
...
}