Skip to content

lyuts/refinny.rs

 
 

Repository files navigation

Finny - Hierarchical Finite State Machines for Rust

Documentation Build Dependencies

Overview

This project is a fork of a great FSM library https://github.com/hashmismatch/finny.rs. Maintenance of the original project has been paused. This fork is a hobby project maintained in spare time. While there are no significant differences from the upstream (at least at this point), this fork makes an attempt at keeping up with the latest dependencies, code cleanup, and minor features. There are no specific plans to upstream these changes since the original project maintenance is on hold. However, should the author of finny revive the project we'd consider upstreaming accumulated changes.

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::{bundled::derive_more, 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(())
}

License: MIT OR Apache-2.0

About

Finite State Machines for Rust

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 100.0%