bevy_ecs/storage/mod.rs
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
28mod blob_array;
29mod non_send;
30mod sparse_set;
31mod table;
32mod thin_array_ptr;
33
34pub use non_send::*;
35pub use sparse_set::*;
36pub use table::*;
37
38use crate::component::{ComponentInfo, StorageType};
39use alloc::vec::Vec;
40
41/// The raw data stores of a [`World`](crate::world::World)
42#[derive(Default)]
43pub 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
53impl 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
67struct AbortOnPanic;
68
69impl 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>`
77trait 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
96impl<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}