generic_state_machine/
lib.rs

1//! ## Summary
2//! A simple library that allows to create Moore or Mealy state machines
3//! It is designed around the [`StateMachine<S,E>`](primitives::StateMachine) type and allows the use of
4//! custom transition functions.
5//!
6//! ## Requirements:
7//!  * All states need to be of the same type `S`
8//!  * All events (inputs) need to be of the same type `E`
9//!  * Transition functions are executed over `self` (to have access to internal lists of states or events)
10//!    and need to follow the prototype:
11//!    ```rust, ignore
12//!     fn(&mut StateMachine<S, E>, E) -> S;
13//!    ```
14//!    where input E is the trigger event and the return value is the new state.
15//!  * Output generation is left to the user to allow the implementation to be as generic as possible.
16//!    You can print or call exernal functions to produce the desired output
17//!
18//! ## Implement Moore state machine:
19//!  * Define transition functions that calculate the next state and use that to produce any outputs
20//!
21//! ## Implement Mealy state machine:
22//!  * Define transition functions that calculate the next state and use that together with the input event E to produce any outputs
23//!
24//! ### A Basic Example of a State Machine (using the asynchronous implementation):
25//! ```ignore
26//!            +------------+
27//!   Event: 1 |            | +----+
28//!            |            V |    | Event: 1
29//!      +->[false]       [true]<--+
30//!      |   | ^            |
31//!      +---+ |            | Event: 0
32//!  Event: 0  +------------+
33//! ```
34//!
35//! ```rust
36//! #[cfg(features = "async")]
37//! #[tokio::test]
38//! async fn state_machine_example() -> Result<()> {
39//!     let mut fsm = AsyncStateMachine::<bool, usize>::new(5);
40//!         fsm.add_states(&mut vec![true, false])
41//!             .await
42//!             .add_transition(true, 0, |_fsm, _event| false)
43//!             .await
44//!             .add_transition(true, 1, |_fsm, _event| true)
45//!             .await
46//!             .add_transition(false, 0, |_fsm, _event| false)
47//!             .await
48//!             .add_transition(false, 1, |_fsm, _event| true)
49//!             .await
50//!             .set_state(false)
51//!             .await;
52//!
53//!         fsm.start().await.unwrap();
54//!
55//!         println!("My State Machine: {:?}", fsm);
56//!
57//!         fsm.push_event(0).await.unwrap();
58//!         assert_eq!(fsm.current_state().await, false);
59//!
60//!         fsm.push_event(1).await.unwrap();
61//!         assert_eq!(fsm.current_state().await, true);
62//!
63//!         fsm.push_event(1).await.unwrap();
64//!         assert_eq!(fsm.current_state().await, true);
65//!
66//!         fsm.push_event(0).await.unwrap();
67//!         assert_eq!(fsm.current_state().await, false);
68//!
69//!         fsm.push_event(0).await.unwrap();
70//!         assert_eq!(fsm.current_state().await, false);
71//! }
72//! ```
73//!
74//! ### A Basic Example of a State Machine (using the primitive type):
75//! ```ignore
76//!            +---->[1]----+
77//!   Event: 1 |            | Event: 2
78//!            |            V
79//!           [3]          [2]
80//!            ^            |
81//!            |            | Event: 3
82//!            +------------+
83//! ```
84//! ```rust
85//! use generic_state_machine::primitives::StateMachine;
86//!
87//! // Define a transition function. It can as general as we want!
88//! fn tf(_fsm: &StateMachine<i32, i32>, event: i32) -> i32 {
89//! match event {
90//!     1 => 1,
91//!     2 => 2,
92//!     3 => 3,
93//!     _ => panic!(), // Invalid transition
94//!     }
95//! }
96//!
97//! let mut fsm = StateMachine::<i32, i32>::new();
98//! fsm.add_states(&mut vec![1, 2, 3]);
99//!
100//! // We can even use captures as transition functions!
101//! fsm.add_transition(1, 2, |_fsm, _event| {
102//!     // We are in state 1! Go to state 2! Ignore Input!
103//!     2
104//! });
105//!
106//! fsm.add_transition(2, 3, tf);
107//! fsm.add_transition(3, 1, tf);
108//! fsm.initial_state(1);
109//!
110//! println!("{:?}", fsm);
111//!
112//! assert_eq!(2, fsm.execute(2).unwrap());
113//! assert_eq!(3, fsm.execute(3).unwrap());
114//! assert_eq!(1, fsm.execute(1).unwrap());
115//!
116//! ```
117mod error;
118pub mod primitives;
119#[cfg(feature = "async")]
120pub mod state_machine;
121mod tests;