Skip to content

Instantly share code, notes, and snippets.

@dmoghnie

dmoghnie/fsm.md Secret

Created March 31, 2023 04:35
Show Gist options
  • Save dmoghnie/404bbd6025dd68ed076102598862087c to your computer and use it in GitHub Desktop.
Save dmoghnie/404bbd6025dd68ed076102598862087c to your computer and use it in GitHub Desktop.

Introduction

Finite State Machines (FSMs) are a popular and effective way to manage the behavior of systems or applications, often used to model the control flow and organize the logic of applications. FSMs consist of a finite number of states, events, and transitions between states triggered by those events. They are particularly useful in simplifying complex systems, making it easier to reason about their behavior and maintain their code.

In this article, we will discuss a simple state machine library implemented in Rust, a systems programming language known for its performance and safety guarantees. The library is designed to be flexible and easy to use, using Rust's enum data type for states and events. This makes it suitable for a wide range of state machine designs.

Rust State Machine Library

The library's primary components are the FsmEnum and Stateful traits, and the StateMachine struct. We will discuss each component in detail below.

FsmEnum

FsmEnum is a trait that defines how to create a new state machine state based on a given enum value. This is used to instantiate new state machine states when a state transition occurs. The FsmEnum trait makes it easy to create new state objects for each state in the state machine.

Stateful

The Stateful trait defines how a state should handle state transition events. It contains methods for handling events on entering a state (on_enter), on receiving an event (on_event), and on exiting a state (on_exit). This trait allows for custom behavior to be implemented for each state.

StateMachine

StateMachine is the main struct that represents a state machine instance. It tracks the current state, provides methods to initialize the state machine, process events, and get the current state. The StateMachine struct is generic and can be instantiated with any specific set of enums for states and events.

Implementation

The state machine library is implemented in Rust with two versions: a synchronous version (sync module) and an asynchronous version (Async module). Both versions share the same basic structure, using the FsmEnum, Stateful, and StateMachine components mentioned above.

The synchronous version uses standard Rust traits and methods, while the asynchronous version uses the async_trait crate to define async traits and async methods. This enables the state machine to work seamlessly with Rust's async/await syntax for asynchronous programming.

In both versions, state machine states are cached in a HashMap to avoid recreating them every time a state transition occurs. This improves the performance and memory usage of the state machine. Additionally, a global event handler can be defined to handle global events that are not specific to any state. This further enhances the flexibility of the library.

Usage

Using the Rust state machine library is straightforward. First, define your states and events as Rust enums, and implement the FsmEnum trait for your state enum. Next, implement the Stateful trait for each state in your state machine, providing the desired behavior for each state. Finally, create a new StateMachine instance, providing the initial state and an optional global event handler, and use the provided methods to initialize the state machine and process events.

Conclusion

This Rust state machine library provides a simple, flexible, and efficient way to define state machines using Rust enums for states and events. The library's design makes it easy to use and adaptable to various state machine designs, and its performance is optimized through caching and the use of Rust's powerful features. Whether you need a synchronous or asynchronous state machine, this library offers a solid foundation for implementing state machines in Rust.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment