Skip to main content

goud_engine/ecs/storage/
traits.rs

1//! Component storage trait definitions.
2//!
3//! This module defines the [`ComponentStorage`] trait, which provides an abstract
4//! interface for component storage backends, and [`AnyComponentStorage`], which
5//! is the object-safe type-erased variant.
6
7use crate::ecs::{Component, Entity};
8
9/// Trait for component storage backends.
10///
11/// `ComponentStorage` defines the interface for storing components indexed by entity.
12/// Any type implementing this trait can be used as a storage backend for components
13/// in the ECS world.
14///
15/// # Type Parameters
16///
17/// The associated type `Item` specifies what component type this storage holds.
18/// It must implement [`Component`] to ensure thread safety requirements are met.
19///
20/// # Thread Safety
21///
22/// Implementations must be `Send + Sync` to allow the ECS world to be shared
23/// across threads. This is enforced by the trait bounds.
24///
25/// # Object Safety
26///
27/// This trait is **not** object-safe due to the associated type. For type-erased
28/// storage, use [`AnyComponentStorage`] which provides a runtime interface.
29///
30/// # Example Implementation
31///
32/// ```
33/// use goud_engine::ecs::{Entity, Component, ComponentStorage, SparseSet};
34///
35/// // Define a custom storage (wrapping SparseSet for this example)
36/// struct MyStorage<T: Component> {
37///     inner: SparseSet<T>,
38/// }
39///
40/// impl<T: Component> ComponentStorage for MyStorage<T> {
41///     type Item = T;
42///
43///     fn insert(&mut self, entity: Entity, value: T) -> Option<T> {
44///         self.inner.insert(entity, value)
45///     }
46///
47///     fn remove(&mut self, entity: Entity) -> Option<T> {
48///         self.inner.remove(entity)
49///     }
50///
51///     fn get(&self, entity: Entity) -> Option<&T> {
52///         self.inner.get(entity)
53///     }
54///
55///     fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
56///         self.inner.get_mut(entity)
57///     }
58///
59///     fn contains(&self, entity: Entity) -> bool {
60///         self.inner.contains(entity)
61///     }
62///
63///     fn len(&self) -> usize {
64///         self.inner.len()
65///     }
66///
67///     fn is_empty(&self) -> bool {
68///         self.inner.is_empty()
69///     }
70/// }
71/// ```
72pub trait ComponentStorage: Send + Sync {
73    /// The component type stored in this storage.
74    type Item: Component;
75
76    /// Inserts a component for the given entity.
77    ///
78    /// If the entity already has a component, the old value is returned.
79    /// Otherwise, `None` is returned.
80    ///
81    /// # Arguments
82    ///
83    /// * `entity` - The entity to associate with the component
84    /// * `value` - The component value to store
85    ///
86    /// # Returns
87    ///
88    /// The previous component value if one existed, or `None`.
89    ///
90    /// # Panics
91    ///
92    /// Implementations may panic if `entity` is invalid (e.g., placeholder).
93    fn insert(&mut self, entity: Entity, value: Self::Item) -> Option<Self::Item>;
94
95    /// Removes the component for the given entity.
96    ///
97    /// # Arguments
98    ///
99    /// * `entity` - The entity whose component to remove
100    ///
101    /// # Returns
102    ///
103    /// The removed component if one existed, or `None`.
104    fn remove(&mut self, entity: Entity) -> Option<Self::Item>;
105
106    /// Returns a reference to the component for the given entity.
107    ///
108    /// # Arguments
109    ///
110    /// * `entity` - The entity to look up
111    ///
112    /// # Returns
113    ///
114    /// A reference to the component if the entity has one, or `None`.
115    fn get(&self, entity: Entity) -> Option<&Self::Item>;
116
117    /// Returns a mutable reference to the component for the given entity.
118    ///
119    /// # Arguments
120    ///
121    /// * `entity` - The entity to look up
122    ///
123    /// # Returns
124    ///
125    /// A mutable reference to the component if the entity has one, or `None`.
126    fn get_mut(&mut self, entity: Entity) -> Option<&mut Self::Item>;
127
128    /// Returns `true` if the entity has a component in this storage.
129    ///
130    /// # Arguments
131    ///
132    /// * `entity` - The entity to check
133    fn contains(&self, entity: Entity) -> bool;
134
135    /// Returns the number of components in this storage.
136    fn len(&self) -> usize;
137
138    /// Returns `true` if this storage contains no components.
139    fn is_empty(&self) -> bool;
140}
141
142/// Type-erased component storage for runtime operations.
143///
144/// Unlike [`ComponentStorage`], this trait is object-safe and can be used for
145/// type-erased storage in the ECS world. It provides basic operations that
146/// don't require knowing the concrete component type.
147///
148/// # Usage
149///
150/// This trait is primarily used internally by the ECS world to manage storage
151/// for different component types. Most users should interact with components
152/// through the typed [`ComponentStorage`] trait.
153///
154/// # Example
155///
156/// ```
157/// use goud_engine::ecs::{Entity, Component, SparseSet, AnyComponentStorage};
158///
159/// struct Position { x: f32, y: f32 }
160/// impl Component for Position {}
161///
162/// let mut storage: Box<dyn AnyComponentStorage> = Box::new(SparseSet::<Position>::new());
163///
164/// let entity = Entity::new(0, 1);
165///
166/// // Type-erased operations
167/// assert!(!storage.contains_entity(entity));
168/// assert_eq!(storage.storage_len(), 0);
169/// assert!(storage.storage_is_empty());
170/// ```
171pub trait AnyComponentStorage: Send + Sync {
172    /// Returns `true` if the entity has a component in this storage.
173    fn contains_entity(&self, entity: Entity) -> bool;
174
175    /// Removes the component for the given entity (dropping the value).
176    ///
177    /// Returns `true` if a component was removed, `false` otherwise.
178    fn remove_entity(&mut self, entity: Entity) -> bool;
179
180    /// Returns the number of components in this storage.
181    fn storage_len(&self) -> usize;
182
183    /// Returns `true` if this storage contains no components.
184    fn storage_is_empty(&self) -> bool;
185
186    /// Clears all components from this storage.
187    fn clear(&mut self);
188
189    /// Returns the type name of the stored component (for debugging).
190    fn component_type_name(&self) -> &'static str;
191}