Skip to main content

goud_engine/ecs/query/fetch/
impls.rs

1//! `WorldQuery` implementations for primitive query types.
2//!
3//! Provides implementations for [`Entity`], unit type `()`, and tuples of
4//! up to 8 query elements.
5
6use std::collections::BTreeSet;
7
8use crate::ecs::archetype::Archetype;
9use crate::ecs::component::ComponentId;
10use crate::ecs::entity::Entity;
11use crate::ecs::World;
12
13use super::traits::{ReadOnlyWorldQuery, WorldQuery};
14
15// =============================================================================
16// Entity Implementation
17// =============================================================================
18
19/// `Entity` can be queried to get the entity ID itself.
20///
21/// This is useful when you need the entity ID along with component data,
22/// or when iterating over all entities in an archetype.
23impl WorldQuery for Entity {
24    type Item<'w> = Entity;
25    type State = ();
26
27    #[inline]
28    fn init_state(_world: &World) -> Self::State {
29        // Entity query has no state
30    }
31
32    #[inline]
33    fn component_access(_state: &Self::State) -> BTreeSet<ComponentId> {
34        // Entity query accesses no components
35        BTreeSet::new()
36    }
37
38    #[inline]
39    fn matches_archetype(_state: &Self::State, _archetype: &Archetype) -> bool {
40        // Entity query matches all archetypes
41        true
42    }
43
44    #[inline]
45    fn fetch<'w>(_state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>> {
46        // Return the entity if it's alive
47        if world.is_alive(entity) {
48            Some(entity)
49        } else {
50            None
51        }
52    }
53}
54
55impl ReadOnlyWorldQuery for Entity {}
56
57// =============================================================================
58// Unit Type Implementation
59// =============================================================================
60
61/// Unit type `()` represents an empty query.
62///
63/// This is useful as a base case for tuple queries and for queries that
64/// only use filters without fetching any data.
65impl WorldQuery for () {
66    type Item<'w> = ();
67    type State = ();
68
69    #[inline]
70    fn init_state(_world: &World) -> Self::State {}
71
72    #[inline]
73    fn component_access(_state: &Self::State) -> BTreeSet<ComponentId> {
74        BTreeSet::new()
75    }
76
77    #[inline]
78    fn matches_archetype(_state: &Self::State, _archetype: &Archetype) -> bool {
79        true
80    }
81
82    #[inline]
83    fn fetch<'w>(
84        _state: &Self::State,
85        _world: &'w World,
86        _entity: Entity,
87    ) -> Option<Self::Item<'w>> {
88        Some(())
89    }
90}
91
92impl ReadOnlyWorldQuery for () {}
93
94// =============================================================================
95// Tuple WorldQuery Implementations
96// =============================================================================
97
98// Macro to implement WorldQuery for tuples of different sizes
99macro_rules! impl_tuple_world_query {
100    ($($T:ident),*) => {
101        #[allow(non_snake_case)]
102        impl<$($T: WorldQuery),*> WorldQuery for ($($T,)*) {
103            type Item<'w> = ($($T::Item<'w>,)*);
104            type State = ($($T::State,)*);
105
106            #[inline]
107            fn init_state(world: &World) -> Self::State {
108                ($($T::init_state(world),)*)
109            }
110
111            #[inline]
112            fn component_access(state: &Self::State) -> BTreeSet<ComponentId> {
113                let ($($T,)*) = state;
114                let mut access = BTreeSet::new();
115                $(
116                    access.extend($T::component_access($T));
117                )*
118                access
119            }
120
121            #[inline]
122            fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool {
123                let ($($T,)*) = state;
124                true $(&& $T::matches_archetype($T, archetype))*
125            }
126
127            #[inline]
128            fn fetch<'w>(state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>> {
129                let ($($T,)*) = state;
130                Some((
131                    $($T::fetch($T, world, entity)?,)*
132                ))
133            }
134        }
135
136        // A tuple is ReadOnlyWorldQuery if all its elements are ReadOnlyWorldQuery
137        impl<$($T: ReadOnlyWorldQuery),*> ReadOnlyWorldQuery for ($($T,)*) {}
138    };
139}
140
141// Implement for tuples of size 1-8
142impl_tuple_world_query!(A);
143impl_tuple_world_query!(A, B);
144impl_tuple_world_query!(A, B, C);
145impl_tuple_world_query!(A, B, C, D);
146impl_tuple_world_query!(A, B, C, D, E);
147impl_tuple_world_query!(A, B, C, D, E, F);
148impl_tuple_world_query!(A, B, C, D, E, F, G);
149impl_tuple_world_query!(A, B, C, D, E, F, G, H);