1use alloc::vec::Vec;
14
15use core::ops::Deref;
16
17use crate::ecs::entity::Entity;
18use crate::ecs::tick::Tick;
19
20#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
28pub struct ColumnTicks {
29 pub changed: Tick,
31 pub added: Tick,
33 pub bulk: Tick,
35 pub structural: Tick,
37}
38
39#[derive(Debug)]
40pub struct Column<T> {
42 data: Vec<T>,
43 entities: Vec<Entity>,
44 row_changed: Vec<Tick>,
45 changed: Tick,
46 added: Tick,
47 bulk: Tick,
48 structural: Tick,
49}
50
51impl<T> Default for Column<T> {
52 fn default() -> Column<T> {
53 Column {
54 data: Vec::new(),
55 entities: Vec::new(),
56 row_changed: Vec::new(),
57 changed: Tick::ZERO,
58 added: Tick::ZERO,
59 bulk: Tick::ZERO,
60 structural: Tick::ZERO,
61 }
62 }
63}
64
65impl<T> Column<T> {
66 pub fn new() -> Column<T> {
68 Column::default()
69 }
70
71 pub fn entities(&self) -> &[Entity] {
73 &self.entities
74 }
75
76 pub fn changed_tick(&self) -> Tick {
78 self.changed
79 }
80
81 #[cfg(test)]
82 pub(crate) fn added_tick(&self) -> Tick {
83 self.added
84 }
85
86 pub fn ticks(&self) -> ColumnTicks {
89 ColumnTicks {
90 changed: self.changed,
91 added: self.added,
92 bulk: self.bulk,
93 structural: self.structural,
94 }
95 }
96
97 #[cfg(test)]
99 pub(crate) fn row_ticks(&self) -> &[Tick] {
100 &self.row_changed
101 }
102
103 pub fn reserve(&mut self, additional: usize) {
106 self.data.reserve(additional);
107 self.entities.reserve(additional);
108 self.row_changed.reserve(additional);
109 }
110
111 pub fn capacity(&self) -> usize {
113 self.data.capacity()
114 }
115
116 pub fn push(&mut self, entity: Entity, value: T, tick: Tick) {
119 self.data.push(value);
120 self.entities.push(entity);
121 self.row_changed.push(tick);
122 self.added = tick;
123 self.changed = tick;
124 self.structural = tick;
125 debug_assert_eq!(self.data.len(), self.entities.len());
126 debug_assert_eq!(self.data.len(), self.row_changed.len());
127 }
128
129 pub fn swap_remove(&mut self, index: usize, tick: Tick) -> T {
134 let value = self.data.swap_remove(index);
135 self.entities.swap_remove(index);
136 self.row_changed.swap_remove(index);
137 self.changed = tick;
138 self.structural = tick;
139 debug_assert_eq!(self.data.len(), self.entities.len());
140 debug_assert_eq!(self.data.len(), self.row_changed.len());
141 value
142 }
143
144 pub fn drain(&mut self, tick: Tick) -> Vec<T> {
146 self.entities.clear();
147 self.row_changed.clear();
148 self.changed = tick;
149 self.structural = tick;
150 core::mem::take(&mut self.data)
151 }
152
153 pub fn clear(&mut self, tick: Tick) {
155 self.data.clear();
156 self.entities.clear();
157 self.row_changed.clear();
158 self.changed = tick;
159 self.structural = tick;
160 }
161
162 pub fn values_mut(&mut self, tick: Tick) -> &mut [T] {
166 self.changed = tick;
167 self.bulk = tick;
168 &mut self.data
169 }
170
171 pub fn value_mut(&mut self, row: usize, tick: Tick) -> Option<&mut T> {
175 let value = self.data.get_mut(row)?;
176 self.row_changed[row] = tick;
177 self.changed = tick;
178 Some(value)
179 }
180
181 pub fn iter_with_entities(&self) -> impl Iterator<Item = (Entity, &T)> {
183 self.entities.iter().copied().zip(self.data.iter())
184 }
185
186 pub fn iter_mut_with_entities(&mut self, tick: Tick) -> impl Iterator<Item = (Entity, &mut T)> {
189 self.changed = tick;
190 self.bulk = tick;
191 self.entities.iter().copied().zip(self.data.iter_mut())
192 }
193
194 pub fn changed_rows(&self, last_run: Tick) -> impl Iterator<Item = (Entity, &T)> {
199 self.row_changed
200 .iter()
201 .zip(self.entities.iter().copied().zip(self.data.iter()))
202 .filter_map(move |(row, pair)| row.is_newer_than(last_run).then_some(pair))
203 }
204
205 #[cfg(test)]
207 pub(crate) fn changed_since(&self, last_run: Tick) -> bool {
208 self.changed.is_newer_than(last_run)
209 }
210}
211
212impl<T> Deref for Column<T> {
213 type Target = [T];
214
215 fn deref(&self) -> &[T] {
216 &self.data
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use super::*;
223 use crate::ecs::entity::Entities;
224 use alloc::vec;
225
226 fn three() -> (Entities, [Entity; 3]) {
227 let mut entities = Entities::new();
228 let ids = [entities.alloc(), entities.alloc(), entities.alloc()];
229 (entities, ids)
230 }
231
232 #[test]
233 fn push_keeps_rows_aligned_and_stamps_ticks() {
234 let (_e, ids) = three();
235 let mut col: Column<u32> = Column::new();
236 col.push(ids[0], 10, Tick(1));
237 col.push(ids[1], 20, Tick(2));
238 assert_eq!(col.len(), 2);
239 assert_eq!(&col[..], &[10, 20]);
240 assert_eq!(col.entities(), &[ids[0], ids[1]]);
241 assert_eq!(col.added_tick(), Tick(2));
242 assert_eq!(col.changed_tick(), Tick(2));
243 }
244
245 #[test]
246 fn swap_remove_reorders_and_returns_value() {
247 let (_e, ids) = three();
248 let mut col: Column<u32> = Column::new();
249 col.push(ids[0], 10, Tick(1));
250 col.push(ids[1], 20, Tick(1));
251 col.push(ids[2], 30, Tick(1));
252 let removed = col.swap_remove(0, Tick(5));
253 assert_eq!(removed, 10);
254 assert_eq!(&col[..], &[30, 20]);
256 assert_eq!(col.entities(), &[ids[2], ids[1]]);
257 assert_eq!(col.changed_tick(), Tick(5));
258 }
259
260 #[test]
261 fn drain_empties_and_returns_data() {
262 let (_e, ids) = three();
263 let mut col: Column<u32> = Column::new();
264 col.push(ids[0], 10, Tick(1));
265 col.push(ids[1], 20, Tick(1));
266 let drained = col.drain(Tick(9));
267 assert_eq!(drained, vec![10, 20]);
268 assert!(col.is_empty());
269 assert!(col.entities().is_empty());
270 assert_eq!(col.changed_tick(), Tick(9));
271 }
272
273 #[test]
274 fn values_mut_stamps_change() {
275 let (_e, ids) = three();
276 let mut col: Column<u32> = Column::new();
277 col.push(ids[0], 10, Tick(1));
278 for v in col.values_mut(Tick(7)) {
279 *v += 1;
280 }
281 assert_eq!(&col[..], &[11]);
282 assert!(col.changed_since(Tick(6)));
283 assert!(!col.changed_since(Tick(7)));
284 }
285
286 #[test]
287 fn iter_with_entities_pairs_rows() {
288 let (_e, ids) = three();
289 let mut col: Column<&str> = Column::new();
290 col.push(ids[0], "a", Tick(1));
291 col.push(ids[1], "b", Tick(1));
292 let pairs: Vec<(Entity, &str)> = col.iter_with_entities().map(|(e, v)| (e, *v)).collect();
293 assert_eq!(pairs, vec![(ids[0], "a"), (ids[1], "b")]);
294 }
295
296 #[test]
297 fn value_mut_stamps_only_its_own_row() {
298 let (_e, ids) = three();
299 let mut col: Column<u32> = Column::new();
300 col.push(ids[0], 10, Tick(1));
301 col.push(ids[1], 20, Tick(1));
302 col.push(ids[2], 30, Tick(1));
303
304 *col.value_mut(1, Tick(7)).unwrap() = 99;
305 assert_eq!(&col[..], &[10, 99, 30]);
306 assert_eq!(col.row_ticks(), &[Tick(1), Tick(7), Tick(1)]);
307 assert_eq!(col.changed_tick(), Tick(7));
309 assert_eq!(col.ticks().bulk, Tick::ZERO);
311
312 let changed: Vec<(Entity, u32)> = col.changed_rows(Tick(1)).map(|(e, v)| (e, *v)).collect();
313 assert_eq!(changed, vec![(ids[1], 99)]);
314 }
315
316 #[test]
317 fn value_mut_returns_none_past_the_end() {
318 let (_e, ids) = three();
319 let mut col: Column<u32> = Column::new();
320 col.push(ids[0], 10, Tick(1));
321 assert!(col.value_mut(1, Tick(5)).is_none());
322 assert_eq!(col.changed_tick(), Tick(1));
324 }
325
326 #[test]
327 fn values_mut_stamps_the_bulk_tick_and_leaves_rows_alone() {
328 let (_e, ids) = three();
329 let mut col: Column<u32> = Column::new();
330 col.push(ids[0], 10, Tick(1));
331 col.push(ids[1], 20, Tick(1));
332 for v in col.values_mut(Tick(6)) {
333 *v += 1;
334 }
335 assert_eq!(col.row_ticks(), &[Tick(1), Tick(1)]);
337 assert_eq!(col.ticks().bulk, Tick(6));
338 assert_eq!(col.ticks().changed, Tick(6));
339 }
340
341 #[test]
342 fn push_and_remove_stamp_the_structural_tick() {
343 let (_e, ids) = three();
344 let mut col: Column<u32> = Column::new();
345 col.push(ids[0], 10, Tick(1));
346 assert_eq!(col.ticks().structural, Tick(1));
347 col.value_mut(0, Tick(2));
349 assert_eq!(col.ticks().structural, Tick(1));
350 col.push(ids[1], 20, Tick(3));
351 col.swap_remove(0, Tick(4));
352 assert_eq!(col.ticks().structural, Tick(4));
353 assert_eq!(col.row_ticks(), &[Tick(3)]);
355 col.clear(Tick(5));
356 assert_eq!(col.ticks().structural, Tick(5));
357 assert!(col.row_ticks().is_empty());
358 }
359
360 #[test]
361 fn changed_rows_survives_tick_wraparound() {
362 let (_e, ids) = three();
363 let mut col: Column<u32> = Column::new();
364 col.push(ids[0], 10, Tick(u32::MAX - 1));
365 col.push(ids[1], 20, Tick(u32::MAX - 1));
366 *col.value_mut(0, Tick(2)).unwrap() = 11;
368 let changed: Vec<Entity> = col
369 .changed_rows(Tick(u32::MAX - 1))
370 .map(|(e, _)| e)
371 .collect();
372 assert_eq!(changed, vec![ids[0]]);
373 }
374
375 #[test]
376 fn iter_mut_with_entities_pairs_rows_and_stamps_change() {
377 let (_e, ids) = three();
378 let mut col: Column<u32> = Column::new();
379 col.push(ids[0], 10, Tick(1));
380 col.push(ids[1], 20, Tick(1));
381 let seen: Vec<Entity> = col
382 .iter_mut_with_entities(Tick(4))
383 .map(|(e, v)| {
384 *v += 1;
385 e
386 })
387 .collect();
388 assert_eq!(seen, vec![ids[0], ids[1]]);
389 assert_eq!(&col[..], &[11, 21]);
390 assert!(col.changed_since(Tick(3)));
391 assert!(!col.changed_since(Tick(4)));
392 }
393}