Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/storage/sparse_set.rs
9358 views
1
use crate::{
2
change_detection::{CheckChangeTicks, ComponentTickCells, ComponentTicks, MaybeLocation, Tick},
3
component::{ComponentId, ComponentInfo},
4
entity::{Entity, EntityIndex},
5
query::DebugCheckedUnwrap,
6
storage::{AbortOnPanic, Column, TableRow, VecExtensions},
7
};
8
use alloc::{boxed::Box, vec::Vec};
9
use bevy_ptr::{OwningPtr, Ptr};
10
use core::{cell::UnsafeCell, hash::Hash, marker::PhantomData, num::NonZero, panic::Location};
11
use nonmax::{NonMaxU32, NonMaxUsize};
12
13
#[derive(Debug)]
14
pub(crate) struct SparseArray<I, V = I> {
15
values: Vec<Option<V>>,
16
marker: PhantomData<I>,
17
}
18
19
/// A space-optimized version of [`SparseArray`] that cannot be changed
20
/// after construction.
21
#[derive(Debug)]
22
pub(crate) struct ImmutableSparseArray<I, V = I> {
23
values: Box<[Option<V>]>,
24
marker: PhantomData<I>,
25
}
26
27
impl<I: SparseSetIndex, V> Default for SparseArray<I, V> {
28
fn default() -> Self {
29
Self::new()
30
}
31
}
32
33
impl<I, V> SparseArray<I, V> {
34
#[inline]
35
pub const fn new() -> Self {
36
Self {
37
values: Vec::new(),
38
marker: PhantomData,
39
}
40
}
41
}
42
43
macro_rules! impl_sparse_array {
44
($ty:ident) => {
45
impl<I: SparseSetIndex, V> $ty<I, V> {
46
/// Returns `true` if the collection contains a value for the specified `index`.
47
#[inline]
48
pub fn contains(&self, index: I) -> bool {
49
let index = index.sparse_set_index();
50
self.values.get(index).is_some_and(Option::is_some)
51
}
52
53
/// Returns a reference to the value at `index`.
54
///
55
/// Returns `None` if `index` does not have a value or if `index` is out of bounds.
56
#[inline]
57
pub fn get(&self, index: I) -> Option<&V> {
58
let index = index.sparse_set_index();
59
self.values.get(index).and_then(Option::as_ref)
60
}
61
}
62
};
63
}
64
65
impl_sparse_array!(SparseArray);
66
impl_sparse_array!(ImmutableSparseArray);
67
68
impl<I: SparseSetIndex, V> SparseArray<I, V> {
69
/// Inserts `value` at `index` in the array.
70
///
71
/// # Panics
72
/// - Panics if the insertion forces a reallocation, and any of the new capacity overflows `isize::MAX` bytes.
73
/// - Panics if the insertion forces a reallocation, and any of the new the reallocations causes an out-of-memory error.
74
///
75
/// If `index` is out-of-bounds, this will enlarge the buffer to accommodate it.
76
#[inline]
77
pub fn insert(&mut self, index: I, value: V) {
78
let index = index.sparse_set_index();
79
if index >= self.values.len() {
80
self.values.resize_with(index + 1, || None);
81
}
82
self.values[index] = Some(value);
83
}
84
85
/// Returns a mutable reference to the value at `index`.
86
///
87
/// Returns `None` if `index` does not have a value or if `index` is out of bounds.
88
#[inline]
89
pub fn get_mut(&mut self, index: I) -> Option<&mut V> {
90
let index = index.sparse_set_index();
91
self.values.get_mut(index).and_then(Option::as_mut)
92
}
93
94
/// Removes and returns the value stored at `index`.
95
///
96
/// Returns `None` if `index` did not have a value or if `index` is out of bounds.
97
#[inline]
98
pub fn remove(&mut self, index: I) -> Option<V> {
99
let index = index.sparse_set_index();
100
self.values.get_mut(index).and_then(Option::take)
101
}
102
103
/// Removes all of the values stored within.
104
pub fn clear(&mut self) {
105
self.values.clear();
106
}
107
108
/// Converts the [`SparseArray`] into an immutable variant.
109
pub(crate) fn into_immutable(self) -> ImmutableSparseArray<I, V> {
110
ImmutableSparseArray {
111
values: self.values.into_boxed_slice(),
112
marker: PhantomData,
113
}
114
}
115
}
116
117
/// A sparse data structure of [`Component`](crate::component::Component)s.
118
///
119
/// Designed for relatively fast insertions and deletions.
120
#[derive(Debug)]
121
pub struct ComponentSparseSet {
122
/// Capacity and length match those of `entities`.
123
dense: Column,
124
// Internally this only relies on the Entity index to keep track of where the component data is
125
// stored for entities that are alive. The generation is not required, but is stored
126
// in debug builds to validate that access is correct.
127
#[cfg(not(debug_assertions))]
128
entities: Vec<EntityIndex>,
129
#[cfg(debug_assertions)]
130
entities: Vec<Entity>,
131
sparse: SparseArray<EntityIndex, TableRow>,
132
}
133
134
impl ComponentSparseSet {
135
/// Creates a new [`ComponentSparseSet`] with a given component type layout and
136
/// initial `capacity`.
137
pub(crate) fn new(component_info: &ComponentInfo, capacity: usize) -> Self {
138
let entities = Vec::with_capacity(capacity);
139
Self {
140
dense: Column::with_capacity(component_info, entities.capacity()),
141
entities,
142
sparse: Default::default(),
143
}
144
}
145
146
/// Removes all of the values stored within.
147
pub(crate) fn clear(&mut self) {
148
// SAFETY: This is using the size of the ComponentSparseSet.
149
unsafe { self.dense.clear(self.len()) };
150
self.entities.clear();
151
self.sparse.clear();
152
}
153
154
/// Returns the number of component values in the sparse set.
155
#[inline]
156
pub fn len(&self) -> usize {
157
self.entities.len()
158
}
159
160
/// Returns `true` if the sparse set contains no component values.
161
#[inline]
162
pub fn is_empty(&self) -> bool {
163
self.entities.is_empty()
164
}
165
166
/// Inserts the `entity` key and component `value` pair into this sparse
167
/// set.
168
///
169
/// # Aborts
170
/// - Aborts the process if the insertion forces a reallocation, and any of the new capacity overflows `isize::MAX` bytes.
171
/// - Aborts the process if the insertion forces a reallocation, and any of the new the reallocations causes an out-of-memory error.
172
///
173
/// # Safety
174
/// The `value` pointer must point to a valid address that matches the [`Layout`](std::alloc::Layout)
175
/// inside the [`ComponentInfo`] given when constructing this sparse set.
176
pub(crate) unsafe fn insert(
177
&mut self,
178
entity: Entity,
179
value: OwningPtr<'_>,
180
change_tick: Tick,
181
caller: MaybeLocation,
182
) {
183
if let Some(&dense_index) = self.sparse.get(entity.index()) {
184
#[cfg(debug_assertions)]
185
assert_eq!(entity, self.entities[dense_index.index()]);
186
self.dense.replace(dense_index, value, change_tick, caller);
187
} else {
188
let dense_index = self.entities.len();
189
let capacity = self.entities.capacity();
190
191
#[cfg(not(debug_assertions))]
192
self.entities.push(entity.index());
193
#[cfg(debug_assertions)]
194
self.entities.push(entity);
195
196
// If any of the following operations panic due to an allocation error, the state
197
// of the `ComponentSparseSet` will be left in an invalid state and potentially cause UB.
198
// We create an AbortOnPanic guard to force panics to terminate the process if this occurs.
199
let _guard = AbortOnPanic;
200
if capacity != self.entities.capacity() {
201
// SAFETY: An entity was just pushed onto `entities`, its capacity cannot be zero.
202
let new_capacity = unsafe { NonZero::new_unchecked(self.entities.capacity()) };
203
if let Some(capacity) = NonZero::new(capacity) {
204
// SAFETY: This is using the capacity of the previous allocation.
205
unsafe { self.dense.realloc(capacity, new_capacity) };
206
} else {
207
self.dense.alloc(new_capacity);
208
}
209
}
210
211
// SAFETY: This entity index does not exist here yet, so there are no duplicates,
212
// and the entity index is `NonMaxU32` so the length must not be max either.
213
let table_row = unsafe { TableRow::new(NonMaxU32::new_unchecked(dense_index as u32)) };
214
self.dense.initialize(table_row, value, change_tick, caller);
215
self.sparse.insert(entity.index(), table_row);
216
217
core::mem::forget(_guard);
218
}
219
}
220
221
/// Returns `true` if the sparse set has a component value for the provided `entity`.
222
#[inline]
223
pub fn contains(&self, entity: Entity) -> bool {
224
#[cfg(debug_assertions)]
225
{
226
if let Some(&dense_index) = self.sparse.get(entity.index()) {
227
#[cfg(debug_assertions)]
228
assert_eq!(entity, self.entities[dense_index.index()]);
229
true
230
} else {
231
false
232
}
233
}
234
#[cfg(not(debug_assertions))]
235
self.sparse.contains(entity.index())
236
}
237
238
/// Returns a reference to the entity's component value.
239
///
240
/// Returns `None` if `entity` does not have a component in the sparse set.
241
#[inline]
242
pub fn get(&self, entity: Entity) -> Option<Ptr<'_>> {
243
self.sparse.get(entity.index()).map(|&dense_index| {
244
#[cfg(debug_assertions)]
245
assert_eq!(entity, self.entities[dense_index.index()]);
246
// SAFETY: if the sparse index points to something in the dense vec, it exists
247
unsafe { self.dense.get_data_unchecked(dense_index) }
248
})
249
}
250
251
/// Returns references to the entity's component value and its added and changed ticks.
252
///
253
/// Returns `None` if `entity` does not have a component in the sparse set.
254
#[inline]
255
pub fn get_with_ticks(&self, entity: Entity) -> Option<(Ptr<'_>, ComponentTickCells<'_>)> {
256
let dense_index = *self.sparse.get(entity.index())?;
257
#[cfg(debug_assertions)]
258
assert_eq!(entity, self.entities[dense_index.index()]);
259
// SAFETY: if the sparse index points to something in the dense vec, it exists
260
unsafe {
261
Some((
262
self.dense.get_data_unchecked(dense_index),
263
ComponentTickCells {
264
added: self.dense.get_added_tick_unchecked(dense_index),
265
changed: self.dense.get_changed_tick_unchecked(dense_index),
266
changed_by: self.dense.get_changed_by_unchecked(dense_index),
267
},
268
))
269
}
270
}
271
272
/// Returns a reference to the "added" tick of the entity's component value.
273
///
274
/// Returns `None` if `entity` does not have a component in the sparse set.
275
#[inline]
276
pub fn get_added_tick(&self, entity: Entity) -> Option<&UnsafeCell<Tick>> {
277
let dense_index = *self.sparse.get(entity.index())?;
278
#[cfg(debug_assertions)]
279
assert_eq!(entity, self.entities[dense_index.index()]);
280
// SAFETY: if the sparse index points to something in the dense vec, it exists
281
unsafe { Some(self.dense.get_added_tick_unchecked(dense_index)) }
282
}
283
284
/// Returns a reference to the "changed" tick of the entity's component value.
285
///
286
/// Returns `None` if `entity` does not have a component in the sparse set.
287
#[inline]
288
pub fn get_changed_tick(&self, entity: Entity) -> Option<&UnsafeCell<Tick>> {
289
let dense_index = *self.sparse.get(entity.index())?;
290
#[cfg(debug_assertions)]
291
assert_eq!(entity, self.entities[dense_index.index()]);
292
// SAFETY: if the sparse index points to something in the dense vec, it exists
293
unsafe { Some(self.dense.get_changed_tick_unchecked(dense_index)) }
294
}
295
296
/// Returns a reference to the "added" and "changed" ticks of the entity's component value.
297
///
298
/// Returns `None` if `entity` does not have a component in the sparse set.
299
#[inline]
300
pub fn get_ticks(&self, entity: Entity) -> Option<ComponentTicks> {
301
let dense_index = *self.sparse.get(entity.index())?;
302
#[cfg(debug_assertions)]
303
assert_eq!(entity, self.entities[dense_index.index()]);
304
// SAFETY: if the sparse index points to something in the dense vec, it exists
305
unsafe { Some(self.dense.get_ticks_unchecked(dense_index)) }
306
}
307
308
/// Returns a reference to the calling location that last changed the entity's component value.
309
///
310
/// Returns `None` if `entity` does not have a component in the sparse set.
311
#[inline]
312
pub fn get_changed_by(
313
&self,
314
entity: Entity,
315
) -> MaybeLocation<Option<&UnsafeCell<&'static Location<'static>>>> {
316
MaybeLocation::new_with_flattened(|| {
317
let dense_index = *self.sparse.get(entity.index())?;
318
#[cfg(debug_assertions)]
319
assert_eq!(entity, self.entities[dense_index.index()]);
320
// SAFETY: if the sparse index points to something in the dense vec, it exists
321
unsafe { Some(self.dense.get_changed_by_unchecked(dense_index)) }
322
})
323
}
324
325
/// Returns the drop function for the component type stored in the sparse set,
326
/// or `None` if it doesn't need to be dropped.
327
#[inline]
328
pub fn get_drop(&self) -> Option<unsafe fn(OwningPtr<'_>)> {
329
self.dense.get_drop()
330
}
331
332
/// Removes the `entity` from this sparse set and returns a pointer to the associated value (if
333
/// it exists).
334
#[must_use = "The returned pointer must be used to drop the removed component."]
335
pub(crate) fn remove_and_forget(&mut self, entity: Entity) -> Option<OwningPtr<'_>> {
336
self.sparse.remove(entity.index()).map(|dense_index| {
337
#[cfg(debug_assertions)]
338
assert_eq!(entity, self.entities[dense_index.index()]);
339
let last = self.entities.len() - 1;
340
if dense_index.index() >= last {
341
#[cfg(debug_assertions)]
342
assert_eq!(dense_index.index(), last);
343
// SAFETY: This is strictly decreasing the length, so it cannot outgrow
344
// it also cannot underflow as an item was just removed from the sparse array.
345
unsafe { self.entities.set_len(last) };
346
// SAFETY: `last` is guaranteed to be the last element in `dense` as the length is synced with
347
// the `entities` store.
348
unsafe {
349
self.dense
350
.get_data_unchecked(dense_index)
351
.assert_unique()
352
.promote()
353
}
354
} else {
355
// SAFETY: The above check ensures that `dense_index` and the last element are not
356
// overlapping, and thus also within bounds.
357
unsafe {
358
self.entities
359
.swap_remove_nonoverlapping_unchecked(dense_index.index());
360
};
361
// SAFETY: The above check ensures that `dense_index` is in bounds.
362
let swapped_entity = unsafe { self.entities.get_unchecked(dense_index.index()) };
363
#[cfg(not(debug_assertions))]
364
let index = *swapped_entity;
365
#[cfg(debug_assertions)]
366
let index = swapped_entity.index();
367
// SAFETY: The swapped entity was just fetched from the entity Vec, it must have already
368
// been inserted and in bounds.
369
unsafe {
370
*self.sparse.get_mut(index).debug_checked_unwrap() = dense_index;
371
}
372
// SAFETY: The above check ensures that `dense_index` and the last element are not
373
// overlapping, and thus also within bounds.
374
unsafe {
375
self.dense
376
.swap_remove_and_forget_unchecked_nonoverlapping(last, dense_index)
377
}
378
}
379
})
380
}
381
382
/// Removes (and drops) the entity's component value from the sparse set.
383
///
384
/// Returns `true` if `entity` had a component value in the sparse set.
385
pub(crate) fn remove(&mut self, entity: Entity) -> bool {
386
self.sparse
387
.remove(entity.index())
388
.map(|dense_index| {
389
#[cfg(debug_assertions)]
390
assert_eq!(entity, self.entities[dense_index.index()]);
391
let last = self.entities.len() - 1;
392
if dense_index.index() >= last {
393
#[cfg(debug_assertions)]
394
assert_eq!(dense_index.index(), last);
395
// SAFETY: This is strictly decreasing the length, so it cannot outgrow
396
// it also cannot underflow as an item was just removed from the sparse array.
397
unsafe { self.entities.set_len(last) };
398
// SAFETY: `last` is guaranteed to be the last element in `dense` as the length is synced with
399
// the `entities` store.
400
unsafe { self.dense.drop_last_component(last) };
401
} else {
402
// SAFETY: The above check ensures that `dense_index` and the last element are not
403
// overlapping, and thus also within bounds.
404
unsafe {
405
self.entities
406
.swap_remove_nonoverlapping_unchecked(dense_index.index());
407
};
408
let swapped_entity =
409
// SAFETY: The above check ensures that `dense_index` is in bounds.
410
unsafe { self.entities.get_unchecked(dense_index.index()) };
411
#[cfg(not(debug_assertions))]
412
let index = *swapped_entity;
413
#[cfg(debug_assertions)]
414
let index = swapped_entity.index();
415
// SAFETY: The swapped entity was just fetched from the entity Vec, it must have already
416
// been inserted and in bounds.
417
unsafe {
418
*self.sparse.get_mut(index).debug_checked_unwrap() = dense_index;
419
}
420
// SAFETY: The above check ensures that `dense_index` and the last element are not
421
// overlapping, and thus also within bounds.
422
unsafe {
423
self.dense
424
.swap_remove_and_drop_unchecked_nonoverlapping(last, dense_index);
425
}
426
}
427
})
428
.is_some()
429
}
430
431
pub(crate) fn check_change_ticks(&mut self, check: CheckChangeTicks) {
432
// SAFETY: This is using the valid size of the column.
433
unsafe { self.dense.check_change_ticks(self.len(), check) };
434
}
435
}
436
437
impl Drop for ComponentSparseSet {
438
fn drop(&mut self) {
439
let len = self.entities.len();
440
self.entities.clear();
441
// SAFETY: `cap` and `len` are correct. `dense` is never accessed again after this call.
442
unsafe {
443
self.dense.drop(self.entities.capacity(), len);
444
}
445
}
446
}
447
448
/// A data structure that blends dense and sparse storage
449
///
450
/// `I` is the type of the indices, while `V` is the type of data stored in the dense storage.
451
#[derive(Debug)]
452
pub struct SparseSet<I, V: 'static> {
453
dense: Vec<V>,
454
indices: Vec<I>,
455
sparse: SparseArray<I, NonMaxUsize>,
456
}
457
458
/// A space-optimized version of [`SparseSet`] that cannot be changed
459
/// after construction.
460
#[derive(Debug)]
461
pub(crate) struct ImmutableSparseSet<I, V: 'static> {
462
dense: Box<[V]>,
463
indices: Box<[I]>,
464
sparse: ImmutableSparseArray<I, NonMaxUsize>,
465
}
466
467
macro_rules! impl_sparse_set {
468
($ty:ident) => {
469
impl<I: SparseSetIndex, V> $ty<I, V> {
470
/// Returns the number of elements in the sparse set.
471
#[inline]
472
pub fn len(&self) -> usize {
473
self.dense.len()
474
}
475
476
/// Returns `true` if the sparse set contains a value for `index`.
477
#[inline]
478
pub fn contains(&self, index: I) -> bool {
479
self.sparse.contains(index)
480
}
481
482
/// Returns a reference to the value for `index`.
483
///
484
/// Returns `None` if `index` does not have a value in the sparse set.
485
pub fn get(&self, index: I) -> Option<&V> {
486
self.sparse.get(index).map(|dense_index| {
487
// SAFETY: if the sparse index points to something in the dense vec, it exists
488
unsafe { self.dense.get_unchecked(dense_index.get()) }
489
})
490
}
491
492
/// Returns a mutable reference to the value for `index`.
493
///
494
/// Returns `None` if `index` does not have a value in the sparse set.
495
pub fn get_mut(&mut self, index: I) -> Option<&mut V> {
496
let dense = &mut self.dense;
497
self.sparse.get(index).map(move |dense_index| {
498
// SAFETY: if the sparse index points to something in the dense vec, it exists
499
unsafe { dense.get_unchecked_mut(dense_index.get()) }
500
})
501
}
502
503
/// Returns an iterator visiting all keys (indices) in arbitrary order.
504
pub fn indices(&self) -> &[I] {
505
&self.indices
506
}
507
508
/// Returns an iterator visiting all values in arbitrary order.
509
pub fn values(&self) -> impl Iterator<Item = &V> {
510
self.dense.iter()
511
}
512
513
/// Returns an iterator visiting all values mutably in arbitrary order.
514
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
515
self.dense.iter_mut()
516
}
517
518
/// Returns an iterator visiting all key-value pairs in arbitrary order, with references to the values.
519
pub fn iter(&self) -> impl Iterator<Item = (&I, &V)> {
520
self.indices.iter().zip(self.dense.iter())
521
}
522
523
/// Returns an iterator visiting all key-value pairs in arbitrary order, with mutable references to the values.
524
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&I, &mut V)> {
525
self.indices.iter().zip(self.dense.iter_mut())
526
}
527
}
528
};
529
}
530
531
impl_sparse_set!(SparseSet);
532
impl_sparse_set!(ImmutableSparseSet);
533
534
impl<I: SparseSetIndex, V> Default for SparseSet<I, V> {
535
fn default() -> Self {
536
Self::new()
537
}
538
}
539
540
impl<I, V> SparseSet<I, V> {
541
/// Creates a new [`SparseSet`].
542
pub const fn new() -> Self {
543
Self {
544
dense: Vec::new(),
545
indices: Vec::new(),
546
sparse: SparseArray::new(),
547
}
548
}
549
}
550
551
impl<I: SparseSetIndex, V> SparseSet<I, V> {
552
/// Creates a new [`SparseSet`] with a specified initial capacity.
553
///
554
/// # Panics
555
/// - Panics if the new capacity of the allocation overflows `isize::MAX` bytes.
556
/// - Panics if the new allocation causes an out-of-memory error.
557
pub fn with_capacity(capacity: usize) -> Self {
558
Self {
559
dense: Vec::with_capacity(capacity),
560
indices: Vec::with_capacity(capacity),
561
sparse: Default::default(),
562
}
563
}
564
565
/// Returns the total number of elements the [`SparseSet`] can hold without needing to reallocate.
566
#[inline]
567
pub fn capacity(&self) -> usize {
568
self.dense.capacity()
569
}
570
571
/// Inserts `value` at `index`.
572
///
573
/// If a value was already present at `index`, it will be overwritten.
574
///
575
/// # Panics
576
/// - Panics if the insertion forces an reallocation and the new capacity overflows `isize::MAX` bytes.
577
/// - Panics if the insertion forces an reallocation and causes an out-of-memory error.
578
pub fn insert(&mut self, index: I, value: V) {
579
if let Some(dense_index) = self.sparse.get(index.clone()).cloned() {
580
// SAFETY: dense indices stored in self.sparse always exist
581
unsafe {
582
*self.dense.get_unchecked_mut(dense_index.get()) = value;
583
}
584
} else {
585
self.sparse
586
.insert(index.clone(), NonMaxUsize::new(self.dense.len()).unwrap());
587
self.indices.push(index);
588
self.dense.push(value);
589
}
590
}
591
592
/// Returns a reference to the value for `index`, inserting one computed from `func`
593
/// if not already present.
594
///
595
/// # Panics
596
/// - Panics if the insertion forces an reallocation and the new capacity overflows `isize::MAX` bytes.
597
/// - Panics if the insertion forces an reallocation and causes an out-of-memory error.
598
pub fn get_or_insert_with(&mut self, index: I, func: impl FnOnce() -> V) -> &mut V {
599
if let Some(dense_index) = self.sparse.get(index.clone()).cloned() {
600
// SAFETY: dense indices stored in self.sparse always exist
601
unsafe { self.dense.get_unchecked_mut(dense_index.get()) }
602
} else {
603
let value = func();
604
let dense_index = self.dense.len();
605
self.sparse
606
.insert(index.clone(), NonMaxUsize::new(dense_index).unwrap());
607
self.indices.push(index);
608
self.dense.push(value);
609
// SAFETY: dense index was just populated above
610
unsafe { self.dense.get_unchecked_mut(dense_index) }
611
}
612
}
613
614
/// Returns `true` if the sparse set contains no elements.
615
#[inline]
616
pub fn is_empty(&self) -> bool {
617
self.dense.len() == 0
618
}
619
620
/// Removes and returns the value for `index`.
621
///
622
/// Returns `None` if `index` does not have a value in the sparse set.
623
pub fn remove(&mut self, index: I) -> Option<V> {
624
self.sparse.remove(index).map(|dense_index| {
625
let index = dense_index.get();
626
let is_last = index == self.dense.len() - 1;
627
let value = self.dense.swap_remove(index);
628
self.indices.swap_remove(index);
629
if !is_last {
630
let swapped_index = self.indices[index].clone();
631
*self.sparse.get_mut(swapped_index).unwrap() = dense_index;
632
}
633
value
634
})
635
}
636
637
/// Clears all of the elements from the sparse set.
638
///
639
/// # Panics
640
/// - Panics if any of the keys or values implements [`Drop`] and any of those panic.
641
pub fn clear(&mut self) {
642
self.dense.clear();
643
self.indices.clear();
644
self.sparse.clear();
645
}
646
647
/// Converts the sparse set into its immutable variant.
648
pub(crate) fn into_immutable(self) -> ImmutableSparseSet<I, V> {
649
ImmutableSparseSet {
650
dense: self.dense.into_boxed_slice(),
651
indices: self.indices.into_boxed_slice(),
652
sparse: self.sparse.into_immutable(),
653
}
654
}
655
}
656
657
/// Represents something that can be stored in a [`SparseSet`] as an integer.
658
///
659
/// Ideally, the `usize` values should be very small (ie: incremented starting from
660
/// zero), as the number of bits needed to represent a `SparseSetIndex` in a `FixedBitSet`
661
/// is proportional to the **value** of those `usize`.
662
pub trait SparseSetIndex: Clone + PartialEq + Eq + Hash {
663
/// Gets the sparse set index corresponding to this instance.
664
fn sparse_set_index(&self) -> usize;
665
/// Creates a new instance of this type with the specified index.
666
fn get_sparse_set_index(value: usize) -> Self;
667
}
668
669
macro_rules! impl_sparse_set_index {
670
($($ty:ty),+) => {
671
$(impl SparseSetIndex for $ty {
672
#[inline]
673
fn sparse_set_index(&self) -> usize {
674
*self as usize
675
}
676
677
#[inline]
678
fn get_sparse_set_index(value: usize) -> Self {
679
value as $ty
680
}
681
})*
682
};
683
}
684
685
impl_sparse_set_index!(u8, u16, u32, u64, usize);
686
687
/// A collection of [`ComponentSparseSet`] storages, indexed by [`ComponentId`]
688
///
689
/// Can be accessed via [`Storages`](crate::storage::Storages)
690
#[derive(Default)]
691
pub struct SparseSets {
692
sets: SparseSet<ComponentId, ComponentSparseSet>,
693
}
694
695
impl SparseSets {
696
/// Returns the number of [`ComponentSparseSet`]s this collection contains.
697
#[inline]
698
pub fn len(&self) -> usize {
699
self.sets.len()
700
}
701
702
/// Returns true if this collection contains no [`ComponentSparseSet`]s.
703
#[inline]
704
pub fn is_empty(&self) -> bool {
705
self.sets.is_empty()
706
}
707
708
/// An Iterator visiting all ([`ComponentId`], [`ComponentSparseSet`]) pairs.
709
/// NOTE: Order is not guaranteed.
710
pub fn iter(&self) -> impl Iterator<Item = (ComponentId, &ComponentSparseSet)> {
711
self.sets.iter().map(|(id, data)| (*id, data))
712
}
713
714
/// Gets a reference to the [`ComponentSparseSet`] of a [`ComponentId`]. This may be `None` if the component has never been spawned.
715
#[inline]
716
pub fn get(&self, component_id: ComponentId) -> Option<&ComponentSparseSet> {
717
self.sets.get(component_id)
718
}
719
720
/// Gets a mutable reference of [`ComponentSparseSet`] of a [`ComponentInfo`].
721
/// Create a new [`ComponentSparseSet`] if not exists.
722
///
723
/// # Panics
724
/// - Panics if the insertion forces an reallocation and the new capacity overflows `isize::MAX` bytes.
725
/// - Panics if the insertion forces an reallocation and causes an out-of-memory error.
726
pub(crate) fn get_or_insert(
727
&mut self,
728
component_info: &ComponentInfo,
729
) -> &mut ComponentSparseSet {
730
if !self.sets.contains(component_info.id()) {
731
self.sets.insert(
732
component_info.id(),
733
ComponentSparseSet::new(component_info, 64),
734
);
735
}
736
737
self.sets.get_mut(component_info.id()).unwrap()
738
}
739
740
/// Gets a mutable reference to the [`ComponentSparseSet`] of a [`ComponentId`]. This may be `None` if the component has never been spawned.
741
pub(crate) fn get_mut(&mut self, component_id: ComponentId) -> Option<&mut ComponentSparseSet> {
742
self.sets.get_mut(component_id)
743
}
744
745
/// Clear entities stored in each [`ComponentSparseSet`]
746
///
747
/// # Panics
748
/// - Panics if any of the components stored within implement [`Drop`] and any of them panic.
749
pub(crate) fn clear_entities(&mut self) {
750
for set in self.sets.values_mut() {
751
set.clear();
752
}
753
}
754
755
pub(crate) fn check_change_ticks(&mut self, check: CheckChangeTicks) {
756
for set in self.sets.values_mut() {
757
set.check_change_ticks(check);
758
}
759
}
760
}
761
762
#[cfg(test)]
763
mod tests {
764
use super::SparseSets;
765
use crate::{
766
component::{Component, ComponentDescriptor, ComponentId, ComponentInfo},
767
entity::{Entity, EntityIndex},
768
storage::SparseSet,
769
};
770
use alloc::{vec, vec::Vec};
771
772
#[derive(Debug, Eq, PartialEq)]
773
struct Foo(usize);
774
775
#[test]
776
fn sparse_set() {
777
let mut set = SparseSet::<Entity, Foo>::default();
778
let e0 = Entity::from_index(EntityIndex::from_raw_u32(0).unwrap());
779
let e1 = Entity::from_index(EntityIndex::from_raw_u32(1).unwrap());
780
let e2 = Entity::from_index(EntityIndex::from_raw_u32(2).unwrap());
781
let e3 = Entity::from_index(EntityIndex::from_raw_u32(3).unwrap());
782
let e4 = Entity::from_index(EntityIndex::from_raw_u32(4).unwrap());
783
784
set.insert(e1, Foo(1));
785
set.insert(e2, Foo(2));
786
set.insert(e3, Foo(3));
787
788
assert_eq!(set.get(e0), None);
789
assert_eq!(set.get(e1), Some(&Foo(1)));
790
assert_eq!(set.get(e2), Some(&Foo(2)));
791
assert_eq!(set.get(e3), Some(&Foo(3)));
792
assert_eq!(set.get(e4), None);
793
794
{
795
let iter_results = set.values().collect::<Vec<_>>();
796
assert_eq!(iter_results, vec![&Foo(1), &Foo(2), &Foo(3)]);
797
}
798
799
assert_eq!(set.remove(e2), Some(Foo(2)));
800
assert_eq!(set.remove(e2), None);
801
802
assert_eq!(set.get(e0), None);
803
assert_eq!(set.get(e1), Some(&Foo(1)));
804
assert_eq!(set.get(e2), None);
805
assert_eq!(set.get(e3), Some(&Foo(3)));
806
assert_eq!(set.get(e4), None);
807
808
assert_eq!(set.remove(e1), Some(Foo(1)));
809
810
assert_eq!(set.get(e0), None);
811
assert_eq!(set.get(e1), None);
812
assert_eq!(set.get(e2), None);
813
assert_eq!(set.get(e3), Some(&Foo(3)));
814
assert_eq!(set.get(e4), None);
815
816
set.insert(e1, Foo(10));
817
818
assert_eq!(set.get(e1), Some(&Foo(10)));
819
820
*set.get_mut(e1).unwrap() = Foo(11);
821
assert_eq!(set.get(e1), Some(&Foo(11)));
822
}
823
824
#[test]
825
fn sparse_sets() {
826
let mut sets = SparseSets::default();
827
828
#[derive(Component, Default, Debug)]
829
struct TestComponent1;
830
831
#[derive(Component, Default, Debug)]
832
struct TestComponent2;
833
834
assert_eq!(sets.len(), 0);
835
assert!(sets.is_empty());
836
837
register_component::<TestComponent1>(&mut sets, 1);
838
assert_eq!(sets.len(), 1);
839
840
register_component::<TestComponent2>(&mut sets, 2);
841
assert_eq!(sets.len(), 2);
842
843
// check its shape by iter
844
let mut collected_sets = sets
845
.iter()
846
.map(|(id, set)| (id, set.len()))
847
.collect::<Vec<_>>();
848
collected_sets.sort();
849
assert_eq!(
850
collected_sets,
851
vec![(ComponentId::new(1), 0), (ComponentId::new(2), 0),]
852
);
853
854
fn register_component<T: Component>(sets: &mut SparseSets, id: usize) {
855
let descriptor = ComponentDescriptor::new::<T>();
856
let id = ComponentId::new(id);
857
let info = ComponentInfo::new(id, descriptor);
858
sets.get_or_insert(&info);
859
}
860
}
861
}
862
863