hyperion/
component_storage.rs

1use crate::entity::Entity;
2use std::any::Any;
3use std::collections::HashMap;
4
5/// Marker trait for types that can be used as components in the ECS.
6pub trait Component: 'static {}
7
8/// Storage for components of type `T`. Maintains dense storage and entity-index mappings.
9///
10/// # Fields
11/// - `components`: Dense array of components of type `T`.
12/// - `entity_to_index`: Map from `Entity` to its dense array index.
13/// - `index_to_entity`: Reverse map from dense array index to owning `Entity`.
14///
15/// # Safety
16/// - Storage remains dense by using swap-remove on deletion; index maps are updated
17///   accordingly to prevent dangling indices. Component references returned by
18///   queries are valid for the borrow duration and follow Rust's aliasing rules.
19pub struct ComponentStorage<T: Component> {
20    components: Vec<T>,
21    entity_to_index: HashMap<Entity, usize>,
22    index_to_entity: Vec<Entity>,
23}
24
25impl<T: Component> ComponentStorage<T> {
26    /// Creates a new, empty component storage.
27    ///
28    /// # Returns
29    /// - `ComponentStorage<T>`: An empty storage ready to hold components of type `T`.
30    pub fn new() -> Self {
31        Self {
32            components: Vec::new(),
33            entity_to_index: HashMap::new(),
34            index_to_entity: Vec::new(),
35        }
36    }
37
38    /// Given a reference to a component in this storage, return the owning `Entity`.
39    ///
40    /// This performs an O(n) scan comparing pointer identity within the dense
41    /// component array to locate the index, then maps that index back to the entity.
42    ///
43    /// # Parameters
44    /// - `component`: A reference to a component stored in this storage.
45    ///
46    /// # Returns
47    /// - `Option<Entity>`: The entity that owns the component, if found.
48    pub fn get_entity_for_component(&self, component: &T) -> Option<Entity> {
49        for (idx, comp_ref) in self.components.iter().enumerate() {
50            if std::ptr::eq(comp_ref, component) {
51                return Some(self.index_to_entity[idx]);
52            }
53        }
54        None
55    }
56
57    /// Inserts or replaces a component for an entity.
58    ///
59    /// # Parameters
60    /// - `entity`: The entity that will own the component.
61    /// - `component`: The component instance to insert (or replace if one already exists).
62    pub fn insert(&mut self, entity: Entity, component: T) {
63        if let Some(&index) = self.entity_to_index.get(&entity) {
64            // Replace existing component at index.
65            self.components[index] = component;
66        } else {
67            // Insert new component at end and update mappings.
68            let index = self.components.len();
69            self.components.push(component);
70            self.entity_to_index.insert(entity, index);
71            self.index_to_entity.push(entity);
72        }
73    }
74
75    /// Removes the component for an entity, returning it if present.
76    /// Uses swap-remove to keep storage dense and updates mappings accordingly.
77    ///
78    /// # Parameters
79    /// - `entity`: The entity whose component should be removed.
80    ///
81    /// # Returns
82    /// - `Option<T>`: The removed component if it existed.
83    pub fn remove(&mut self, entity: Entity) -> Option<T> {
84        self.entity_to_index.remove(&entity).map(|index| {
85            let last_index = self.components.len() - 1;
86
87            // If not the last component, swap to keep storage dense
88            if index != last_index {
89                self.components.swap(index, last_index);
90                self.index_to_entity.swap(index, last_index);
91
92                // Update moved entity's mapping to new index
93                let swapped_entity = self.index_to_entity[index];
94                self.entity_to_index.insert(swapped_entity, index);
95            }
96
97            self.index_to_entity.pop();
98            self.components.pop().unwrap()
99        })
100    }
101
102    /// Gets an immutable reference to a component for an entity, if it exists.
103    ///
104    /// # Parameters
105    /// - `entity`: The entity whose component to retrieve.
106    ///
107    /// # Returns
108    /// - `Option<&T>`: A reference to the component if present.
109    pub fn get(&self, entity: Entity) -> Option<&T> {
110        self.entity_to_index
111            .get(&entity)
112            .map(|&index| &self.components[index])
113    }
114
115    /// Gets a mutable reference to a component for an entity, if it exists.
116    ///
117    /// # Parameters
118    /// - `entity`: The entity whose component to retrieve mutably.
119    ///
120    /// # Returns
121    /// - `Option<&mut T>`: A mutable reference to the component if present.
122    pub fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
123        self.entity_to_index
124            .get(&entity)
125            .map(|&index| &mut self.components[index])
126    }
127
128    /// Returns all components as a vector of immutable references.
129    ///
130    /// # Returns
131    /// - `Vec<&T>`: All components currently stored.
132    pub fn get_all(&self) -> Vec<&T> {
133        self.components.iter().collect()
134    }
135
136    /// Returns all components as a vector of mutable references.
137    ///
138    /// # Returns
139    /// - `Vec<&mut T>`: All components currently stored, mutably borrowed.
140    pub fn get_all_mut(&mut self) -> Vec<&mut T> {
141        self.components.iter_mut().collect()
142    }
143
144    /// Returns an iterator over immutable references to components.
145    ///
146    /// # Returns
147    /// - `impl Iterator<Item = &T>`: Iterator over all components.
148    pub fn iter(&self) -> impl Iterator<Item = &T> {
149        self.components.iter()
150    }
151
152    /// Returns an iterator over mutable references to components.
153    ///
154    /// # Returns
155    /// - `impl Iterator<Item = &mut T>`: Iterator over all components mutably.
156    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
157        self.components.iter_mut()
158    }
159
160    /// Returns an iterator over all entities and immutable references to their components.
161    ///
162    /// # Returns
163    /// - `impl Iterator<Item = (Entity, &T)>`: Iterator of `(Entity, &T)` pairs.
164    pub fn iter_with_entities(&self) -> impl Iterator<Item = (Entity, &T)> {
165        self.index_to_entity
166            .iter()
167            .copied()
168            .zip(self.components.iter())
169    }
170
171    /// Returns an iterator over all entities and mutable references to their components.
172    ///
173    /// # Returns
174    /// - `impl Iterator<Item = (Entity, &mut T)>`: Iterator of `(Entity, &mut T)` pairs.
175    pub fn iter_with_entities_mut(&mut self) -> impl Iterator<Item = (Entity, &mut T)> {
176        let entities = self.index_to_entity.clone(); // Clone to avoid borrow checker issues
177        entities.into_iter().zip(self.components.iter_mut())
178    }
179
180    /// Returns true if this storage contains a component for the specified entity.
181    ///
182    /// # Parameters
183    /// - `entity`: The entity to check.
184    ///
185    /// # Returns
186    /// - `bool`: `true` if a component for `entity` exists in this storage.
187    pub fn has(&self, entity: Entity) -> bool {
188        self.entity_to_index.contains_key(&entity)
189    }
190}
191
192/// A type-erased interface over concrete `ComponentStorage<T>` implementations.
193///
194/// Enables the `World` to store heterogeneous component storages behind a single
195/// trait object and perform operations such as removing an entity's component
196/// without knowing the concrete `T` at compile time.
197///
198/// # Safety
199/// - Downcasting is only exposed via `as_any`/`as_any_mut` and is guarded by
200///   external `TypeId` checks in `World` before downcast is attempted.
201/// - `remove_entity` must maintain dense storage invariants of the underlying
202///   storage (e.g., swap-remove updates index maps) when implemented.
203pub trait ComponentStorageTrait {
204    /// Removes the component associated with `entity` from this storage, if present.
205    ///
206    /// # Parameters
207    /// - `entity`: The entity whose component should be removed from this storage.
208    ///
209    /// # Effects
210    /// - If a component exists for `entity`, it is removed. Implementations typically
211    ///   use swap-remove to keep storage dense and update internal mappings accordingly.
212    fn remove_entity(&mut self, entity: Entity);
213
214    /// Returns a type-erased immutable view of this storage for downcasting.
215    ///
216    /// # Returns
217    /// - `&dyn Any`: A reference that can be downcast using `Any::downcast_ref` to
218    ///   access the concrete `ComponentStorage<T>` when the caller knows `T`.
219    ///
220    /// # Safety
221    /// - Callers must only downcast to the correct type, typically ensured via
222    ///   `TypeId` checks performed by `World` helpers.
223    fn as_any(&self) -> &dyn Any;
224
225    /// Returns a type-erased mutable view of this storage for downcasting.
226    ///
227    /// # Returns
228    /// - `&mut dyn Any`: A mutable reference that can be downcast using
229    ///   `Any::downcast_mut` to access the concrete `ComponentStorage<T>`.
230    ///
231    /// # Safety
232    /// - Callers must ensure the downcast target type matches the actual storage type.
233    ///   The `World` ensures correctness via `TypeId` checks before downcasting.
234    fn as_any_mut(&mut self) -> &mut dyn Any;
235}
236
237impl<T: Component> ComponentStorageTrait for ComponentStorage<T> {
238    /// Removes the component for the given `entity` from this concrete storage.
239    ///
240    /// # Parameters
241    /// - `entity`: The entity whose component should be removed.
242    ///
243    /// # Effects
244    /// - If a component exists for `entity`, it is removed using the storage's
245    ///   internal removal logic (swap-remove), maintaining dense storage and
246    ///   updating index mappings accordingly.
247    fn remove_entity(&mut self, entity: Entity) {
248        let _ = self.remove(entity);
249    }
250
251    /// Returns an immutable, type-erased view of this concrete storage for downcasting.
252    ///
253    /// # Returns
254    /// - `&dyn Any`: A reference that can be downcast via `Any::downcast_ref`
255    ///   to `ComponentStorage<T>` by callers that know the concrete `T`.
256    ///
257    /// # Safety
258    /// - Callers must only attempt to downcast to the correct concrete type.
259    ///   The `World` ensures this by checking `TypeId` prior to downcasting.
260    fn as_any(&self) -> &dyn Any {
261        self
262    }
263
264    /// Returns a mutable, type-erased view of this concrete storage for downcasting.
265    ///
266    /// # Returns
267    /// - `&mut dyn Any`: A mutable reference that can be downcast via
268    ///   `Any::downcast_mut` to `ComponentStorage<T>` when the caller knows `T`.
269    ///
270    /// # Safety
271    /// - Callers must ensure the downcast target type matches the underlying
272    ///   storage. `World` APIs guard this via `TypeId` checks before downcasting.
273    fn as_any_mut(&mut self) -> &mut dyn Any {
274        self
275    }
276}