elevator_core/query/
iter.rs1use std::marker::PhantomData;
4
5use slotmap::basic::Keys;
6
7use crate::entity::EntityId;
8use crate::world::World;
9
10use super::fetch::WorldQuery;
11use super::filter::QueryFilter;
12
13pub struct ExtQueryMut<'w, T: 'static + Send + Sync, F: QueryFilter = ()> {
19 world: &'w mut World,
21 ids: Vec<EntityId>,
23 _marker: PhantomData<(T, F)>,
25}
26
27impl<'w, T: 'static + Send + Sync, F: QueryFilter> ExtQueryMut<'w, T, F> {
28 pub(crate) fn new(world: &'w mut World) -> Self {
30 let ids: Vec<EntityId> = world
31 .alive_keys()
32 .filter(|&id| {
33 world.ext_map::<T>().is_some_and(|m| m.contains_key(id)) && F::matches(world, id)
34 })
35 .collect();
36 Self {
37 world,
38 ids,
39 _marker: PhantomData,
40 }
41 }
42
43 #[must_use]
45 pub fn ids(&self) -> &[EntityId] {
46 &self.ids
47 }
48
49 #[must_use]
51 pub const fn count(&self) -> usize {
52 self.ids.len()
53 }
54
55 pub fn for_each_mut(&mut self, mut f: impl FnMut(EntityId, &mut T)) {
57 for &id in &self.ids {
58 if let Some(val) = self.world.get_ext_mut::<T>(id) {
59 f(id, val);
60 }
61 }
62 }
63}
64
65pub struct QueryBuilder<'w, Q: WorldQuery, F: QueryFilter = ()> {
70 world: &'w World,
72 _marker: PhantomData<(Q, F)>,
74}
75
76impl<'w, Q: WorldQuery, F: QueryFilter> QueryBuilder<'w, Q, F> {
77 pub(crate) const fn new(world: &'w World) -> Self {
79 Self {
80 world,
81 _marker: PhantomData,
82 }
83 }
84
85 #[must_use]
87 pub const fn with<T: 'static>(self) -> QueryBuilder<'w, Q, (F, super::filter::With<T>)>
88 where
89 (F, super::filter::With<T>): QueryFilter,
90 {
91 QueryBuilder::new(self.world)
92 }
93
94 #[must_use]
96 pub const fn without<T: 'static>(self) -> QueryBuilder<'w, Q, (F, super::filter::Without<T>)>
97 where
98 (F, super::filter::Without<T>): QueryFilter,
99 {
100 QueryBuilder::new(self.world)
101 }
102
103 #[must_use]
105 pub const fn ext_with<T: 'static + Send + Sync>(
106 self,
107 ) -> QueryBuilder<'w, Q, (F, super::filter::ExtWith<T>)>
108 where
109 (F, super::filter::ExtWith<T>): QueryFilter,
110 {
111 QueryBuilder::new(self.world)
112 }
113
114 #[must_use]
116 pub const fn ext_without<T: 'static + Send + Sync>(
117 self,
118 ) -> QueryBuilder<'w, Q, (F, super::filter::ExtWithout<T>)>
119 where
120 (F, super::filter::ExtWithout<T>): QueryFilter,
121 {
122 QueryBuilder::new(self.world)
123 }
124
125 #[must_use]
127 pub fn iter(self) -> QueryIter<'w, Q, F> {
128 QueryIter {
129 world: self.world,
130 keys: self.world.alive_keys(),
131 _marker: PhantomData,
132 }
133 }
134
135 #[must_use]
137 pub fn get(self, id: EntityId) -> Option<Q::Item<'w>> {
138 if !Q::contains(self.world, id) || !F::matches(self.world, id) {
139 return None;
140 }
141 Q::fetch(self.world, id)
142 }
143}
144
145pub struct QueryIter<'w, Q: WorldQuery, F: QueryFilter> {
147 world: &'w World,
149 keys: Keys<'w, EntityId, ()>,
151 _marker: PhantomData<(Q, F)>,
153}
154
155impl<'w, Q: WorldQuery, F: QueryFilter> Iterator for QueryIter<'w, Q, F> {
156 type Item = Q::Item<'w>;
157
158 fn next(&mut self) -> Option<Self::Item> {
159 loop {
160 let id = self.keys.next()?;
161 if !Q::contains(self.world, id) {
162 continue;
163 }
164 if !F::matches(self.world, id) {
165 continue;
166 }
167 if let Some(item) = Q::fetch(self.world, id) {
168 return Some(item);
169 }
170 }
171 }
172}
173
174impl<'w, Q: WorldQuery, F: QueryFilter> QueryIter<'w, Q, F> {
175 #[must_use]
177 pub fn count_matches(self) -> usize {
178 self.count()
179 }
180
181 pub fn any_match(mut self, predicate: impl FnMut(Q::Item<'w>) -> bool) -> bool {
183 self.any(predicate)
184 }
185
186 pub fn all_match(mut self, predicate: impl FnMut(Q::Item<'w>) -> bool) -> bool {
190 self.all(predicate)
191 }
192
193 pub fn find_match(
195 mut self,
196 predicate: impl FnMut(&Q::Item<'w>) -> bool,
197 ) -> Option<Q::Item<'w>> {
198 self.find(predicate)
199 }
200}