brood/query/mod.rs
1//! Queries over [`World`]s.
2//!
3//! Entities within a `World` are difficult to interact with directly due to being made of
4//! heterogeneous lists of [`Component`]s. Therefore, queries can be executed to give [`Views`] of
5//! `Component`s within the entities stored in a `World`.
6//!
7//! Queries are made up of `Views`, giving access to `Component`s, and [`Filter`]s which can filter
8//! which entities are viewed. Query results are returned as heterogeneous lists, so the
9//! [`result!`] macro is provided to unpack the results.
10//!
11//! # Example
12//! The below example queries mutably for the component `Foo`, immutably for the component `Bar`,
13//! and filters out entities that do not have the component `Baz`.
14//!
15//! ``` rust
16//! use brood::{
17//! entity,
18//! query::{
19//! filter,
20//! result,
21//! Views,
22//! },
23//! Query,
24//! Registry,
25//! World,
26//! };
27//!
28//! // Define components.
29//! struct Foo(u32);
30//! struct Bar(bool);
31//! struct Baz(f64);
32//!
33//! type Registry = Registry!(Foo, Bar, Baz);
34//!
35//! let mut world = World::<Registry>::new();
36//! world.insert(entity!(Foo(42), Bar(true), Baz(1.5)));
37//!
38//! for result!(foo, bar) in world
39//! .query(Query::<Views!(&mut Foo, &Bar), filter::Has<Baz>>::new())
40//! .iter
41//! {
42//! // Do something.
43//! }
44//! ```
45//!
46//! [`Component`]: crate::component::Component
47//! [`Filter`]: crate::query::filter::Filter
48//! [`result!`]: crate::query::result!
49//! [`Views`]: trait@crate::query::view::Views
50//! [`World`]: crate::world::World
51
52pub mod entries;
53pub mod filter;
54pub mod result;
55pub mod view;
56
57#[doc(inline)]
58pub use entries::Entries;
59#[doc(inline)]
60pub use result::{
61 result,
62 Result,
63};
64#[doc(inline)]
65pub use view::inner::Views;
66
67use core::{
68 fmt,
69 marker::PhantomData,
70};
71
72/// Defines a query to be run over a world.
73///
74/// This defines either a regular or parallel query (parallel requires the `rayon` feature to be
75/// enabled). It is essentially a marker type, simply providing the types to the calls to
76/// [`query()`] to make the API as simple to use as possible.
77///
78/// # Example
79/// ``` rust
80/// use brood::{
81/// entity,
82/// query::{
83/// filter,
84/// result,
85/// Views,
86/// },
87/// Query,
88/// Registry,
89/// World,
90/// };
91///
92/// // Define components.
93/// struct Foo(u32);
94/// struct Bar(bool);
95/// struct Baz(f64);
96///
97/// type Registry = Registry!(Foo, Bar, Baz);
98///
99/// let mut world = World::<Registry>::new();
100/// world.insert(entity!(Foo(42), Bar(true), Baz(1.5)));
101///
102/// for result!(foo, bar) in world
103/// .query(Query::<Views!(&mut Foo, &Bar), filter::Has<Baz>>::new())
104/// .iter
105/// {
106/// // Do something.
107/// }
108/// ```
109///
110/// [`query()`]: crate::world::World::query()
111pub struct Query<Views, Filters = filter::None, ResourceViews = view::Null, EntryViews = view::Null>
112{
113 view: PhantomData<Views>,
114 filter: PhantomData<Filters>,
115 resource_views: PhantomData<ResourceViews>,
116 entry_views: PhantomData<EntryViews>,
117}
118
119impl<Views, Filters, ResourceViews, EntryViews> Query<Views, Filters, ResourceViews, EntryViews> {
120 /// Creates a new `Query`.
121 ///
122 /// When creating a query, you must specify the views type `V`, and can optionally specify the
123 /// filter type `F`. If no filter is specified, the default filter, [`filter::None`], will be
124 /// used.
125 #[must_use]
126 pub fn new() -> Self {
127 Self {
128 view: PhantomData,
129 filter: PhantomData,
130 resource_views: PhantomData,
131 entry_views: PhantomData,
132 }
133 }
134}
135
136impl<Views, Filters, ResourceViews, EntryViews> Default
137 for Query<Views, Filters, ResourceViews, EntryViews>
138{
139 fn default() -> Self {
140 Self::new()
141 }
142}
143
144impl<Views, Filters, ResourceViews, EntryViews> Clone
145 for Query<Views, Filters, ResourceViews, EntryViews>
146{
147 fn clone(&self) -> Self {
148 *self
149 }
150}
151
152impl<Views, Filters, ResourceViews, EntryViews> PartialEq
153 for Query<Views, Filters, ResourceViews, EntryViews>
154{
155 fn eq(&self, _other: &Self) -> bool {
156 true
157 }
158}
159
160impl<Views, Filters, ResourceViews, EntryViews> Eq
161 for Query<Views, Filters, ResourceViews, EntryViews>
162{
163}
164
165impl<Views, Filters, ResourceViews, EntryViews> Copy
166 for Query<Views, Filters, ResourceViews, EntryViews>
167{
168}
169
170impl<Views, Filters, ResourceViews, EntryViews> fmt::Debug
171 for Query<Views, Filters, ResourceViews, EntryViews>
172{
173 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
174 formatter.debug_struct("Query").finish()
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::Query;
181 use crate::query::Views;
182 use alloc::format;
183
184 #[test]
185 fn query_default() {
186 assert_eq!(Query::<Views!()>::default(), Query::<Views!()>::new());
187 }
188
189 #[test]
190 fn query_clone() {
191 let query = Query::<Views!()>::new();
192
193 assert_eq!(query.clone(), query);
194 }
195
196 #[test]
197 fn query_debug() {
198 assert_eq!(format!("{:?}", Query::<Views!()>::new()), "Query");
199 }
200}