bevy_ecs/storage/
mod.rs

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