Skip to main content

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}