Finite state machines in rust; bendns fork to add types.
use doc = include_str
Yevhenii Babichenko 2024-05-13
parent ff103aa · commit 7abd833
-rw-r--r--CHANGELOG.md2
-rw-r--r--README.md10
-rw-r--r--rust-fsm/src/lib.rs195
3 files changed, 7 insertions, 200 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0bab69..bc1fa4d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,7 +20,7 @@ adheres to [Semantic Versioning][semver].
## Added
* A type alias `StateMachine` for `rust_fsm::StateMachine<Impl>` is now
generated inside the said module.
-* Supplying ones own enums for state, input and output in the proc-macro.
+* Supplying ones own enums for state, input and output in the proc-macro (#10).
## [0.6.2] - 2024-05-11
### Changed
diff --git a/README.md b/README.md
index 0496f25..52035d4 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@
The `rust-fsm` crate provides a simple and universal framework for building
state machines in Rust with minimum effort.
-The essential part of this crate is the `StateMachineImpl` trait. This trait
-allows a developer to provide a strict state machine definition, e.g. specify
-its:
+The essential part of this crate is the
+[`StateMachineImpl`](trait.StateMachineImpl.html) trait. This trait allows a
+developer to provide a strict state machine definition, e.g. specify its:
* An input alphabet - a set of entities that the state machine takes as
inputs and performs state transitions based on them.
@@ -141,13 +141,13 @@ state_machine! {
The default visibility is private.
-#### Custom allphabet types
+#### Custom alphabet types
You can supply your own types to use as input, output or state. All of them are
optional: you can use only one of them or all of them at once if you want to.
The current limitation is that you have to supply a fully qualified type path.
-```rust
+```rust,ignore
use rust_fsm::*;
pub enum Input {
diff --git a/rust-fsm/src/lib.rs b/rust-fsm/src/lib.rs
index 98e1c57..95a5ea9 100644
--- a/rust-fsm/src/lib.rs
+++ b/rust-fsm/src/lib.rs
@@ -1,197 +1,4 @@
-//! A framework for building finite state machines in Rust
-//!
-//! The `rust-fsm` crate provides a simple and universal framework for building
-//! state machines in Rust with minimum effort.
-//!
-//! The essential part of this crate is the
-//! [`StateMachineImpl`](trait.StateMachineImpl.html) trait. This trait allows a
-//! developer to provide a strict state machine definition, e.g. specify its:
-//!
-//! * An input alphabet - a set of entities that the state machine takes as
-//! inputs and performs state transitions based on them.
-//! * Possible states - a set of states this machine could be in.
-//! * An output alphabet - a set of entities that the state machine may output
-//! as results of its work.
-//! * A transition function - a function that changes the state of the state
-//! machine based on its current state and the provided input.
-//! * An output function - a function that outputs something from the output
-//! alphabet based on the current state and the provided inputs.
-//! * The initial state of the machine.
-//!
-//! Note that on the implementation level such abstraction allows build any type
-//! of state machines:
-//!
-//! * A classical state machine by providing only an input alphabet, a set of
-//! states and a transition function.
-//! * A Mealy machine by providing all entities listed above.
-//! * A Moore machine by providing an output function that do not depend on the
-//! provided inputs.
-//!
-//! # Usage in `no_std` environments
-//!
-//! This library has the feature named `std` which is enabled by default. You
-//! may want to import this library as
-//! `rust-fsm = { version = "0.6", default-features = false, features = ["dsl"] }`
-//! to use it in a `no_std` environment. This only affects error types (the
-//! `Error` trait is only available in `std`).
-//!
-//! The DSL implementation re-export is gated by the feature named `dsl` which
-//! is also enabled by default.
-//!
-//! # Use
-//!
-//! Initially this library was designed to build an easy to use DSL for defining
-//! state machines on top of it. Using the DSL will require to connect an
-//! additional crate `rust-fsm-dsl` (this is due to limitation of the procedural
-//! macros system).
-//!
-//! ## Using the DSL for defining state machines
-//!
-//! The DSL is parsed by the `state_machine` macro. Here is a little example.
-//!
-//! ```rust
-//! use rust_fsm::*;
-//!
-//! state_machine! {
-//! #[derive(Debug)]
-//! #[repr(C)]
-//! circuit_breaker(Closed)
-//!
-//! Closed(Unsuccessful) => Open [SetupTimer],
-//! Open(TimerTriggered) => HalfOpen,
-//! HalfOpen => {
-//! Successful => Closed,
-//! Unsuccessful => Open [SetupTimer]
-//! }
-//! }
-//! ```
-//!
-//! This code sample:
-//!
-//! * Defines a state machine called `circuit_breaker`;
-//! * Derives the `Debug` trait for it. All attributes you use here (like
-//! `#[repr(C)]`) will be applied to all types generated by this macro. If you
-//! want to apply attributes or a docstring to the `mod` generated by this
-//! macro, just put it before the macro invocation.
-//! * Sets the initial state of this state machine to `Closed`;
-//! * Defines state transitions. For example: on receiving the `Successful`
-//! input when in the `HalfOpen` state, the machine must move to the `Closed`
-//! state;
-//! * Defines outputs. For example: on receiving `Unsuccessful` in the
-//! `Closed` state, the machine must output `SetupTimer`.
-//!
-//! This state machine can be used as follows:
-//!
-//! ```rust,ignore
-//! // Initialize the state machine. The state is `Closed` now.
-//! let mut machine = circuit_breaker::StateMachine::new();
-//! // Consume the `Successful` input. No state transition is performed.
-//! let _ = machine.consume(&circuit_breaker::Input::Successful);
-//! // Consume the `Unsuccesful` input. The machine is moved to the `Open`
-//! // state. The output is `SetupTimer`.
-//! let output = machine.consume(&circuit_breaker::Input::Unsuccessful).unwrap();
-//! // Check the output
-//! if let Some(circuit_breaker::Output::SetupTimer) = output {
-//! // Set up the timer...
-//! }
-//! // Check the state
-//! if let circuit_breaker::State::Open = machine.state() {
-//! // Do something...
-//! }
-//! ```
-//!
-//! The following entities are generated:
-//!
-//! * An empty structure `circuit_breaker::Impl` that implements the
-//! `StateMachineImpl` trait.
-//! * Enums `circuit_breaker::State`, `circuit_breaker::Input` and
-//! `circuit_breaker::Output` that represent the state, the input alphabet and
-//! the output alphabet respectively.
-//! * Type alias `circuit_breaker::StateMachine` that expands to
-//! `StateMachine<circuit_breaker::Impl>`.
-//!
-//! Note that if there is no outputs in the specification, the output alphabet
-//! is an empty enum and due to technical limitations of many Rust attributes,
-//! no attributes (e.g. `derive`, `repr`) are applied to it.
-//!
-//! Within the `state_machine` macro you must define at least one state
-//! transition.
-//!
-//! ### Visibility
-//!
-//! You can specify the module visibility like this:
-//!
-//! ```rust
-//! use rust_fsm::*;
-//!
-//! state_machine! {
-//! pub CircuitBreaker(Closed)
-//!
-//! Closed(Unsuccessful) => Open [SetupTimer],
-//! Open(TimerTriggered) => HalfOpen,
-//! HalfOpen => {
-//! Successful => Closed,
-//! Unsuccessful => Open [SetupTimer],
-//! }
-//! }
-//! ```
-//!
-//! The default visibility is private.
-//!
-//! ### Custom allphabet types
-//!
-//! You can supply your own types to use as input, output or state. All of them
-//! are optional: you can use only one of them or all of them at once if you
-//! want to. The current limitation is that you have to supply a fully qualified
-//! type path.
-//!
-//! ```rust,ignore
-//! use rust_fsm::*;
-//!
-//! pub enum Input {
-//! Successful,
-//! Unsuccessful,
-//! TimerTriggered,
-//! }
-//!
-//! pub enum State {
-//! Closed,
-//! HalfOpen,
-//! Open,
-//! }
-//!
-//! pub enum Output {
-//! SetupTimer,
-//! }
-//!
-//! state_machine! {
-//! #[state_machine(input(crate::Input), state(crate::State), output(crate::Output))]
-//! circuit_breaker(Closed)
-//!
-//! Closed(Unsuccessful) => Open [SetupTimer],
-//! Open(TimerTriggered) => HalfOpen,
-//! HalfOpen => {
-//! Successful => Closed,
-//! Unsuccessful => Open [SetupTimer]
-//! }
-//! }
-//! ```
-//!
-//! ## Without DSL
-//!
-//! The `state_machine` macro has limited capabilities (for example, a state
-//! cannot carry any additional data), so in certain complex cases a user might
-//! want to write a more complex state machine by hand.
-//!
-//! All you need to do to build a state machine is to implement the
-//! `StateMachineImpl` trait and use it in conjuctions with some of the provided
-//! wrappers (for now there is only `StateMachine`).
-//!
-//! You can see an example of the Circuit Breaker state machine in the
-//! [project repository][repo].
-//!
-//! [repo]: https://github.com/eugene-babichenko/rust-fsm/blob/master/tests/circuit_breaker.rs
-
+#![doc = include_str!("../../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
use core::fmt;