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
/// Defines concrete state marker ZSTs.
///
/// Use this in the definition crate for every concrete state in the contract.
/// The generated structs are markers, not runtime state. Runtime data stays in
/// your implementation type; the marker appears only in the type of
/// [`State`](crate::State), [`StateOwned`](crate::StateOwned), shared guards,
/// and generated union enums.
///
/// Attributes placed before a state are copied to the generated struct. This
/// is the intended way to document public state markers:
///
/// ```
/// use magicstatemachines::{ConcreteStateKind, StateMarker, States};
///
/// States! {
/// /// No connection has been established yet.
/// #[derive(Debug, Default)]
/// Disconnected;
///
/// /// The transport is open but no user is authenticated.
/// Connected;
/// }
///
/// fn assert_concrete_state<T>()
/// where
/// T: StateMarker<Kind = ConcreteStateKind>,
/// {
/// }
///
/// assert_concrete_state::<Disconnected>();
/// let _ = format!("{:?}", Disconnected::default());
/// ```
///
/// Each generated type is a public zero-sized struct implementing the traits
/// needed by the rest of the library:
///
/// - [`StateMarker`](crate::StateMarker) with
/// [`ConcreteStateKind`](crate::ConcreteStateKind), so generic code can tell
/// concrete states apart from union markers;
/// - [`StateTrait`](crate::StateTrait), so shared storage and tracing can keep
/// an erased runtime marker;
/// - the concrete-state marker trait used internally to reject storing a union
/// as the authoritative shared state.
///
/// Prefer this macro over hand-written state structs. The library assumes that
/// concrete states are ZST markers whose erased representation still names a
/// concrete state, not a union. Shared storage uses that erased marker at the
/// runtime boundary, tracing stores it in trace entries, and union
/// discrimination compares against it later. Writing the structs by hand means
/// wiring all of those invariants yourself; using `States!` keeps the state
/// definition crate small and makes the generated rustdoc show the state docs
/// exactly where downstream users expect them.
}
)*
};
}