5 releases (breaking)
0.5.0 | Mar 11, 2024 |
---|---|
0.4.0 | Mar 11, 2024 |
0.3.0 | Mar 11, 2024 |
0.2.0 | Mar 5, 2024 |
0.1.0 | Mar 5, 2024 |
#1919 in Algorithms
108 downloads per month
12KB
142 lines
State Machine DSL
This is a Rust project that provides a domain-specific language (DSL) for creating state machines.
Getting Started
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
Prerequisites
You need to have Rust and Cargo installed on your machine. If you don't have them installed, you can get them from here.
Cloning the Repository
To clone the repository, run the following command:
git clone https://github.com/hansaskov1/state_machine_dsl.git
cd state_machine_dsl
Running the Project
You can run one of the three available examples cd_player, turnstile_enum, turnstile_str. Here is how to run the cd_player example
cargo run --example cd_player
Running the Tests
You can run the tests with:
cargo test
Code Examples
Creating a Turnstile State Machine with String Literals
fn main() {
let mut turnstyle = StateMachineBuilder::new((), "Locked")
.state("Locked")
.on("Coin").go_to("Unlocked")
.state("Unlocked")
.on("Push").go_to("Locked")
.build().unwrap();
turnstyle.trigger("Coin");
println!("State: {}", turnstyle.state);
}
This code will print out State: UnLocked
Creating a Turnstile State Machine with Enums
#[derive(Debug, Clone, Copy, PartialEq)]
enum State {
Locked,
UnLocked
}
#[derive(PartialEq)]
enum Event {
Coin,
Push,
}
fn main() {
let mut turnstyle = StateMachineBuilder::new((), State::Locked)
.state(State::Locked)
.on(Event::Coin).go_to(State::UnLocked)
.state(State::UnLocked)
.on(Event::Push).go_to(State::Locked)
.build().unwrap();
turnstyle.trigger(Event::Coin);
println!("State: {:?}", turnstyle.state);
}
This will also print out "State: UnLocked"
And here is a more complex example for a Cd-Player
fn main() {
// Create store for state machine. In this case it is an integer
let track = 0;
let mut cd_player = StateMachineBuilder::new( track, "Stopped")
.state("Stopped")
.on("Play").go_to("Playing").only_if(|track| *track > 0 )
.on("Forward").update(|track| *track += 1 )
.on("Backward").update(|track| *track -= 1)
.state("Playing")
.on("Stop").go_to("Stopped").then(|track| *track = 0)
.on("Pause").go_to("Paused")
.state("Paused")
.on("Play").go_to("Playing")
.on("Stop").go_to("Stopped").then(|track| *track = 0)
.on("Forward").update(|track| *track += 1)
.on("Backward").update(|track| *track -= 1)
.build()
.unwrap();
println!("Track: {}, State: {}", cd_player.store, cd_player.state);
cd_player.trigger("Forward");
println!("Track: {}, State: {}", cd_player.store, cd_player.state);
cd_player.trigger("Play");
println!("Track: {}, State: {}", cd_player.store, cd_player.state);
}
Running this example gives us the following output: " Track: 0, State: Stopped Track: 1, State: Stopped Track: 1, State: Playing "