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
use ;
use ;
/// `Uid` serves as a unique identifier (UID) for referencing objects across
/// different Models.
///
/// Although it is theoretically possible to re-use a Uid value once the object
/// it was originally associated with gets freed, this optimization is usually
/// not necessary. Instead, we use a 64-bit counter, which, while capable of
/// wrapping around, is practically unlikely to overflow within the program's
/// lifetime, thus providing unique values.
;
/// Conversion implementations for `Uid` to `usize` and vice versa.
/// Safe cast as `usize` is at least 64 bits on 64-bit platforms.
/// Conversion implementations for `Uid` to `u64` and vice versa.
/// `Objects` is a type alias for a `BTreeMap` that maps `Uid`s to object
/// instances of a given type. This is used by Models to maintain a collection
/// of objects that can be uniquely identified and accessed using their `Uid`s.
pub type Objects<T> = ;
/// `State` struct encapsulates the state-machine's state.
///
/// This includes a `Uid` generator, a vector of one or more `Substates`
/// instances, and the `current_instance` field holding the index of the
/// currently active instance in the state-machine's main loop.
///
/// In most scenarios, the `Substates` vector contains a single element.
/// Multiple elements mainly occur in testing scenarios where multiple
/// instances are simulated.
/// The `ModelState` trait provides an interface for Models to access their own
/// state or the states of their dependencies (other models) from the main
/// `State`. This trait relies on runtime type information (RTTI) to correctly
/// identify and return a reference to the desired field in Substates.
///
/// Models are defined in terms of their own state type, and each Model's state
/// is a field in the `Substates` struct, which is defined by the top-most Model.
/// This struct must contain one field for every Model dependency (for
/// Pure/InputModels only).
///
/// The `ModelState` trait might seem a bit complicated, but it's a crucial
/// part of this state-machine setup. It provides flexibility and helps keep
/// things organized. In simple terms, it allows different parts of our program
/// (the models) to access and manage their own specific data (state) within the
/// larger system (the state-machine). This trait makes it easier to add,
/// remove, or change parts of the system without disrupting the whole thing.
///
/// A derive macro is provided, which simplifies a lot of the work for us.
/// This macro automates the process of implementing the `ModelState` trait for
/// a struct. The macro iterates over all named fields. For each field, it
/// generates code that tries to downcast the field to the requested type (T).
/// If the downcast succeeds, it returns a reference (or mutable reference) to
/// the field. If the downcast fails, it proceeds to the next field.