1use super::WorldQuery;
2use crate::world::World;
3use std::marker::PhantomData;
4
5pub struct QueryIter<'a, 'w, Q: WorldQuery> {
10 pub(super) world: &'a World,
11 pub(super) archetype_indices: &'a [usize],
12 pub(super) current_arch_idx: usize,
13 pub(super) current_row: usize,
14 pub(super) current_fetch: Option<Q::Fetch<'a>>,
15 pub(super) _marker: PhantomData<Q>,
16 pub(super) _marker_w: PhantomData<&'w ()>,
17}
18
19impl<'a, 'w, Q: WorldQuery> Iterator for QueryIter<'a, 'w, Q>
20where
21 'w: 'a,
22{
23 type Item = (u32, Q::Item<'a>);
24
25 fn next(&mut self) -> Option<Self::Item> {
26 loop {
27 if self.current_arch_idx >= self.archetype_indices.len() {
28 return None;
29 }
30
31 let arch_idx = self.archetype_indices[self.current_arch_idx];
32 let arch = &self.world.archetype_index.archetypes[arch_idx];
33
34 let fetch = match self.current_fetch {
35 Some(f) => f,
36 None => {
37 match unsafe { Q::fetch_raw(self.world, arch, self.world.tick) } {
38 Some(f) => {
39 self.current_fetch = Some(f);
40 self.current_row = 0;
41 f
42 }
43 None => {
44 self.current_arch_idx += 1;
46 continue;
47 }
48 }
49 }
50 };
51
52 if self.current_row < arch.len() {
53 let row = self.current_row;
54 self.current_row += 1;
55 let id = arch.entities()[row];
56 if unsafe { Q::filter_row(fetch, row, id, self.world.change_ref_tick) } {
57 let item = unsafe { Q::get_item(fetch, row, id) };
58 return Some((id, item));
59 }
60 continue;
61 }
62
63 self.current_fetch = None;
64 self.current_arch_idx += 1;
65 }
66 }
67
68 #[inline(always)]
69 fn for_each<F>(self, mut f: F)
70 where
71 Self: Sized,
72 F: FnMut(Self::Item),
73 {
74 for &arch_idx in self.archetype_indices {
75 let arch = &self.world.archetype_index.archetypes[arch_idx];
76 let len = arch.len();
77 if len == 0 {
78 continue;
79 }
80 if let Some(fetch) = unsafe { Q::fetch_raw(self.world, arch, self.world.tick) } {
81 let entities = arch.entities();
82 for (row, &id) in entities.iter().enumerate().take(len) {
83 if unsafe { Q::filter_row(fetch, row, id, self.world.change_ref_tick) } {
84 let item = unsafe { Q::get_item(fetch, row, id) };
85 f((id, item));
86 }
87 }
88 }
89 }
90 }
91}
92
93pub struct QueryChunksIter<'a, 'w, Q: WorldQuery> {
98 pub(super) world: &'a World,
99 pub(super) archetype_indices: &'a [usize],
100 pub(super) current_arch_idx: usize,
101 pub(super) _marker: PhantomData<&'w Q>,
102}
103
104impl<'a, 'w, Q: WorldQuery> Iterator for QueryChunksIter<'a, 'w, Q>
105where
106 'w: 'a,
107{
108 type Item = (&'a [u32], Q::Slice<'a>);
109
110 fn next(&mut self) -> Option<Self::Item> {
111 while self.current_arch_idx < self.archetype_indices.len() {
112 let arch_idx = self.archetype_indices[self.current_arch_idx];
113 self.current_arch_idx += 1;
114
115 let arch = &self.world.archetype_index.archetypes[arch_idx];
116 let len = arch.len();
117 if len == 0 {
118 continue;
119 }
120
121 let fetch = match unsafe { Q::fetch_raw(self.world, arch, self.world.tick) } {
122 Some(f) => f,
123 None => continue,
124 };
125
126 let ids = unsafe { std::slice::from_raw_parts(arch.entities().as_ptr(), len) };
127 let slice = unsafe { Q::get_slice(fetch, len) };
128
129 return Some((ids, slice));
130 }
131 None
132 }
133}