Skip to main content

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 () {}