termite/storage/
storage.rs

1use std::cell::UnsafeCell;
2
3use crate::{
4    ChangeTicks, ComponentDescriptor, ComponentId, ComponentInfo, Entity, EntityIdSet, SparseArray,
5    SparseStorage,
6};
7
8pub struct StorageSets<T> {
9    storage_sets: SparseArray<T>,
10}
11
12impl<T> Default for StorageSets<T> {
13    #[inline]
14    fn default() -> Self {
15        Self {
16            storage_sets: SparseArray::new(),
17        }
18    }
19}
20
21impl<T> StorageSets<T>
22where
23    T: StorageSet,
24{
25    #[inline]
26    pub fn get(&self, id: ComponentId) -> Option<&T> {
27        self.storage_sets.get(id.index())
28    }
29
30    #[inline]
31    pub fn get_mut(&mut self, id: ComponentId) -> Option<&mut T> {
32        self.storage_sets.get_mut(id.index())
33    }
34
35    #[inline]
36    pub unsafe fn get_unchecked(&self, id: ComponentId) -> &T {
37        unsafe { self.storage_sets.get_unchecked(id.index()) }
38    }
39
40    #[inline]
41    pub unsafe fn get_unchecked_mut(&mut self, id: ComponentId) -> &mut T {
42        unsafe { self.storage_sets.get_unchecked_mut(id.index()) }
43    }
44
45    #[inline]
46    pub fn initialize(&mut self, info: &ComponentInfo) {
47        if !self.storage_sets.contains(info.id().index()) {
48            let set = StorageSet::new(*info.descriptor(), info.id().index());
49            self.storage_sets.insert(info.id().index(), set);
50        }
51    }
52
53    #[inline]
54    pub fn remove_and_drop(&mut self, entity: Entity, id: ComponentId) {
55        if let Some(storage) = self.get_mut(id) {
56            storage.remove_and_drop(entity);
57        }
58    }
59
60    #[inline]
61    pub fn remove(&mut self, entity: Entity) {
62        for (_, storage) in self.storage_sets.iter_mut() {
63            storage.remove_and_drop(entity);
64        }
65    }
66}
67
68#[derive(Default)]
69pub struct ComponentStorage {
70    sparse: StorageSets<SparseStorage>,
71}
72
73impl ComponentStorage {
74    #[inline]
75    pub fn sparse(&self) -> &StorageSets<SparseStorage> {
76        &self.sparse
77    }
78
79    #[inline]
80    pub fn sparse_mut(&mut self) -> &mut StorageSets<SparseStorage> {
81        &mut self.sparse
82    }
83
84    #[inline]
85    pub fn remove(&mut self, entity: Entity) {
86        self.sparse.remove(entity);
87    }
88
89    #[inline]
90    pub fn contains(&self, id: ComponentId, entity: Entity) -> bool {
91        if let Some(storage) = self.sparse.get(id) {
92            return storage.contains(entity);
93        }
94
95        false
96    }
97
98    #[inline]
99    pub fn entity_ids(&self, id: ComponentId) -> EntityIdSet {
100        if let Some(sparse) = self.sparse.get(id) {
101            return sparse.entity_ids();
102        }
103
104        EntityIdSet::default()
105    }
106
107    #[inline]
108    pub fn check_change_ticks(&mut self, tick: u32) {
109        for (_, storage) in self.sparse.storage_sets.iter_mut() {
110            storage.check_change_ticks(tick);
111        }
112    }
113}
114
115pub trait StorageSet: Send + Sync + 'static {
116    /// Create a new storage for the given component type `T`.
117    fn new(desc: ComponentDescriptor, capacity: usize) -> Self;
118
119    /// Returns `true` if the storage contains a component for the given entity.
120    fn contains(&self, entity: Entity) -> bool;
121
122    fn entity_ids(&self) -> EntityIdSet;
123
124    /// Inserts a component for the given entity.
125    ///
126    /// # Safety
127    /// - The storage must be able to store components of type `T`.
128    unsafe fn insert(&mut self, entity: Entity, component: *mut u8, change_ticks: u32);
129
130    /// Removes a component for the given entity.
131    ///
132    /// # Safety
133    /// - `entity` must be contained in the storage.
134    /// - `component` must be a valid pointer.
135    unsafe fn remove_unchecked(&mut self, entity: Entity, component: *mut u8);
136
137    /// Removes a component for the given entity.
138    fn remove_and_drop(&mut self, entity: Entity);
139
140    /// Returns a pointer to the component for the given entity.
141    ///
142    /// # Safety
143    /// - `entity` must be contained in the storage.
144    unsafe fn get_unchecked(&self, entity: Entity) -> *mut u8;
145
146    /// Returns a pointer to the component for the given entity.
147    #[inline]
148    fn get(&self, entity: Entity) -> Option<*mut u8> {
149        if self.contains(entity) {
150            unsafe { Some(self.get_unchecked(entity)) }
151        } else {
152            None
153        }
154    }
155
156    /// Returns change ticks for the given entity.
157    ///
158    /// # Safety
159    /// - `entity` must be contained in the storage.
160    unsafe fn get_ticks_unchecked(&self, entity: Entity) -> &UnsafeCell<ChangeTicks>;
161
162    /// Returns a pointer to the component for the given entity and it's change ticks.
163    ///
164    /// # Safety
165    /// - `entity` must be contained in the storage.
166    unsafe fn get_with_ticks_unchecked(
167        &self,
168        entity: Entity,
169    ) -> (*mut u8, &UnsafeCell<ChangeTicks>);
170}