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;