edict/query/
mod.rs

1//! Queries are used to fetch data from the [`World`].
2//!
3//! Basic query types are `&T`, `&mut T`, and `Entities`.
4//! `&T` fetches component `T` for reading. It yields `&T`, so it also
5//! filters out entities that don't have component `T`.
6//! `&mut T` fetches component `T` for writing. And filters same way as `&T`.
7//! `Entities` fetches [`EntityId`]s. All entities have an ID,
8//! so it doesn't filter anything.
9//!
10//! Queries are divided into two categories: stateful and stateless.
11//!
12//! Stateful queries implement `Query` trait and are passed into methods by value.
13//! Some of them have `DefaultQuery` implementation, and can be used in methods
14//! that do not accept query as an argument and only as a type parameter.
15//!
16//! Stateless queries implement `PhantomQuery` trait, and `PhantomData<Q>`
17//! is stateful counterpart for stateless query `Q`.
18//!
19//! All basic queries are stateless.
20//! Advanced queries like `Modified` - that filter entities based on
21//! component modification - and `RelatedTo` - that filter entities based on
22//! entity relation - are stateful.
23//!
24//! Queries can be combined into tuples producing a new query that yields
25//! a tuple of items from the original queries and filtering out entities
26//! that don't satisfy all queries.
27//!
28//! TODO: Derive impl for structures with named fields.
29//!
30//!
31//! Queries can be used with [`World`] to produce a [`View`].
32//! A [`View`] can be iterated to visit all matching entities and fetch
33//! data from them.
34//! [`View`] can also be indexed with [`Entity`] to fetch data from
35//! a specific entity.
36//!
37//! [`World`]: crate::world::World
38//! [`View`]: crate::view::View
39//! [`Entity`]: crate::entity::Entity
40//!
41
42use core::any::TypeId;
43
44use crate::{
45    archetype::Archetype, component::ComponentInfo, entity::EntityId, epoch::EpochId, Access,
46};
47
48pub use self::{
49    alt::{Alt, FetchAlt},
50    // any_of::AnyOf,
51    boolean::{
52        And, And2, And3, And4, And5, And6, And7, And8, BooleanFetch, BooleanFetchOp, BooleanQuery,
53        Or, Or2, Or3, Or4, Or5, Or6, Or7, Or8, Xor, Xor2, Xor3, Xor4, Xor5, Xor6, Xor7, Xor8,
54    },
55    borrow::{
56        FetchBorrowAllRead, FetchBorrowAnyRead, FetchBorrowAnyWrite, FetchBorrowOneRead,
57        FetchBorrowOneWrite, QueryBorrowAll, QueryBorrowAny, QueryBorrowOne,
58    },
59    copied::{Cpy, FetchCopied},
60    entities::{Entities, EntitiesFetch},
61    fetch::{Fetch, UnitFetch, VerifyFetch},
62    filter::{FilteredFetch, Not, With, Without},
63    modified::{
64        Modified, ModifiedFetchAlt, ModifiedFetchCopied, ModifiedFetchRead, ModifiedFetchWith,
65        ModifiedFetchWrite,
66    },
67    read::{FetchRead, Read},
68    with_epoch::{EpochOf, FetchEpoch},
69    write::{FetchWrite, Write},
70};
71
72mod alt;
73// mod any_of;
74mod boolean;
75mod borrow;
76mod copied;
77mod entities;
78mod fetch;
79mod filter;
80mod modified;
81mod option;
82// mod phantom;
83mod read;
84mod tuple;
85mod with_epoch;
86mod write;
87
88/// Types associated with a query type.
89pub trait AsQuery {
90    /// Associated query type.
91    type Query: Query;
92}
93
94/// Types convertible into query type.
95pub trait IntoQuery: AsQuery {
96    /// Converts into query.
97    fn into_query(self) -> Self::Query;
98}
99
100/// Types convertible into query type.
101pub unsafe trait IntoSendQuery: IntoQuery + AsSendQuery {}
102unsafe impl<Q> IntoSendQuery for Q where Q: IntoQuery + AsSendQuery {}
103
104/// Types associated with default-constructible query type.
105pub trait DefaultQuery: AsQuery {
106    /// Returns default query instance.
107    fn default_query() -> Self::Query;
108}
109
110/// Types associated with default-constructible query type.
111pub unsafe trait DefaultSendQuery: DefaultQuery + AsSendQuery {}
112unsafe impl<Q> DefaultSendQuery for Q where Q: DefaultQuery + AsSendQuery {}
113
114/// Detected write aliasing.
115/// Should be either resolved at runtime or reported with panic.
116pub struct WriteAlias;
117
118/// Trait to query components from entities in the world.
119/// Queries implement efficient iteration over entities while yielding
120/// references to the components and optionally [`EntityId`] to address same components later.
121///
122/// [`EntityId`]: edict::entity::EntityId
123pub unsafe trait Query: IntoQuery<Query = Self> + Copy + Send + Sync + 'static {
124    /// Item type this query type yields.
125    type Item<'a>: 'a;
126
127    /// Fetch value type for this query type.
128    /// Contains data from one archetype.
129    type Fetch<'a>: Fetch<'a, Item = Self::Item<'a>> + 'a;
130
131    /// Set to `true` if query fetches at least one mutable component.
132    const MUTABLE: bool;
133
134    /// Set to `true` if query filters individual entities.
135    const FILTERS_ENTITIES: bool = false;
136
137    /// Returns what kind of access the query performs on the component type.
138    /// This method may return stronger access type if it is impossible to know
139    /// exact access with only type-id.
140    #[must_use]
141    fn component_access(&self, comp: &ComponentInfo) -> Result<Option<Access>, WriteAlias>;
142
143    /// Checks if archetype must be visited or skipped.
144    /// If returns `false`, `access_archetype` and `fetch` must not be called,
145    /// meaning that complex query should either skip archetype entirely or
146    /// for this query specifically.
147    ///
148    /// If this method returns `true`, `access_archetype` and `fetch` must be safe to call.
149    #[must_use]
150    fn visit_archetype(&self, archetype: &Archetype) -> bool;
151
152    /// Asks query to provide types and access for the specific archetype.
153    /// Must call provided closure with type id and access pairs.
154    /// Only types from archetype must be used to call closure.
155    ///
156    /// # Safety
157    ///
158    /// Must not be called if `visit_archetype` returned `false`.
159    /// Implementation are allowed to assume conditions that make `visit_archetype` return `true`.
160    unsafe fn access_archetype(&self, archetype: &Archetype, f: impl FnMut(TypeId, Access));
161
162    /// Checks if archetype must be visited or skipped a second time after
163    /// required access was granted.
164    ///
165    /// Most queries do not check visiting again so defaults to `true`.
166    #[must_use]
167    #[inline(always)]
168    fn visit_archetype_late(&self, archetype: &Archetype) -> bool {
169        debug_assert!(self.visit_archetype(archetype));
170        let _ = archetype;
171        true
172    }
173
174    /// Fetches data from one archetype.
175    ///
176    /// # Safety
177    ///
178    /// Must not be called if `visit_archetype` returned `false`.
179    #[must_use]
180    unsafe fn fetch<'a>(
181        &self,
182        arch_idx: u32,
183        archetype: &'a Archetype,
184        epoch: EpochId,
185    ) -> Self::Fetch<'a>;
186
187    /// Returns item for reserved entity if reserved entity (no components) satisfies the query.
188    /// Otherwise returns `None`.
189    #[must_use]
190    #[inline(always)]
191    fn reserved_entity_item<'a>(&self, id: EntityId, idx: u32) -> Option<Self::Item<'a>> {
192        let _ = id;
193        let _ = idx;
194        None
195    }
196}
197
198/// Query that does not mutate any components.
199///
200/// # Safety
201///
202/// [`Query`] must not borrow components mutably.
203/// [`Query`] must not modify entities versions.
204pub unsafe trait ImmutableQuery: Query {
205    /// Checks that query is valid in compile time.
206    const CHECK_VALID: () = {
207        if Self::MUTABLE {
208            panic!("Immutable query cannot fetch mutable components");
209        }
210    };
211}
212
213/// Query that can be used from non-main thread.
214pub unsafe trait SendQuery: Query {}
215
216pub unsafe trait SendImmutableQuery: SendQuery + ImmutableQuery {}
217unsafe impl<Q> SendImmutableQuery for Q where Q: SendQuery + ImmutableQuery {}
218
219/// Query that can be used from non-main thread.
220pub unsafe trait AsSendQuery: AsQuery {}
221
222unsafe impl<Q> AsSendQuery for Q
223where
224    Q: AsQuery,
225    Q::Query: SendQuery,
226{
227}
228
229/// Type alias for items returned by the [`Query`] type.
230pub type QueryItem<'a, Q> = <<Q as AsQuery>::Query as Query>::Item<'a>;