1#![allow(unused_variables)]
29
30use crate::{prelude::*, StorageRef, StorageRefMut};
31use owning_ref::{OwningRef, OwningRefMut};
32use std::collections::BTreeSet;
33
34pub trait Query {
35 type Fetch;
36
37 fn filter(world: &World, entities: &mut Option<BTreeSet<Entity>>) {}
39 fn fetch(world: &World, entity: Entity) -> Self::Fetch;
40}
41
42impl Query for Entity {
43 type Fetch = Entity;
44
45 fn fetch(world: &World, entity: Entity) -> Self::Fetch { entity }
46}
47
48impl Query for Element {
49 type Fetch = Element;
50
51 fn filter(world: &World, entities: &mut Option<BTreeSet<Entity>>) { <&web_sys::Element as Query>::filter(world, entities); }
52 fn fetch(world: &World, entity: Entity) -> Self::Fetch { Element(entity) }
53}
54
55pub struct With<Component: 'static>(std::marker::PhantomData<Component>);
57impl<Component: 'static> Query for With<Component> {
58 type Fetch = ();
59
60 fn filter(world: &World, entities: &mut Option<BTreeSet<Entity>>) { <&Component as Query>::filter(world, entities); }
61
62 fn fetch(world: &World, entity: Entity) -> Self::Fetch {}
63}
64
65impl<Component: 'static> Query for &Component {
66 type Fetch = OwningRef<Box<dyn owning_ref::Erased>, Component>;
67
68 fn filter(world: &World, entities: &mut Option<BTreeSet<Entity>>) {
69 let storage = world.storage::<Component>();
70 if let Some(entities) = entities {
71 entities.retain(|entity| storage.has(entity));
72 } else {
73 *entities = Some(storage.data.keys().copied().collect());
74 }
75 }
76
77 fn fetch(world: &World, entity: Entity) -> Self::Fetch {
78 let storage: StorageRef<Component> = OwningRef::new(world.dyn_storage::<Component>())
79 .map(|x| x.as_any().downcast_ref().unwrap());
80
81 storage
82 .map(|x| x.get(entity).unwrap())
83 .map_owner_box().erase_owner()
84 }
85}
86
87impl<Component: 'static> Query for &mut Component {
88 type Fetch = OwningRefMut<Box<dyn owning_ref::Erased>, Component>;
89
90 fn filter(world: &World, entities: &mut Option<BTreeSet<Entity>>) { <&Component as Query>::filter(world, entities); }
91
92 fn fetch(world: &World, entity: Entity) -> Self::Fetch {
93 let storage: StorageRefMut<Component> = OwningRefMut::new(world.dyn_storage_mut::<Component>())
94 .map_mut(|x| x.as_any_mut().downcast_mut().unwrap());
95
96 storage
97 .map_mut(|x| x.get_mut(entity).unwrap())
98 .map_owner_box().erase_owner()
99 }
100}
101
102macro_rules! impl_for_tuples {
103 (($($_:ident),*)) => {};
104 (($($old:ident),*) $curr:ident $($rest:tt)*) => {
105 impl<$($old: Query,)* $curr: Query> Query for ($($old,)* $curr) {
106 type Fetch = ($($old::Fetch,)* $curr::Fetch);
107
108 fn filter(world: &World, entities: &mut Option<BTreeSet<Entity>>) {
109 $($old::filter(world, entities);)*
110 $curr::filter(world, entities);
111 }
112 fn fetch(world: &World, entity: Entity) -> Self::Fetch {
113 ($($old::fetch(world, entity),)* $curr::fetch(world, entity))
114 }
115 }
116
117 impl_for_tuples![($($old,)* $curr) $($rest)*];
118 };
119 ($first:ident $($rest:tt)*) => {
120 impl_for_tuples![($first) $($rest)*];
121 };
122}
123
124impl_for_tuples![A B C D E F G H I J K L M N O P Q R S T U V W X Y Z];