1mod as_deref;
2mod cloned;
3mod component;
4mod component_mut;
5mod copied;
6mod entity_ref;
7mod ext;
8mod map;
9mod maybe_mut;
10mod opt;
11mod read_only;
12mod relations;
13mod relations_mut;
14mod satisfied;
15mod source;
16mod transform;
17
18use crate::{
19 archetype::{Archetype, ArchetypeId, Slice, Slot},
20 filter::{RefFetch, StaticFilter},
21 system::Access,
22 util::Ptr,
23 ArchetypeSearcher, Entity, World,
24};
25use alloc::vec::Vec;
26use core::fmt::Debug;
27use core::fmt::{self, Formatter};
28
29pub use as_deref::*;
30pub use cloned::*;
31pub use component::*;
32pub use component_mut::*;
33pub use entity_ref::*;
34pub use ext::FetchExt;
35pub use map::Map;
36pub use maybe_mut::{MaybeMut, MutGuard};
37pub use opt::*;
38pub use read_only::*;
39pub use relations::{nth_relation, relations_like, NthRelation, Relations, RelationsIter};
40pub use relations_mut::{relations_like_mut, RelationsIterMut, RelationsMut};
41pub use satisfied::Satisfied;
42pub use source::Source;
43pub use transform::{Added, Modified, TransformFetch};
44
45#[doc(hidden)]
46pub struct FmtQuery<'r, Q>(pub &'r Q);
47
48impl<'r, 'w, Q> Debug for FmtQuery<'r, Q>
49where
50 Q: Fetch<'w>,
51{
52 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
53 self.0.describe(f)
54 }
55}
56
57#[derive(Copy, Clone)]
59pub struct FetchAccessData<'w> {
60 pub world: &'w World,
62 pub arch: &'w Archetype,
64 pub arch_id: ArchetypeId,
66}
67
68impl<'w> From<FetchPrepareData<'w>> for FetchAccessData<'w> {
69 fn from(value: FetchPrepareData<'w>) -> Self {
70 Self {
71 world: value.world,
72 arch: value.arch,
73 arch_id: value.arch_id,
74 }
75 }
76}
77
78#[derive(Copy, Clone)]
80pub struct FetchPrepareData<'w> {
81 pub world: &'w World,
83 pub arch: &'w Archetype,
85 pub arch_id: ArchetypeId,
87 pub old_tick: u32,
89 pub new_tick: u32,
91}
92
93pub trait FetchItem<'q> {
95 type Item;
97}
98
99pub trait Fetch<'w>: for<'q> FetchItem<'q> {
107 const MUTABLE: bool;
109
110 type Prepared: for<'x> PreparedFetch<'x, Item = <Self as FetchItem<'x>>::Item> + 'w;
112
113 fn prepare(&'w self, data: FetchPrepareData<'w>) -> Option<Self::Prepared>;
117
118 fn filter_arch(&self, data: FetchAccessData) -> bool;
120
121 fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>);
123
124 fn describe(&self, f: &mut Formatter<'_>) -> fmt::Result;
126
127 #[inline]
131 fn searcher(&self, _searcher: &mut ArchetypeSearcher) {}
132
133 #[inline]
135 fn by_ref(&self) -> RefFetch<Self>
136 where
137 Self: Sized,
138 {
139 RefFetch(self)
140 }
141}
142
143pub trait PreparedFetch<'q> {
145 type Item: 'q;
147 type Chunk: 'q;
149
150 const HAS_FILTER: bool;
156
157 unsafe fn create_chunk(&'q mut self, slots: Slice) -> Self::Chunk;
163
164 unsafe fn fetch_next(chunk: &mut Self::Chunk) -> Self::Item;
171
172 #[inline]
173 unsafe fn filter_slots(&mut self, slots: Slice) -> Slice {
179 slots
180 }
181}
182
183pub trait UnionFilter {
185 const HAS_UNION_FILTER: bool;
189 unsafe fn filter_union(&mut self, slots: Slice) -> Slice;
194}
195
196impl<'q, F> PreparedFetch<'q> for &'q mut F
197where
198 F: PreparedFetch<'q>,
199{
200 type Item = F::Item;
201 type Chunk = F::Chunk;
202
203 const HAS_FILTER: bool = F::HAS_FILTER;
204
205 unsafe fn create_chunk(&'q mut self, slots: Slice) -> Self::Chunk {
206 (*self).create_chunk(slots)
207 }
208
209 unsafe fn fetch_next(chunk: &mut Self::Chunk) -> Self::Item {
210 F::fetch_next(chunk)
211 }
212
213 unsafe fn filter_slots(&mut self, slots: Slice) -> Slice {
214 (*self).filter_slots(slots)
215 }
216}
217
218impl<'q> FetchItem<'q> for () {
219 type Item = ();
220}
221
222impl UnionFilter for () {
223 const HAS_UNION_FILTER: bool = false;
224
225 unsafe fn filter_union(&mut self, slots: Slice) -> Slice {
226 slots
227 }
228}
229
230impl<'w> Fetch<'w> for () {
231 const MUTABLE: bool = false;
232
233 type Prepared = ();
234
235 fn prepare(&self, _: FetchPrepareData<'w>) -> Option<Self::Prepared> {
236 Some(())
237 }
238
239 fn filter_arch(&self, _: FetchAccessData) -> bool {
240 true
241 }
242
243 fn describe(&self, f: &mut Formatter) -> fmt::Result {
244 write!(f, "()")
245 }
246
247 #[inline]
248 fn access(&self, _: FetchAccessData, _: &mut Vec<Access>) {}
249}
250
251impl<'q> RandomFetch<'q> for () {
252 #[inline]
253 unsafe fn fetch_shared(&'q self, _: Slot) -> Self::Item {}
254 #[inline]
255 unsafe fn fetch_shared_chunk(_: &Self::Chunk, _: Slot) -> Self::Item {}
256}
257
258impl<'q> PreparedFetch<'q> for () {
259 type Item = ();
260
261 type Chunk = ();
262
263 const HAS_FILTER: bool = false;
264
265 #[inline]
266 unsafe fn create_chunk(&'q mut self, _: Slice) -> Self::Chunk {}
267
268 #[inline]
269 unsafe fn fetch_next(_: &mut Self::Chunk) -> Self::Item {}
270}
271
272#[derive(Debug, Clone)]
298pub struct EntityIds;
300#[doc(hidden)]
301pub struct ReadEntities<'a> {
302 entities: &'a [Entity],
303}
304
305impl<'q> FetchItem<'q> for EntityIds {
306 type Item = Entity;
307}
308
309impl<'w> Fetch<'w> for EntityIds {
310 const MUTABLE: bool = false;
311
312 type Prepared = ReadEntities<'w>;
313
314 fn prepare(&self, data: FetchPrepareData<'w>) -> Option<Self::Prepared> {
315 Some(ReadEntities {
316 entities: data.arch.entities(),
317 })
318 }
319
320 fn filter_arch(&self, _: FetchAccessData) -> bool {
321 true
322 }
323
324 fn describe(&self, f: &mut Formatter) -> fmt::Result {
325 f.write_str("entity_ids")
326 }
327
328 #[inline]
329 fn access(&self, _: FetchAccessData, _: &mut Vec<Access>) {}
330}
331
332impl<'w, 'q> PreparedFetch<'q> for ReadEntities<'w> {
333 type Item = Entity;
334 type Chunk = Ptr<'q, Entity>;
335
336 const HAS_FILTER: bool = false;
337
338 unsafe fn create_chunk(&'q mut self, slots: Slice) -> Self::Chunk {
339 Ptr::new(self.entities[slots.as_range()].as_ptr())
340 }
341
342 unsafe fn fetch_next(chunk: &mut Self::Chunk) -> Self::Item {
343 let old = chunk.as_ptr();
344 *chunk = chunk.add(1);
345 *old
346 }
347}
348
349impl<'w, 'q> RandomFetch<'q> for ReadEntities<'w> {
350 #[inline]
351 unsafe fn fetch_shared(&self, slot: usize) -> Self::Item {
352 self.entities[slot]
353 }
354
355 unsafe fn fetch_shared_chunk(chunk: &Self::Chunk, slot: Slot) -> Self::Item {
356 *chunk.add(slot).as_ref()
357 }
358}
359
360macro_rules! tuple_impl {
362 ($($idx: tt => $ty: ident),*) => {
363 impl<'q, $($ty, )*> FetchItem<'q> for ($($ty,)*)
364 where $($ty: FetchItem<'q>,)*
365 {
366 type Item = ($($ty::Item,)*);
367
368 }
369
370 impl<'q, $($ty, )*> RandomFetch<'q> for ($($ty,)*)
371 where $($ty: RandomFetch<'q>,)*
372 {
373
374 #[inline(always)]
375 unsafe fn fetch_shared(&'q self, slot: Slot) -> Self::Item {
376 ($(
377 (self.$idx).fetch_shared(slot),
378 )*)
379 }
380
381 #[inline(always)]
382 unsafe fn fetch_shared_chunk(chunk: &Self::Chunk, slot: Slot) -> Self::Item {
383 ($(
384 $ty::fetch_shared_chunk(&chunk.$idx, slot),
385 )*)
386 }
387 }
388
389
390 impl<'q, $($ty, )*> PreparedFetch<'q> for ($($ty,)*)
391 where $($ty: PreparedFetch<'q>,)*
392 {
393
394 type Item = ($($ty::Item,)*);
395 type Chunk = ($($ty::Chunk,)*);
396
397 const HAS_FILTER: bool = $($ty::HAS_FILTER )||*;
398
399 #[inline]
400 unsafe fn fetch_next(chunk: &mut Self::Chunk) -> Self::Item {
401 ($(
402 $ty::fetch_next(&mut chunk.$idx),
403 )*)
404 }
405
406 #[inline]
407 unsafe fn create_chunk(&'q mut self, slots: Slice) -> Self::Chunk {
408 ($((self.$idx).create_chunk(slots),)*)
409 }
410
411 #[inline]
412 unsafe fn filter_slots(&mut self, mut slots: Slice) -> Slice {
413 $(
414
415 slots = self.$idx.filter_slots(slots);
416 )*
417
418 slots
419 }
420 }
421
422 impl<'q, $($ty, )*> UnionFilter for ($($ty,)*)
423 where $($ty: PreparedFetch<'q>,)*
424 {
425
426 const HAS_UNION_FILTER: bool = $($ty::HAS_FILTER )&&*;
427
428 #[inline]
429 unsafe fn filter_union(&mut self, slots: Slice) -> Slice {
430 [
431 $( self.$idx.filter_slots(slots)),*
433 ]
434 .into_iter()
435 .min()
436 .unwrap_or_default()
437 }
438 }
439
440 impl<'w, $($ty, )*> Fetch<'w> for ($($ty,)*)
441 where $($ty: Fetch<'w>,)*
442 {
443 const MUTABLE: bool = $($ty::MUTABLE )||*;
444 type Prepared = ($($ty::Prepared,)*);
445
446 #[inline]
447 fn prepare(&'w self, data: FetchPrepareData<'w>) -> Option<Self::Prepared> {
448 Some( ($( (self.$idx).prepare(data)?,)*) )
449 }
450
451 #[inline]
452 fn filter_arch(&self, data:FetchAccessData) -> bool {
453 ( $((self.$idx).filter_arch(data)) && * )
454 }
455
456 #[inline]
457 fn describe(&self, f: &mut Formatter) -> fmt::Result {
458 Debug::fmt(&($(FmtQuery(&self.$idx),)*), f)
459 }
460
461 #[inline]
462 fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>) {
463 $( (self.$idx).access(data, dst);)*
464 }
465
466 #[inline]
467 fn searcher(&self, searcher: &mut ArchetypeSearcher) {
468 $((self.$idx).searcher(searcher));*
469 }
470 }
471
472 impl< $($ty: StaticFilter, )*> StaticFilter for ($($ty,)*)
473 {
474 fn filter_static(&self, arch: &Archetype) -> bool {
475 ( $((self.$idx).filter_static(arch)) && * )
476 }
477
478 }
479 };
480}
481
482tuple_impl! { 0 => A }
483tuple_impl! { 0 => A, 1 => B }
484tuple_impl! { 0 => A, 1 => B, 2 => C }
485tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D }
486tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E }
487tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E, 5 => F }
488tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E, 5 => F, 6 => H }
489tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E, 5 => F, 6 => H, 7 => I }
490tuple_impl! { 0 => A, 1 => B, 2 => C, 3 => D, 4 => E, 5 => F, 6 => H, 7 => I, 8 => J }