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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
use std::{
hash::{
Hash,
Hasher,
},
slice::{
Iter,
IterMut,
},
};
/// The ID of an element in the ProcessImage
pub type Id = usize;
pub(crate) trait HasIdMut {
fn id_mut(&mut self) -> &mut Id;
}
/// This trait provides access to the ID of elements in the process image
pub trait HasId {
/// Retrieve the ID of this element
fn id(&self) -> Id;
}
#[derive(Debug, Clone)]
pub(crate) struct IdFactory {
cursor: Id,
}
impl IdFactory {
pub(crate) fn new() -> Self {
Self {
cursor: Id::default().wrapping_add(1),
}
}
pub(crate) fn next(&mut self) -> Id {
let ret = self.cursor;
self.cursor = ret.checked_add(1).expect("Ran out of possible ID values");
ret
}
pub(crate) fn reset(&mut self) {
self.cursor = Id::default().wrapping_add(1);
}
}
pub(crate) type IdMapValues<'a, T> = Iter<'a, T>;
pub(crate) type IdMapValuesMut<'a, T> = IterMut<'a, T>;
#[derive(Clone, Debug)]
pub(crate) struct IdMap<T>
where
T: HasId + HasIdMut + Hash,
{
data: Vec<T>,
factory: IdFactory,
}
impl<T> Hash for IdMap<T>
where
T: HasId + HasIdMut + Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(self.data.len());
for elem in &self.data {
elem.hash(state);
}
}
}
impl<T> IdMap<T>
where
T: HasId + HasIdMut + Hash,
{
pub(crate) fn new() -> Self {
Self {
data: Vec::new(),
factory: IdFactory::new(),
}
}
pub(crate) fn clear(&mut self) {
self.data.clear();
self.factory.reset();
}
pub(crate) fn reserve_id(&mut self, elem: &mut T) -> Id {
let mut id = elem.id();
if id == Id::default() {
id = self.factory.next();
*elem.id_mut() = id;
}
id
}
pub(crate) fn insert(&mut self, mut elem: T) -> Id {
let id = self.reserve_id(&mut elem);
self.data.push(elem);
id
}
pub(crate) fn get(&self, id: Id) -> Option<&T> {
self.data.iter().find(|&elem| elem.id() == id)
}
pub(crate) fn get_mut(&mut self, id: Id) -> Option<&mut T> {
self.data.iter_mut().find(|elem| elem.id() == id)
}
pub(crate) fn values(&self) -> IdMapValues<T> {
self.data.iter()
}
pub(crate) fn values_mut(&mut self) -> IdMapValuesMut<T> {
self.data.iter_mut()
}
pub(crate) fn get_at(&self, idx: usize) -> Option<&T> {
self.data.get(idx)
}
pub(crate) fn get_at_mut(&mut self, idx: usize) -> Option<&mut T> {
self.data.get_mut(idx)
}
pub(crate) fn insert_at(&mut self, idx: usize, mut elem: T) -> Id {
let id = self.reserve_id(&mut elem);
self.data.insert(idx, elem);
id
}
pub(crate) fn remove_at(&mut self, idx: usize) -> T {
self.data.remove(idx)
}
pub(crate) fn len(&self) -> usize {
self.data.len()
}
pub(crate) fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
macro_rules! idmap_functions {
($parent:ty, $child:ty, $suffix:ident) => {
/// Accessor methods that handle the children of this process image element
impl $parent {
/// Get the cursor of this process image element
pub fn cursor(&self) -> usize {
self.cursor
}
/// Set the cursor of this process image element
pub fn set_cursor(&mut self, cursor: usize) {
self.cursor = cursor;
}
/// Move the cursor of this process image element to the end of its children list.
/// This enables appending children.
pub fn move_cursor_beyond_end(&mut self) {
self.cursor = self.idmap.len();
}
/// Increment the cursor of this process image element or return `false` if the cursor
/// is already at the last child
pub fn move_cursor_forward(&mut self) -> bool {
if self.cursor >= self.idmap.len().saturating_sub(1) {
false
} else {
self.cursor += 1;
true
}
}
/// Decrement the cursor of this process image element or return `false` if it's already
/// at the first child
pub fn move_cursor_backwards(&mut self) -> bool {
if self.cursor == 0 {
false
} else {
self.cursor -= 1;
true
}
}
/// Retrieve the child with the given ID of this process image element
pub fn $suffix(&self, id: Id) -> Option<&$child> {
self.idmap.get(id)
}
paste! {
/// Get the number of children for this process image element
pub fn [<num_ $suffix s>](&self) -> usize {
self.idmap.len()
}
/// Get the child at the current cursor position for this process image element
pub fn [<cursor_ $suffix>](&self) -> Option<&$child> {
self.idmap.get_at(self.cursor)
}
/// Get the child at the current cursor position for this process image element
pub fn [<cursor_ $suffix _mut>](&mut self) -> Option<&mut $child> {
self.idmap.get_at_mut(self.cursor)
}
/// Insert the given child into the list of children at the current cursor position for this process image element
pub fn [<insert_ $suffix>](&mut self, child: $child) -> Id {
self.idmap.insert_at(self.cursor, child)
}
/// Delete the child at the current cursor position of this process image element and return it
pub fn [<delete_ $suffix>](&mut self) -> $child {
self.idmap.remove_at(self.cursor)
}
/// Iterate over all children of this process image element independent of the current cursor position
pub fn [<iter_ $suffix s>](&self) -> IdMapValues<$child> {
self.idmap.values()
}
/// Iterate over all children of this process image element independent of the current cursor position
pub fn [<iter_ $suffix s_mut>](&mut self) -> IdMapValuesMut<$child> {
self.idmap.values_mut()
}
/// Retrieve the child with the given ID of this process image element
pub fn [<$suffix _mut>](&mut self, id: Id) -> Option<&mut $child> {
self.idmap.get_mut(id)
}
}
}
};
}
pub(crate) use idmap_functions;