1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
pub use rust_sfsm;
/// # Trait for the state behavior.
///
/// This trait should be implemented for an `enum`
/// representing a set of states.
///
/// ## Example
///
/// ```rust
/// /// List of protocol states.
/// #[derive(Clone, Copy, Default, PartialEq)]
/// enum States {
/// #[default]
/// Init,
/// Opened,
/// Closed,
/// Locked,
/// }
///
/// /// List of protocol events.
/// enum Events {
/// Create,
/// Open,
/// Close,
/// Lock,
/// Unlock,
/// }
///
/// /// Protocol state machine context (data shared between states).
/// #[derive(Default)]
/// struct Context {
/// lock_counter: u16,
/// }
///
/// impl StateBehavior for States {
/// type State = Self;
/// type Event<'a> = Events;
/// type Context = Context;
///
/// fn enter(&self, _context: &mut Self::Context) {
/// if self == &States::Locked {
/// _context.lock_counter += 1
/// }
/// }
///
/// fn handle_event(
/// &self,
/// event: &Self::Event<'_>,
/// _context: &mut Self::Context,
/// ) -> Option<Self::State> {
/// match (self, event) {
/// (&States::Init, &Events::Create) => Some(States::Opened),
/// (&States::Opened, &Events::Close) => Some(States::Closed),
/// (&States::Closed, &Events::Open) => Some(States::Opened),
/// (&States::Closed, &Events::Lock) => Some(States::Locked),
/// (&States::Locked, &Events::Unlock) => Some(States::Closed),
/// _ => None,
/// }
/// }
/// }
/// ```
/// # Trait for the state machine behavior.
///
/// This trait is implemented by the [rust_sfsm] attribute macro
/// and shouldn't be manually implemented by the user.
///
/// It may be used to monomorphize different types implementing
/// the state machine behavior for a given set of states.
///
/// ## Example
///
/// ```rust
/// fn test_state_machine<S: StateMachine<States>>(state_machine: &mut S) {
/// assert!(state_machine.current_state() == States::Init);
///
/// state_machine.handle_event(&Events::Create);
/// assert!(state_machine.current_state() == States::Opened);
///
/// state_machine.handle_event(&Events::Close);
/// assert!(state_machine.current_state() == States::Closed);
///
/// state_machine.handle_event(&Events::Lock);
/// assert!(state_machine.current_state() == States::Locked);
///
/// state_machine.handle_event(&Events::Unlock);
/// assert!(state_machine.current_state() == States::Closed);
///
/// state_machine.handle_event(&Events::Open);
/// assert!(state_machine.current_state() == States::Opened);
/// }
/// ```