Define your Finite State Machines in DOT

66 points drymud64

I've not wanted to change my crate for a couple of months now, so I guess it's time to tell you all about it :)

fsmentry, allows you to define your state machines like this, which I find much easier than existing crates:

fsmentry::dot!{
    red -> amber -> green -> red
}

But that's not all - fsmentry machines can:

  • store arbitrary data inside each state - including other state machines!
  • transition themselves with a nice .entry() API
  • support arbitrary #[derive(..)]s
  • document themselves with nice diagrams

​

Here's a fuller example:

// Using the DSL allows us to add derives and data in each state
fsmentry::dsl! {
    #[derive(Debug)]
    pub User {
        Reading;
        Commenting: String; // data in this state

        Reading -> Commenting -> Reading;
                   Commenting -> Sleeping;

        /// Doc comments are plumbed to the right places
        Reading -"that's enough"-> Sleeping;
    }
}

use user::{Entry::{Commenting, Reading, Sleeping}, State, User};

let mut user = User::new(State::Reading);

loop {
    match user.entry() {
        Commenting(it) => {
            // access the data
            let comment: &String = it.get();
            if contains_bad_words(comment) {
                // transition to one state or the other
                it.sleeping();
            } else {
                it.reading();
            }
        }
        // provide the state for this transition
        Reading(it) => it.commenting(String::from("I've read it")),
        Sleeping => break,
    }
}

I felt like I could add something that other crates don't cover - check out the comparison with other crates in the README

​