Hello rustaceans!
I have been inspired by a few articles I have read and some recent projects that would benefit from the use of State Machines.
So I have decided to try my hand at writing a few.
The design goals of this one (Github Link) were to have:
- Transitions that are checked at compile time
- States wrapped in an enum for flexibility
- Clear and easy to use interface
- Linear State Machine with an Error State (Safety Cut Out State - accessible from any other state)
Transitions checked at compile time
(inspired by Pretty State Machine Pattern - Blog Post)
Example:
impl From<GlorifiedKettle<Heating>> for GlorifiedKettle<Emptying> {
fn from(val: GlorifiedKettle<Heating>) -> GlorifiedKettle<Emptying> {
GlorifiedKettle {
current_level: val.current_level,
current_temperature: val.current_temperature,
state: Emptying { end_level: EMPTY },
}
}
}
States wrapped in an enum for flexibility
let mut state = States::Filling(GlorifiedKettle::new());
Clear and easy to use interface
The main() function can call the state machine using
state.run()
& check if the end condition for the transition is met using state.is_end_condition_met()
and then transition state.step()
Linear State Machine with an Error State
Error state can be entered from any state (if an Error condition is encountered) or could be integrated into an ISR. The transition is called by state.error()
Feedback
I am quite content with how it's panned out. I can integrate it and extend it for a few of my projects as is.
There are a few sections I am wondering if they can be improved. It does seem a bit verbose at times (with the From()
impl's and the enum State
impl wrappers used to call the underlying state methods)
Any feedback would be welcome