ixa/entity/query/
query_impls.rs1use std::any::TypeId;
2
3use seq_macro::seq;
4
5use crate::entity::entity_set::{EntitySetIterator, SourceSet};
6use crate::entity::index::IndexSetResult;
7use crate::entity::multi_property::static_reorder_by_keys;
8use crate::entity::property::Property;
9use crate::entity::{ContextEntitiesExt, Entity, EntityId, HashValueType, Query};
10use crate::hashing::one_shot_128;
11use crate::Context;
12
13impl<E: Entity> Query<E> for () {
14 fn get_query(&self) -> Vec<(usize, HashValueType)> {
15 Vec::new()
16 }
17
18 fn get_type_ids(&self) -> Vec<TypeId> {
19 Vec::new()
20 }
21
22 fn multi_property_id(&self) -> Option<usize> {
23 None
24 }
25
26 fn multi_property_value_hash(&self) -> HashValueType {
27 let empty: &[u128] = &[];
28 one_shot_128(&empty)
29 }
30
31 fn new_query_result_iterator<'c>(&self, context: &'c Context) -> EntitySetIterator<'c, E> {
32 let population_iterator = context.get_entity_iterator::<E>();
33 EntitySetIterator::from_population_iterator(population_iterator)
34 }
35
36 fn match_entity(&self, _entity_id: EntityId<E>, _context: &Context) -> bool {
37 true
39 }
40
41 fn filter_entities(&self, _entities: &mut Vec<EntityId<E>>, _context: &Context) {
42 }
44}
45
46impl<E: Entity, P1: Property<E>> Query<E> for (P1,) {
48 fn get_query(&self) -> Vec<(usize, HashValueType)> {
49 let value = P1::make_canonical(self.0);
50 vec![(P1::id(), P1::hash_property_value(&value))]
51 }
52
53 fn get_type_ids(&self) -> Vec<TypeId> {
54 vec![P1::type_id()]
55 }
56
57 fn multi_property_id(&self) -> Option<usize> {
58 Some(P1::index_id())
61 }
62
63 fn multi_property_value_hash(&self) -> HashValueType {
64 P1::hash_property_value(&P1::make_canonical(self.0))
65 }
66
67 fn new_query_result_iterator<'c>(&self, context: &'c Context) -> EntitySetIterator<'c, E> {
68 let property_store = context.entity_store.get_property_store::<E>();
69
70 if let Some(multi_property_id) = self.multi_property_id() {
75 match property_store.get_index_set_with_hash_for_property_id(
76 context,
77 multi_property_id,
78 self.multi_property_value_hash(),
79 ) {
80 IndexSetResult::Set(people_set) => {
81 return EntitySetIterator::from_index_set(people_set);
82 }
83 IndexSetResult::Empty => {
84 return EntitySetIterator::empty();
85 }
86 IndexSetResult::Unsupported => {}
87 }
88 }
90
91 let mut sources: Vec<SourceSet<E>> = Vec::new();
93
94 if let Some(source_set) = SourceSet::new::<P1>(self.0, context) {
95 sources.push(source_set);
96 } else {
97 return EntitySetIterator::empty();
99 }
100
101 EntitySetIterator::from_sources(sources)
102 }
103
104 fn match_entity(&self, entity_id: EntityId<E>, context: &Context) -> bool {
105 let found_value: P1 = context.get_property(entity_id);
106 found_value == self.0
107 }
108
109 fn filter_entities(&self, entities: &mut Vec<EntityId<E>>, context: &Context) {
110 let property_value_store = context.get_property_value_store::<E, P1>();
111 entities.retain(|entity| self.0 == property_value_store.get(*entity));
112 }
113}
114
115macro_rules! impl_query {
116 ($ct:expr) => {
117 seq!(N in 0..$ct {
118 impl<
119 E: Entity,
120 #(
121 T~N : Property<E>,
122 )*
123 > Query<E> for (
124 #(
125 T~N,
126 )*
127 )
128 {
129 fn get_query(&self) -> Vec<(usize, HashValueType)> {
130 let mut ordered_items = vec![
131 #(
132 (T~N::id(), T~N::hash_property_value(&T~N::make_canonical(self.N))),
133 )*
134 ];
135 ordered_items.sort_unstable_by(|a, b| a.0.cmp(&b.0));
136 ordered_items
137 }
138
139 fn get_type_ids(&self) -> Vec<TypeId> {
140 vec![
141 #(
142 T~N::type_id(),
143 )*
144 ]
145 }
146
147 fn multi_property_value_hash(&self) -> HashValueType {
148 let keys: [&str; $ct] = [
161 #(
162 T~N::name(),
163 )*
164 ];
165 let mut values: [&Vec<u8>; $ct] = [
170 #(
171 &$crate::bincode::serde::encode_to_vec(self.N, bincode::config::standard()).unwrap(),
172 )*
173 ];
174 static_reorder_by_keys(&keys, &mut values);
175
176 let data = values.into_iter().flatten().copied().collect::<Vec<u8>>();
177 one_shot_128(&data.as_slice())
178 }
179
180 fn new_query_result_iterator<'c>(&self, context: &'c Context) -> EntitySetIterator<'c, E> {
181 if let Some(multi_property_id) = self.multi_property_id() {
186 let property_store = context.entity_store.get_property_store::<E>();
187 match property_store.get_index_set_with_hash_for_property_id(
188 context,
189 multi_property_id,
190 self.multi_property_value_hash(),
191 ) {
192 $crate::entity::index::IndexSetResult::Set(entity_set) => {
193 return EntitySetIterator::from_index_set(entity_set);
194 }
195 $crate::entity::index::IndexSetResult::Empty => {
196 return EntitySetIterator::empty();
197 }
198 $crate::entity::index::IndexSetResult::Unsupported => {}
199 }
200 }
202
203 let mut sources: Vec<SourceSet<E>> = Vec::new();
205
206 #(
207 if let Some(source_set) = SourceSet::new::<T~N>(self.N, context) {
208 sources.push(source_set);
209 } else {
210 return EntitySetIterator::empty();
212 }
213 )*
214
215 EntitySetIterator::from_sources(sources)
216 }
217
218 fn match_entity(&self, entity_id: EntityId<E>, context: &Context) -> bool {
219 #(
220 {
221 let found_value: T~N = context.get_property(entity_id);
222 if found_value != self.N {
223 return false
224 }
225 }
226 )*
227 true
228 }
229
230 fn filter_entities(&self, entities: &mut Vec<EntityId<E>>, context: &Context) {
231 if let Some(multi_property_id) = self.multi_property_id() {
233 let property_store = context.entity_store.get_property_store::<E>();
234 match property_store.get_index_set_with_hash_for_property_id(
235 context,
236 multi_property_id,
237 self.multi_property_value_hash(),
238 ) {
239 $crate::entity::index::IndexSetResult::Set(entity_set) => {
240 entities.retain(|entity_id| entity_set.contains(entity_id));
241 return;
242 }
243 $crate::entity::index::IndexSetResult::Empty => {
244 entities.clear();
245 return;
246 }
247 $crate::entity::index::IndexSetResult::Unsupported => {}
248 }
249 }
251
252 #(
254 {
255 let property_value_store = context.get_property_value_store::<E, T~N>();
256 entities.retain(
257 |entity|{
258 self.N == property_value_store.get(*entity)
259 }
260 );
261 }
262 )*
263 }
264 }
265 });
266 }
267}
268
269seq!(Z in 2..10 {
271 impl_query!(Z);
272});