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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
use Pin;
use UniqueRc;
use UniqueArc;
/// Declares that a definition crate permits `TState` as an initial state.
///
/// This trait is normally emitted by
/// [`StateMachineDefinition!`](macro@crate::StateMachineDefinition). It is the
/// proof used by [`State::new`](crate::State::new),
/// [`StateOwned::new`](crate::StateOwned::new), and shared-state constructors:
/// creating a fresh state token only compiles for states declared in the
/// definition crate.
///
/// ```ignore
/// pub struct ConnectionStandin;
/// pub struct Disconnected;
///
/// impl magicstatemachines::Initial<Disconnected> for ConnectionStandin {}
/// ```
///
/// Most users should not write that impl manually; prefer:
///
/// ```ignore
/// magicstatemachines::StateMachineDefinition! {
/// for ConnectionStandin;
///
/// pub Initial: Disconnected;
/// }
/// ```
/// Declares that a definition crate permits `TFrom -> TTo`.
///
/// The definition crate owns the stand-in and state types. Rust's orphan rules
/// therefore prevent an implementation crate from adding transitions. This
/// trait is the graph edge only; it does not define what happens to the
/// runtime value during the edge. Runtime effects are supplied later by
/// [`StateMachineImpl!`](macro@crate::StateMachineImpl).
///
/// `F` is the required positional call signature for the transition. A
/// zero-argument transition can use the default `fn()`. A transition that must
/// be called with a `String` declares `type F = fn(String)`.
///
/// ```ignore
/// pub struct ConnectionStandin;
/// pub struct Connected;
/// pub struct Authenticated;
///
/// impl magicstatemachines::Transition<Connected, Authenticated> for ConnectionStandin {
/// type F = fn(String);
/// }
/// ```
///
/// With the definition macro, the same declaration is usually written as:
///
/// ```ignore
/// magicstatemachines::StateMachineDefinition! {
/// for ConnectionStandin;
///
/// pub Initial: Connected;
/// transition Connected => Authenticated(user: String);
/// }
/// ```
///
/// The name `user` is documentation for the contract and for the matching
/// implementation body. The actual transition call remains positional:
/// `transition!(self, user.into())`.
/// Stable proof that a transition signature accepts a tuple of arguments.
;
}
transition_signature_impls!
/// Connects an implementation type to a state-machine definition.
///
/// Implementations are `'static` so storage backends can provide borrowed
/// guard families without repeating the implementation type in the backend.
/// The associated `Standin` selects the definition-crate contract, while
/// `TransitionToken` is the private capability required to perform retagging.
///
/// [`crate::StateMachineImpl!`] generates this implementation and keeps the
/// transition capability's construction private. Code outside the invocation
/// module cannot manufacture the token:
///
/// ```compile_fail
/// use magicstatemachines::{Initial, State, StateMachineImpl, States, StorageStateOwned, Transition};
///
/// mod implementation {
/// use super::*;
///
/// pub struct Standin;
/// pub struct Runtime;
/// States! {
/// Ready;
/// Running;
/// }
/// impl Initial<Ready> for Standin {}
/// impl Transition<Ready, Running> for Standin {}
///
/// magicstatemachines::StateMachineImpl!(Runtime: Standin; transition Ready => Running(););
///
/// pub fn ready() -> State<StorageStateOwned, Runtime, Ready> {
/// State::new(Runtime)
/// }
/// }
///
/// let ready = implementation::ready();
/// let _ = magicstatemachines::transition_state::<_, _, _, implementation::Running>(
/// ready,
/// implementation::__StateMachineTransitionToken(())
/// ).call(());
/// ```
///
/// The generated ergonomic helpers are also private to the invocation module.
/// This means implementation methods can call [`transition!`](macro@crate::transition),
/// but external callers can only call the methods you expose:
///
/// ```compile_fail
/// use magicstatemachines::{Initial, State, States, StorageStateOwned, Transition};
///
/// mod implementation {
/// use super::*;
///
/// pub struct Standin;
/// pub struct Runtime;
/// States! {
/// Ready;
/// Running;
/// }
///
/// impl Initial<Ready> for Standin {}
/// impl Transition<Ready, Running> for Standin {}
/// magicstatemachines::StateMachineImpl!(Runtime: Standin; transition Ready => Running(););
///
/// pub fn ready() -> State<StorageStateOwned, Runtime, Ready> {
/// State::new(Runtime)
/// }
/// }
///
/// let ready = implementation::ready();
/// let _ = magicstatemachines::transition!(ready);
/// ```