Skip to content

Commit 5f75dab

Browse files
committed
ecs: Remove GATs from QueryDriver
This splits query lifetimes in two: 'w is the lifetime of the ECS and 'q is the lifetime of the query. Additionally, QueryDriver::iter now returns a struct instead of an impl Iterator. These changes allow GATs to be removed from the QueryDriver implementation.
1 parent 52b8b63 commit 5f75dab

File tree

5 files changed

+81
-42
lines changed

5 files changed

+81
-42
lines changed

quill/ecs/src/ecs.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
entity::{Entities, EntityId},
1010
entity_builder::EntityBuilder,
1111
storage::SparseSetStorage,
12-
QueryDriver, QueryTuple,
12+
QueryDriver,
1313
};
1414

1515
pub use self::components::Components;
@@ -140,6 +140,7 @@ impl Ecs {
140140
Ok(())
141141
}
142142

143+
/*
143144
/// Queries for all entities that have the given set of components.
144145
///
145146
/// Returns an iterator over tuples of `(entity, components)`.
@@ -164,6 +165,7 @@ impl Ecs {
164165
(entity, components)
165166
}))
166167
}
168+
*/
167169

168170
fn check_entity(&self, entity: EntityId) -> Result<(), EntityDead> {
169171
self.entities

quill/ecs/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#![allow(unused)] // TEMP (remove before merge)
22
#![allow(unstable_name_collisions)]
3-
#![feature(generic_associated_types)] // TEMP: need to figure out how to remove this before merge (needed for queries)
4-
#![allow(incomplete_features)]
53

64
mod borrow;
75
mod bundle;
@@ -17,5 +15,5 @@ pub use component::Component;
1715
pub use ecs::{ComponentError, Components, Ecs, EntityDead};
1816
pub use entity::EntityId;
1917
pub use entity_builder::EntityBuilder;
20-
pub use query::{QueryDriver, QueryItem, QueryParameter, QueryTuple};
18+
pub use query::{QueryDriver, QueryItem};
2119
pub use storage::{SparseSetRef, SparseSetStorage};

quill/ecs/src/query.rs

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,32 @@
22
33
use std::{any::TypeId, cell::Cell, ops::Deref};
44

5-
use crate::{Component, Components, Ecs, SparseSetRef, SparseSetStorage};
5+
use crate::{storage::sparse_set, Component, Components, Ecs, SparseSetRef, SparseSetStorage};
66

77
/// Drives a query by yielding the entities
88
/// whose components satisfy the query parameters.
9-
pub struct QueryDriver<'a> {
9+
pub struct QueryDriver<'w, 'q> {
1010
/// A sparse set for each component in the query.
11-
sparse_sets: &'a [SparseSetRef<'a>],
11+
sparse_sets: &'q [SparseSetRef<'w>],
1212

1313
/// The "lead" sparse set, chosen as the set with
1414
/// the smallest number of components.
15-
lead: SparseSetRef<'a>,
15+
lead: SparseSetRef<'q>,
1616

1717
/// Used as the yielded value for the iterator.
1818
/// (We can't own this because of the lack of GATs.)
19-
dense_indices: &'a [Cell<u32>],
19+
dense_indices: &'q [Cell<u32>],
2020
}
2121

22-
impl<'a> QueryDriver<'a> {
22+
impl<'w, 'q> QueryDriver<'w, 'q> {
2323
/// Creates a new `QueryDriver` given the sparse sets
2424
/// whose components are required by the query.
2525
///
2626
/// `dense_indices` should be a zeroed slice of size `sparse_sets.len()`.
2727
///
2828
/// # Panics
2929
/// Panics if `sparse_sets.len() != dense_indices.len()`.
30-
pub fn new(sparse_sets: &'a [SparseSetRef<'a>], dense_indices: &'a [Cell<u32>]) -> Self {
30+
pub fn new(sparse_sets: &'q [SparseSetRef<'w>], dense_indices: &'q [Cell<u32>]) -> Self {
3131
let lead = sparse_sets
3232
.iter()
3333
.min_by_key(|set| set.len())
@@ -45,49 +45,69 @@ impl<'a> QueryDriver<'a> {
4545
self.sparse_sets.len()
4646
}
4747

48-
/// Iterates over all `QueryItem`s yielded by the query.
49-
pub fn iter(&mut self) -> impl Iterator<Item = QueryItem<'a>> + '_ {
50-
let Self {
51-
lead,
52-
dense_indices,
53-
sparse_sets,
54-
} = self;
55-
lead.iter()
56-
.filter_map(move |(entity_index, dense_in_lead)| {
57-
for (i, (index, sparse_set)) in
58-
dense_indices.iter().zip(sparse_sets.iter()).enumerate()
59-
{
60-
index.set(sparse_set.dense_index_of(entity_index)?);
61-
}
62-
63-
Some(QueryItem {
64-
sparse_index: entity_index,
65-
dense_indices,
66-
})
67-
})
48+
/// Iterates over dense and sparse indices matching the query.
49+
pub fn iter(&'q mut self) -> QueryDriverIter<'w, 'q> {
50+
QueryDriverIter {
51+
lead_iter: self.lead.iter(),
52+
driver: self,
53+
}
54+
}
55+
}
56+
57+
/// An iterator for a QueryDriver.
58+
pub struct QueryDriverIter<'w, 'q> {
59+
driver: &'q mut QueryDriver<'w, 'q>,
60+
lead_iter: sparse_set::Iter<'q>,
61+
}
62+
63+
impl<'w, 'q> Iterator for QueryDriverIter<'w, 'q> {
64+
type Item = QueryItem<'q>;
65+
66+
fn next(&mut self) -> Option<Self::Item> {
67+
loop {
68+
let (sparse_index, lead_dense_index) = self.lead_iter.next()?;
69+
70+
for (dense_index, sparse_set) in self
71+
.driver
72+
.dense_indices
73+
.iter()
74+
.zip(self.driver.sparse_sets.iter())
75+
{
76+
dense_index.set(match sparse_set.dense_index_of(sparse_index) {
77+
Some(d) => d,
78+
None => continue,
79+
});
80+
}
81+
82+
break Some(QueryItem {
83+
dense_indices: &self.driver.dense_indices,
84+
sparse_index,
85+
});
86+
}
6887
}
6988
}
7089

7190
/// An item yielded by a query.
72-
pub struct QueryItem<'a> {
91+
pub struct QueryItem<'q> {
7392
/// The `dense` index into the sparse set
7493
/// of each component in the query.
75-
pub dense_indices: &'a [Cell<u32>],
94+
pub dense_indices: &'q [Cell<u32>],
7695
/// The sparse (entity) index of this item.
7796
pub sparse_index: u32,
7897
}
7998

8099
// -- Static queries
81100

101+
/*
82102
/// A typed query element.
83103
pub trait QueryParameter {
84-
type Output<'a>;
104+
type Output;
85105
type Component: Component;
86106
87107
unsafe fn get_unchecked_by_dense_index(
88108
storage: &SparseSetStorage,
89109
dense_index: u32,
90-
) -> Self::Output<'_>;
110+
) -> Self::Output;
91111
}
92112
93113
impl<'a, T> QueryParameter for &'a T
@@ -159,3 +179,4 @@ macro_rules! query_tuple_impl {
159179
}
160180
161181
query_tuple_impl!(1, (T1, 0));
182+
*/

quill/ecs/src/storage.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod blob_array;
22
mod component_vec;
3-
mod sparse_set;
3+
pub(crate) mod sparse_set;
44

55
pub use sparse_set::{SparseSetRef, SparseSetStorage};

quill/ecs/src/storage/sparse_set.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
use std::{any::TypeId, iter, mem::MaybeUninit, ptr::NonNull};
1+
use core::slice;
2+
use std::{
3+
any::TypeId,
4+
iter::{self, Enumerate},
5+
mem::MaybeUninit,
6+
ptr::NonNull,
7+
};
28

39
use crate::{
410
borrow::BorrowFlag,
@@ -166,11 +172,23 @@ impl<'a> SparseSetRef<'a> {
166172
}
167173

168174
/// Returns an iterator over (sparse_index, dense_index) within this sparse set.
169-
pub fn iter(&self) -> impl Iterator<Item = (u32, u32)> + '_ {
170-
self.dense
171-
.iter()
172-
.enumerate()
173-
.map(|(dense_index, &sparse_index)| (sparse_index, dense_index as u32))
175+
pub fn iter(&self) -> Iter<'a> {
176+
Iter {
177+
inner: self.dense.iter().enumerate(),
178+
}
179+
}
180+
}
181+
182+
pub struct Iter<'a> {
183+
inner: Enumerate<slice::Iter<'a, u32>>,
184+
}
185+
186+
impl<'a> Iterator for Iter<'a> {
187+
type Item = (u32, u32);
188+
189+
fn next(&mut self) -> Option<Self::Item> {
190+
let (dense_index, sparse_index) = self.inner.next()?;
191+
Some((*sparse_index, dense_index as u32))
174192
}
175193
}
176194

0 commit comments

Comments
 (0)