1use std::marker::PhantomData;
2
3use crate::{entity::EntityId, system::SystemParam, world::UnsafeWorldCell};
4
5use super::QueryComponent;
6
7pub struct Query<'world, Q>
8where
9 Q: QueryComponent,
10{
11 unsafe_world_cell: UnsafeWorldCell<'world>,
12 entity_ids: Vec<EntityId>,
13 _phantom_data: PhantomData<Q>,
14}
15
16impl<'world, Q> Iterator for Query<'world, Q>
17where
18 Q: QueryComponent,
19{
20 type Item = Q::Item<'world>;
21
22 fn next(&mut self) -> Option<Self::Item> {
23 if let Some(entity_id) = self.entity_ids.pop() {
24 let item = Q::get_component(self.unsafe_world_cell, entity_id);
25 return Some(item);
26 }
27
28 None
29 }
30}
31
32impl<'w, Q> SystemParam for Query<'w, Q>
33where
34 Q: QueryComponent,
35{
36 type Item<'world> = Query<'world, Q>;
37
38 fn get_param<'world>(unsafe_world_cell: UnsafeWorldCell<'world>) -> Self::Item<'world> {
39 let entity_ids = {
40 let world = unsafe_world_cell.world();
41 let entities = world.entities();
42 let archetypes = world.archetypes();
43 entities
44 .data
45 .iter()
46 .enumerate()
47 .filter(|(index, data)| {
48 !entities.free_ids.contains(index) && data.archetype_id.is_init() && {
49 let component_ids = &archetypes.get_data(&data.archetype_id).components_ids;
50
51 Q::get_component_ids()
52 .iter()
53 .all(|id| component_ids.contains(id))
54 }
55 })
56 .map(|(index, data)| EntityId {
57 index,
58 gen: data.gen,
59 })
60 .collect::<Vec<_>>()
61 };
62 Query {
63 unsafe_world_cell,
64 entity_ids,
65 _phantom_data: PhantomData,
66 }
67 }
68}