# 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](https://www.rust-lang.org/tools/install).
### Cloning the Repository
To clone the repository, run the following command:
```sh
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](examples/cd_player.rs), [turnstile_enum](examples/turnstile_enum.rs), [turnstile_str](examples/turnstile_str.rs). Here is how to run the cd_player example
```sh
cargo run --example cd_player
```
### Running the Tests
You can run the tests with:
```sh
cargo test
```
## Code Examples
### Creating a Turnstile State Machine with String Literals
```rs
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
```rs
#[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
```Rust
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
"