Crate finny

source · []
Expand description

Finny - Hierarchical Finite State Machines for Rust

Crates.io Documentation Build

Features

  • Declarative, builder API with a procedural function macro that generate the dispatcher
  • Compile-time transition graph validation
  • No run-time allocations required, no_std support
  • Support for generics within the shared context
  • Transition guards and actions
  • State regions, also known as orthogonal states
  • Event queueing and run-to-completition execution
  • Submachines, also known as Hierarchical State Machines
  • Timers on states

Example

Cargo.toml

[dependencies]
finny = "0.2"

Code

use finny::{finny_fsm, FsmFactory, FsmResult, decl::{BuiltFsm, FsmBuilder}};
 
// The context is shared between all guards, actions and transitions. Generics are supported here!
#[derive(Default)]
pub struct MyContext { val: u32 }
// The states are plain structs.
#[derive(Default)] 
pub struct MyStateA { n: usize }
#[derive(Default)]
pub struct MyStateB;
// The events are also plain structs. They can have fields.
#[derive(Clone)]
pub struct MyEvent;

// The FSM is generated by a procedural macro
#[finny_fsm]
fn my_fsm(mut fsm: FsmBuilder<MyFsm, MyContext>) -> BuiltFsm {
    // The FSM is described using a builder-style API
    fsm.state::<MyStateA>()
       .on_entry(|state, ctx| {
           state.n += 1;
           ctx.context.val += 1;
        })
       .on_event::<MyEvent>()
       .transition_to::<MyStateB>()
       .guard(|_ev, ctx, _states| { ctx.context.val > 0 })
       .action(|_ev, ctx, state_a, state_b| { ctx.context.val += 1; });
    fsm.state::<MyStateB>();
    fsm.initial_state::<MyStateA>();
    fsm.build()
}
 
// The FSM is built and tested.
fn main() -> FsmResult<()> {
    let mut fsm = MyFsm::new(MyContext::default())?;
    assert_eq!(0, fsm.val);
    fsm.start()?;
    let state_a: &MyStateA = fsm.get_state();
    assert_eq!(1, state_a.n);
    assert_eq!(1, fsm.val);
    fsm.dispatch(MyEvent)?;
    assert_eq!(2, fsm.val);
    Ok(())
}

Modules

External bundled libraries to be used by the procedural macros.

The builder-style API structures for defining your Finny FSM. The procedural macro parses these method calls and generated the optimized implementation.

A heapless queue with Clone and Arc support.

Structs

The context that is given to all of the guards and actions.

The struct that holds the core context and state of the given Finny FSM. Doesn’t include environmental traits that can be changed at runtime.

A heapless queue with a fixed size. Implemented using the arraydequeue crate.

An unbound event queue that uses VecDeque.

An unbound event queue that uses VecDeque.

The frontend of a state machine which also includes environmental services like queues and inspection. The usual way to use the FSM.

Enums

The current state of the FSM.

The lib-level error type.

The internal event type that also allows stopping or starting the machine.

Traits

Enumerates all the possible variants of a simple enum.

An internal or self action can only mutate itself.

Finite State Machine backend. Handles the dispatching, the types are defined by the code generator.

The event queueing trait for FSMs. Can be used from outside or from within the actions of the FSM.

Builds a frontend for running your FSM.

A state’s entry and exit actions.

Create a new state from the shared global context.

Retrieve a pair of states as mutable references. Used in state transitions.

Retrieve a pair of states as immutable references. Used in state transitions.

The implementation should hold all of the FSM’s states as fields.

A transition’s action that operates on both the exit and entry states.

The transition that starts the machine, triggered using the start() method.

Check if this transition is allowed to be entered.

Associate some data with a specific timer ID.

Functions

Used to funnel the event down to the sub-machine.

Type Definitions

Attribute Macros

The procedural macro that will transform the builder function into the FSM.