Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/storage/mod.rs
9377 views
1
#![expect(
2
unsafe_op_in_unsafe_fn,
3
reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."
4
)]
5
6
//! Storage layouts for ECS data.
7
//!
8
//! This module implements the low-level collections that store data in a [`World`]. These all offer minimal and often
9
//! unsafe APIs, and have been made `pub` primarily for debugging and monitoring purposes.
10
//!
11
//! # Fetching Storages
12
//! Each of the below data stores can be fetched via [`Storages`], which can be fetched from a
13
//! [`World`] via [`World::storages`]. It exposes a top level container for each class of storage within
14
//! ECS:
15
//!
16
//! - [`Tables`] - columnar contiguous blocks of memory, optimized for fast iteration.
17
//! - [`SparseSets`] - sparse `HashMap`-like mappings from entities to components, optimized for random
18
//! lookup and regular insertion/removal of components.
19
//! - [`NonSends`] - singleton storage for non send data in the world.
20
//!
21
//! # Safety
22
//! To avoid trivially unsound use of the APIs in this module, it is explicitly impossible to get a mutable
23
//! reference to [`Storages`] from [`World`], and none of the types publicly expose a mutable interface.
24
//!
25
//! [`World`]: crate::world::World
26
//! [`World::storages`]: crate::world::World::storages
27
28
mod blob_array;
29
mod non_send;
30
mod sparse_set;
31
mod table;
32
mod thin_array_ptr;
33
34
pub use non_send::*;
35
pub use sparse_set::*;
36
pub use table::*;
37
38
use crate::component::{ComponentInfo, StorageType};
39
use alloc::vec::Vec;
40
41
/// The raw data stores of a [`World`](crate::world::World)
42
#[derive(Default)]
43
pub struct Storages {
44
/// Backing storage for [`SparseSet`] components.
45
/// Note that sparse sets are only present for components that have been spawned or have had a relevant bundle registered.
46
pub sparse_sets: SparseSets,
47
/// Backing storage for [`Table`] components.
48
pub tables: Tables,
49
/// Backing storage for `!Send` data.
50
pub non_sends: NonSends,
51
}
52
53
impl Storages {
54
/// ensures that the component has its necessary storage initialize.
55
pub fn prepare_component(&mut self, component: &ComponentInfo) {
56
match component.storage_type() {
57
StorageType::Table => {
58
// table needs no preparation
59
}
60
StorageType::SparseSet => {
61
self.sparse_sets.get_or_insert(component);
62
}
63
}
64
}
65
}
66
67
struct AbortOnPanic;
68
69
impl Drop for AbortOnPanic {
70
fn drop(&mut self) {
71
// Panicking while unwinding will force an abort.
72
panic!("Aborting due to allocator error");
73
}
74
}
75
76
/// Unsafe extension functions for `Vec<T>`
77
trait VecExtensions<T> {
78
/// Removes an element from the vector and returns it.
79
///
80
/// The removed element is replaced by the last element of the vector.
81
///
82
/// This does not preserve ordering of the remaining elements, but is O(1). If you need to preserve the element order, use [`remove`] instead.
83
///
84
///
85
/// # Safety
86
///
87
/// All of the following must be true:
88
/// - `self.len() > 1`
89
/// - `index < self.len() - 1`
90
///
91
/// [`remove`]: alloc::vec::Vec::remove
92
/// [`swap_remove`]: alloc::vec::Vec::swap_remove
93
unsafe fn swap_remove_nonoverlapping_unchecked(&mut self, index: usize) -> T;
94
}
95
96
impl<T> VecExtensions<T> for Vec<T> {
97
#[inline]
98
unsafe fn swap_remove_nonoverlapping_unchecked(&mut self, index: usize) -> T {
99
// SAFETY: The caller must ensure that the element at `index` must be valid.
100
// This function, and then the caller takes ownership of the value, and it cannot be
101
// accessed due to the length being decremented immediately after this.
102
let value = unsafe { self.as_mut_ptr().add(index).read() };
103
let len = self.len();
104
let base_ptr = self.as_mut_ptr();
105
// SAFETY: We replace self[index] with the last element. The caller must ensure that
106
// both the last element and `index` must be valid and cannot point to the same place.
107
unsafe { core::ptr::copy_nonoverlapping(base_ptr.add(len - 1), base_ptr.add(index), 1) };
108
// SAFETY: Upheld by caller
109
unsafe { self.set_len(len - 1) };
110
value
111
}
112
}
113
114