goud_engine/ecs/system/system_param/traits.rs
1//! Core traits for the system parameter abstraction.
2//!
3//! Defines [`SystemParamState`], [`SystemParam`], and [`ReadOnlySystemParam`].
4
5use crate::ecs::query::Access;
6use crate::ecs::World;
7
8// =============================================================================
9// SystemParamState Trait
10// =============================================================================
11
12/// Trait for the cached state of a system parameter.
13///
14/// System parameters may need to cache information (like component IDs or
15/// resource handles) for efficient repeated extraction. This trait defines
16/// the state type and how to initialize it.
17///
18/// # Requirements
19///
20/// State types must be `Send + Sync` for parallel system execution.
21///
22/// # Example
23///
24/// ```ignore
25/// use goud_engine::ecs::World;
26/// use goud_engine::ecs::system::SystemParamState;
27///
28/// // A simple state that caches nothing
29/// impl SystemParamState for () {
30/// fn init(_world: &mut World) -> Self {}
31/// }
32/// ```
33pub trait SystemParamState: Send + Sync + Sized + 'static {
34 /// Initializes the state from the world.
35 ///
36 /// Called once when the system is first registered. The returned state
37 /// is cached and reused for all subsequent parameter extractions.
38 ///
39 /// # Arguments
40 ///
41 /// * `world` - Mutable reference to the world (may be needed for registration)
42 fn init(world: &mut World) -> Self;
43
44 /// Applies any pending state changes.
45 ///
46 /// Called after system execution to apply deferred operations like
47 /// command buffers. The default implementation does nothing.
48 ///
49 /// # Arguments
50 ///
51 /// * `world` - Mutable reference to the world
52 #[inline]
53 fn apply(&mut self, _world: &mut World) {}
54}
55
56// Blanket implementation for unit type (no state needed)
57impl SystemParamState for () {
58 #[inline]
59 fn init(_world: &mut World) -> Self {}
60}
61
62// =============================================================================
63// SystemParam Trait
64// =============================================================================
65
66/// Trait for types that can be used as system function parameters.
67///
68/// `SystemParam` defines how a type is extracted from the [`World`] when a
69/// function system runs. It provides:
70///
71/// 1. **State caching**: What data to cache between runs
72/// 2. **Access tracking**: What components/resources are accessed
73/// 3. **Parameter fetching**: How to get the actual value from World
74///
75/// # Design
76///
77/// The trait uses associated types and GATs (Generic Associated Types) to
78/// express the complex lifetime relationships between the World borrow,
79/// the parameter value, and the cached state.
80///
81/// # Implementing SystemParam
82///
83/// Most users won't implement this trait directly. Instead, use the built-in
84/// parameter types (Query, Res, ResMut) or derive macros (future).
85///
86/// # Thread Safety
87///
88/// System parameters must properly track their access patterns via
89/// `update_access`. This enables the scheduler to detect conflicts and
90/// safely parallelize system execution.
91///
92/// # Example
93///
94/// ```
95/// use goud_engine::ecs::World;
96/// use goud_engine::ecs::query::Access;
97/// use goud_engine::ecs::system::{SystemParam, SystemParamState, ReadOnlySystemParam};
98///
99/// // A parameter that just provides the entity count
100/// struct EntityCount(usize);
101///
102/// // State for EntityCount (none needed)
103/// struct EntityCountState;
104///
105/// impl SystemParamState for EntityCountState {
106/// fn init(_world: &mut World) -> Self {
107/// EntityCountState
108/// }
109/// }
110///
111/// impl SystemParam for EntityCount {
112/// type State = EntityCountState;
113/// type Item<'w, 's> = EntityCount;
114///
115/// fn update_access(_state: &Self::State, _access: &mut Access) {
116/// // No component access needed
117/// }
118///
119/// fn get_param<'w, 's>(
120/// _state: &'s mut Self::State,
121/// world: &'w World,
122/// ) -> Self::Item<'w, 's> {
123/// EntityCount(world.entity_count())
124/// }
125/// }
126///
127/// // EntityCount is read-only
128/// impl ReadOnlySystemParam for EntityCount {}
129/// ```
130pub trait SystemParam: Sized {
131 /// The cached state for this parameter.
132 ///
133 /// State is initialized once via `SystemParamState::init` and reused
134 /// for all subsequent parameter extractions.
135 type State: SystemParamState;
136
137 /// The type of value this parameter produces.
138 ///
139 /// This is a GAT with two lifetime parameters:
140 /// - `'w`: The World borrow lifetime
141 /// - `'s`: The State borrow lifetime
142 ///
143 /// These separate lifetimes allow for both:
144 /// - References to World data (`'w`)
145 /// - References to cached state (`'s`)
146 type Item<'w, 's>;
147
148 /// Updates the access pattern for this parameter.
149 ///
150 /// Called during system setup to build the complete access pattern.
151 /// Implementations should add any component/resource reads or writes
152 /// to the provided access tracker.
153 ///
154 /// # Arguments
155 ///
156 /// * `state` - The parameter's cached state
157 /// * `access` - Access tracker to update
158 fn update_access(state: &Self::State, access: &mut Access);
159
160 /// Extracts the parameter value from the World.
161 ///
162 /// Called each time the system runs to get the actual parameter value.
163 /// The returned value has lifetimes tied to both the World and the state.
164 ///
165 /// # Arguments
166 ///
167 /// * `state` - Mutable reference to cached state
168 /// * `world` - Immutable reference to the World
169 ///
170 /// # Returns
171 ///
172 /// The extracted parameter value.
173 fn get_param<'w, 's>(state: &'s mut Self::State, world: &'w World) -> Self::Item<'w, 's>;
174
175 /// Extracts the parameter value from a mutable World reference.
176 ///
177 /// Some parameters (like `ResMut`) need mutable world access. This method
178 /// provides that access. The default implementation calls `get_param`.
179 ///
180 /// # Arguments
181 ///
182 /// * `state` - Mutable reference to cached state
183 /// * `world` - Mutable reference to the World
184 ///
185 /// # Returns
186 ///
187 /// The extracted parameter value.
188 #[inline]
189 fn get_param_mut<'w, 's>(
190 state: &'s mut Self::State,
191 world: &'w mut World,
192 ) -> Self::Item<'w, 's> {
193 // Default: use immutable access
194 Self::get_param(state, world)
195 }
196}
197
198// =============================================================================
199// ReadOnlySystemParam Marker Trait
200// =============================================================================
201
202/// Marker trait for system parameters that only read data.
203///
204/// `ReadOnlySystemParam` indicates that a parameter does not mutate the World.
205/// This enables optimizations:
206///
207/// 1. **Parallel execution**: Multiple read-only systems can run concurrently
208/// 2. **Shared borrows**: Can coexist with other readers
209/// 3. **Cache friendliness**: Read-only access enables certain optimizations
210///
211/// # Safety
212///
213/// Implementors must ensure the parameter truly never mutates World state,
214/// even when given mutable access.
215///
216/// # Built-in Implementations
217///
218/// - `Query<Q, F>` where Q: ReadOnlyWorldQuery
219/// - `Res<T>` (immutable resource access)
220/// - `&World` (immutable world access)
221/// - Tuples of read-only parameters
222///
223/// # Example
224///
225/// ```
226/// use goud_engine::ecs::system::ReadOnlySystemParam;
227///
228/// // Marker trait - just implement it for read-only types
229/// // struct MyReadOnlyParam;
230/// // impl ReadOnlySystemParam for MyReadOnlyParam {}
231/// ```
232pub trait ReadOnlySystemParam: SystemParam {}
233
234// =============================================================================
235// Unit Type Implementation
236// =============================================================================
237
238/// Unit type `()` as a system parameter represents no data.
239///
240/// Useful as a base case for tuple parameters or for systems that
241/// don't need any parameters extracted from the World.
242impl SystemParam for () {
243 type State = ();
244 type Item<'w, 's> = ();
245
246 #[inline]
247 fn update_access(_state: &Self::State, _access: &mut Access) {
248 // No access needed
249 }
250
251 #[inline]
252 fn get_param<'w, 's>(_state: &'s mut Self::State, _world: &'w World) -> Self::Item<'w, 's> {}
253}
254
255impl ReadOnlySystemParam for () {}