1use crate::{
2    archetype::{
3        Archetype, ArchetypeColumnAccess, ArchetypeDynamicColumnAccess, ArchetypeDynamicColumnItem,
4        ArchetypeDynamicColumnIter, ArchetypeError,
5    },
6    component::{Component, ComponentRef, ComponentRefMut},
7    entity::{Entity, EntityDenseMap},
8    view::WorldView,
9    world::World,
10};
11use intuicio_data::type_hash::TypeHash;
12use std::{
13    collections::{HashMap, HashSet},
14    error::Error,
15    marker::PhantomData,
16    sync::Arc,
17};
18
19#[derive(Debug)]
20pub enum QueryError {
21    Archetype(ArchetypeError),
22    TryingToReadUnavailableType { type_hash: TypeHash },
23    TryingToWriteUnavailableType { type_hash: TypeHash },
24}
25
26impl Error for QueryError {}
27
28impl From<ArchetypeError> for QueryError {
29    fn from(value: ArchetypeError) -> Self {
30        Self::Archetype(value)
31    }
32}
33
34impl std::fmt::Display for QueryError {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        match self {
37            Self::Archetype(archetype) => write!(f, "World archetype: {archetype}"),
38            Self::TryingToReadUnavailableType { type_hash } => {
39                write!(f, "Trying to read unavailable type: {type_hash:?}")
40            }
41            Self::TryingToWriteUnavailableType { type_hash } => {
42                write!(f, "Trying to write unavailable type: {type_hash:?}")
43            }
44        }
45    }
46}
47
48pub struct Query<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>>(
49    PhantomData<fn() -> &'a Fetch>,
50);
51
52impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Default
53    for Query<'a, LOCKING, Fetch>
54{
55    fn default() -> Self {
56        Self(Default::default())
57    }
58}
59
60impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Clone
61    for Query<'a, LOCKING, Fetch>
62{
63    fn clone(&self) -> Self {
64        *self
65    }
66}
67
68impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Copy
69    for Query<'a, LOCKING, Fetch>
70{
71}
72
73impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Query<'a, LOCKING, Fetch> {
74    pub fn query(&self, world: &'a World) -> TypedQueryIter<'a, LOCKING, Fetch> {
75        world.query::<'a, LOCKING, Fetch>()
76    }
77
78    pub fn query_view(&self, view: &'a WorldView) -> TypedQueryIter<'a, LOCKING, Fetch> {
79        view.query::<'a, LOCKING, Fetch>()
80    }
81}
82
83impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> TypedQueryFetch<'a, LOCKING>
84    for Query<'a, LOCKING, Fetch>
85{
86    type Value = ();
87    type Access = ();
88
89    fn does_accept_archetype(archetype: &Archetype) -> bool {
90        Fetch::does_accept_archetype(archetype)
91    }
92
93    fn access(_: &Archetype) -> Result<Self::Access, QueryError> {
94        Ok(())
95    }
96
97    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
98        Some(())
99    }
100}
101
102impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> TypedLookupFetch<'a, LOCKING>
103    for Query<'a, LOCKING, Fetch>
104{
105    type Value = ();
106    type ValueOne = Self::Value;
107    type Access = ();
108
109    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
110        if Fetch::does_accept_archetype(archetype) {
111            Some(())
112        } else {
113            None
114        }
115    }
116
117    fn fetch(_: &mut Self::Access, _: Entity) -> Option<Self::Value> {
118        Some(())
119    }
120
121    fn fetch_one(_: &World, _: Entity) -> Option<Self::ValueOne> {
122        Some(())
123    }
124}
125
126pub struct Lookup<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>(
127    PhantomData<fn() -> &'a Fetch>,
128);
129
130impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> Default
131    for Lookup<'a, LOCKING, Fetch>
132{
133    fn default() -> Self {
134        Self(Default::default())
135    }
136}
137
138impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> Clone
139    for Lookup<'a, LOCKING, Fetch>
140{
141    fn clone(&self) -> Self {
142        *self
143    }
144}
145
146impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> Copy
147    for Lookup<'a, LOCKING, Fetch>
148{
149}
150
151impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> Lookup<'a, LOCKING, Fetch> {
152    pub fn lookup(
153        &self,
154        world: &'a World,
155        entities: impl IntoIterator<Item = Entity> + 'a,
156    ) -> TypedLookupIter<'a, LOCKING, Fetch> {
157        world.lookup::<'a, LOCKING, Fetch>(entities)
158    }
159
160    pub fn lookup_view(
161        &self,
162        view: &'a WorldView,
163        entities: impl IntoIterator<Item = Entity> + 'a,
164    ) -> TypedLookupIter<'a, LOCKING, Fetch> {
165        view.lookup::<'a, LOCKING, Fetch>(entities)
166    }
167
168    pub fn lookup_access(&self, world: &'a World) -> TypedLookupAccess<'a, LOCKING, Fetch> {
169        world.lookup_access::<'a, LOCKING, Fetch>()
170    }
171
172    pub fn lookup_access_view(&self, view: &'a WorldView) -> TypedLookupAccess<'a, LOCKING, Fetch> {
173        view.lookup_access::<'a, LOCKING, Fetch>()
174    }
175}
176
177impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedLookupFetch<'a, LOCKING>
178    for Lookup<'a, LOCKING, Fetch>
179{
180    type Value = ();
181    type ValueOne = Self::Value;
182    type Access = ();
183
184    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
185        if Fetch::try_access(archetype).is_some() {
186            Some(())
187        } else {
188            None
189        }
190    }
191
192    fn fetch(_: &mut Self::Access, _: Entity) -> Option<Self::Value> {
193        Some(())
194    }
195
196    fn fetch_one(_: &World, _: Entity) -> Option<Self::ValueOne> {
197        Some(())
198    }
199}
200
201impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedQueryFetch<'a, LOCKING>
202    for Lookup<'a, LOCKING, Fetch>
203{
204    type Value = ();
205    type Access = ();
206
207    fn does_accept_archetype(archetype: &Archetype) -> bool {
208        let archetype = unsafe { std::mem::transmute::<&Archetype, &Archetype>(archetype) };
209        Fetch::try_access(archetype).is_some()
210    }
211
212    fn access(_: &'a Archetype) -> Result<Self::Access, QueryError> {
213        Ok(())
214    }
215
216    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
217        Some(())
218    }
219}
220
221pub trait TypedQueryFetch<'a, const LOCKING: bool> {
222    type Value;
223    type Access;
224
225    fn does_accept_archetype(archetype: &Archetype) -> bool;
226    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError>;
227    fn fetch(access: &mut Self::Access) -> Option<Self::Value>;
228
229    #[allow(unused_variables)]
230    fn unique_access(output: &mut HashSet<TypeHash>) {}
231}
232
233pub trait TypedLookupFetch<'a, const LOCKING: bool> {
234    type Value;
235    type ValueOne;
236    type Access;
237
238    fn try_access(archetype: &'a Archetype) -> Option<Self::Access>;
239    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value>;
240    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne>;
241
242    #[allow(unused_variables)]
243    fn unique_access(output: &mut HashSet<TypeHash>) {}
244}
245
246pub trait TypedRelationLookupFetch<'a> {
247    type Value;
248    type Access;
249
250    fn access(world: &'a World, entity: Entity) -> Self::Access;
251    fn fetch(access: &mut Self::Access) -> Option<Self::Value>;
252}
253
254pub trait TypedRelationLookupTransform<'a> {
255    type Input;
256    type Output;
257
258    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output>;
259}
260
261impl<const LOCKING: bool> TypedQueryFetch<'_, LOCKING> for () {
262    type Value = ();
263    type Access = ();
264
265    fn does_accept_archetype(_: &Archetype) -> bool {
266        true
267    }
268
269    fn access(_: &Archetype) -> Result<Self::Access, QueryError> {
270        Ok(())
271    }
272
273    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
274        Some(())
275    }
276}
277
278impl<const LOCKING: bool> TypedLookupFetch<'_, LOCKING> for () {
279    type Value = ();
280    type ValueOne = Self::Value;
281    type Access = ();
282
283    fn try_access(_: &Archetype) -> Option<Self::Access> {
284        Some(())
285    }
286
287    fn fetch(_: &mut Self::Access, _: Entity) -> Option<Self::Value> {
288        Some(())
289    }
290
291    fn fetch_one(_: &World, _: Entity) -> Option<Self::ValueOne> {
292        Some(())
293    }
294}
295
296impl<'a, const LOCKING: bool> TypedQueryFetch<'a, LOCKING> for Entity {
297    type Value = Entity;
298    type Access = Box<dyn Iterator<Item = Entity> + 'a>;
299
300    fn does_accept_archetype(_: &Archetype) -> bool {
301        true
302    }
303
304    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
305        Ok(Box::new(archetype.entities().iter()))
306    }
307
308    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
309        access.next()
310    }
311}
312
313impl<'a, const LOCKING: bool> TypedLookupFetch<'a, LOCKING> for Entity {
314    type Value = Entity;
315    type ValueOne = Self::Value;
316    type Access = &'a EntityDenseMap;
317
318    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
319        Some(archetype.entities())
320    }
321
322    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
323        if access.contains(entity) {
324            Some(entity)
325        } else {
326            None
327        }
328    }
329
330    fn fetch_one(_: &World, entity: Entity) -> Option<Self::ValueOne> {
331        Some(entity)
332    }
333}
334
335impl<'a, const LOCKING: bool, T: Component> TypedQueryFetch<'a, LOCKING> for &'a T {
336    type Value = &'a T;
337    type Access = Box<dyn Iterator<Item = &'a T> + 'a>;
338
339    fn does_accept_archetype(archetype: &Archetype) -> bool {
340        archetype.has_type(TypeHash::of::<T>())
341    }
342
343    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
344        Ok(Box::new(archetype.column_read_iter::<LOCKING, T>()?))
345    }
346
347    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
348        access.next()
349    }
350}
351
352impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for &'a T {
353    type Value = &'a T;
354    type ValueOne = ComponentRef<'a, LOCKING, T>;
355    type Access = (&'a EntityDenseMap, ArchetypeColumnAccess<'a, LOCKING, T>);
356
357    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
358        if archetype.has_type(TypeHash::of::<T>()) {
359            Some((
360                archetype.entities(),
361                archetype.column::<LOCKING, T>(false).ok()?,
362            ))
363        } else {
364            None
365        }
366    }
367
368    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
369        if let Some(index) = access.0.index_of(entity) {
370            access
371                .1
372                .read(index)
373                .map(|value| unsafe { std::mem::transmute(value) })
374        } else {
375            None
376        }
377    }
378
379    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
380        world.component::<LOCKING, T>(entity).ok()
381    }
382}
383
384impl<'a, const LOCKING: bool, T: Component> TypedQueryFetch<'a, LOCKING> for &'a mut T {
385    type Value = &'a mut T;
386    type Access = Box<dyn Iterator<Item = &'a mut T> + 'a>;
387
388    fn does_accept_archetype(archetype: &Archetype) -> bool {
389        archetype.has_type(TypeHash::of::<T>())
390    }
391
392    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
393        Ok(Box::new(archetype.column_write_iter::<LOCKING, T>()?))
394    }
395
396    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
397        access.next()
398    }
399
400    fn unique_access(output: &mut HashSet<TypeHash>) {
401        output.insert(TypeHash::of::<T>());
402    }
403}
404
405impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for &'a mut T {
406    type Value = &'a mut T;
407    type ValueOne = ComponentRefMut<'a, LOCKING, T>;
408    type Access = (&'a EntityDenseMap, ArchetypeColumnAccess<'a, LOCKING, T>);
409
410    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
411        if archetype.has_type(TypeHash::of::<T>()) {
412            Some((
413                archetype.entities(),
414                archetype.column::<LOCKING, T>(true).ok()?,
415            ))
416        } else {
417            None
418        }
419    }
420
421    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
422        if let Some(index) = access.0.index_of(entity) {
423            access
424                .1
425                .write(index)
426                .map(|value| unsafe { std::mem::transmute(value) })
427        } else {
428            None
429        }
430    }
431
432    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
433        world.component_mut::<LOCKING, T>(entity).ok()
434    }
435
436    fn unique_access(output: &mut HashSet<TypeHash>) {
437        output.insert(TypeHash::of::<T>());
438    }
439}
440
441impl<'a, const LOCKING: bool, T: Component> TypedQueryFetch<'a, LOCKING> for Option<&'a T> {
442    type Value = Option<&'a T>;
443    type Access = Option<Box<dyn Iterator<Item = &'a T> + 'a>>;
444
445    fn does_accept_archetype(_: &Archetype) -> bool {
446        true
447    }
448
449    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
450        match archetype.column_read_iter::<LOCKING, T>().ok() {
451            Some(value) => Ok(Some(Box::new(value))),
452            None => Ok(None),
453        }
454    }
455
456    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
457        match access {
458            Some(access) => Some(access.next()),
460            None => Some(None),
461        }
462    }
463}
464
465impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Option<&'a T> {
466    type Value = Option<&'a T>;
467    type ValueOne = Option<ComponentRef<'a, LOCKING, T>>;
468    type Access = Option<(&'a EntityDenseMap, ArchetypeColumnAccess<'a, LOCKING, T>)>;
469
470    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
471        match archetype.column::<LOCKING, T>(false).ok() {
472            Some(value) => Some(Some((archetype.entities(), value))),
473            None => Some(None),
474        }
475    }
476
477    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
478        match access {
479            Some(access) => Some(if let Some(index) = access.0.index_of(entity) {
481                access
482                    .1
483                    .read(index)
484                    .map(|value| unsafe { std::mem::transmute(value) })
485            } else {
486                None
487            }),
488            None => Some(None),
489        }
490    }
491
492    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
493        Some(world.component::<LOCKING, T>(entity).ok())
494    }
495}
496
497impl<'a, const LOCKING: bool, T: Component> TypedQueryFetch<'a, LOCKING> for Option<&'a mut T> {
498    type Value = Option<&'a mut T>;
499    type Access = Option<Box<dyn Iterator<Item = &'a mut T> + 'a>>;
500
501    fn does_accept_archetype(_: &Archetype) -> bool {
502        true
503    }
504
505    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
506        match archetype.column_write_iter::<LOCKING, T>().ok() {
507            Some(value) => Ok(Some(Box::new(value))),
508            None => Ok(None),
509        }
510    }
511
512    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
513        match access {
514            Some(access) => Some(access.next()),
516            None => Some(None),
517        }
518    }
519
520    fn unique_access(output: &mut HashSet<TypeHash>) {
521        output.insert(TypeHash::of::<T>());
522    }
523}
524
525impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Option<&'a mut T> {
526    type Value = Option<&'a mut T>;
527    type ValueOne = Option<ComponentRefMut<'a, LOCKING, T>>;
528    type Access = Option<(&'a EntityDenseMap, ArchetypeColumnAccess<'a, LOCKING, T>)>;
529
530    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
531        match archetype.column::<LOCKING, T>(true).ok() {
532            Some(value) => Some(Some((archetype.entities(), value))),
533            None => Some(None),
534        }
535    }
536
537    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
538        match access {
539            Some(access) => Some(if let Some(index) = access.0.index_of(entity) {
541                access
542                    .1
543                    .write(index)
544                    .map(|value| unsafe { std::mem::transmute(value) })
545            } else {
546                None
547            }),
548            None => Some(None),
549        }
550    }
551
552    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
553        Some(world.component_mut::<LOCKING, T>(entity).ok())
554    }
555
556    fn unique_access(output: &mut HashSet<TypeHash>) {
557        output.insert(TypeHash::of::<T>());
558    }
559}
560
561pub struct Satisfy<T>(PhantomData<fn() -> T>);
562
563impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> TypedQueryFetch<'a, LOCKING>
564    for Satisfy<Fetch>
565{
566    type Value = ();
567    type Access = ();
568
569    fn does_accept_archetype(archetype: &Archetype) -> bool {
570        Fetch::does_accept_archetype(archetype)
571    }
572
573    fn access(_: &'_ Archetype) -> Result<Self::Access, QueryError> {
574        Ok(())
575    }
576
577    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
578        Some(())
579    }
580}
581
582impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedLookupFetch<'a, LOCKING>
583    for Satisfy<Fetch>
584{
585    type Value = ();
586    type ValueOne = ();
587    type Access = &'a EntityDenseMap;
588
589    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
590        if Fetch::try_access(archetype).is_some() {
591            Some(archetype.entities())
592        } else {
593            None
594        }
595    }
596
597    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
598        if access.contains(entity) {
599            Some(())
600        } else {
601            None
602        }
603    }
604
605    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
606        if Fetch::fetch_one(world, entity).is_some() {
607            Some(())
608        } else {
609            None
610        }
611    }
612}
613
614pub struct DoesNotSatisfy<T>(PhantomData<fn() -> T>);
615
616impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> TypedQueryFetch<'a, LOCKING>
617    for DoesNotSatisfy<Fetch>
618{
619    type Value = ();
620    type Access = ();
621
622    fn does_accept_archetype(archetype: &Archetype) -> bool {
623        !Fetch::does_accept_archetype(archetype)
624    }
625
626    fn access(_: &'_ Archetype) -> Result<Self::Access, QueryError> {
627        Ok(())
628    }
629
630    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
631        Some(())
632    }
633}
634
635impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedLookupFetch<'a, LOCKING>
636    for DoesNotSatisfy<Fetch>
637{
638    type Value = ();
639    type ValueOne = ();
640    type Access = &'a EntityDenseMap;
641
642    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
643        if Fetch::try_access(archetype).is_none() {
644            Some(archetype.entities())
645        } else {
646            None
647        }
648    }
649
650    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
651        if access.contains(entity) {
652            Some(())
653        } else {
654            None
655        }
656    }
657
658    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
659        if Fetch::fetch_one(world, entity).is_none() {
660            Some(())
661        } else {
662            None
663        }
664    }
665}
666
667pub struct Include<T: Component>(PhantomData<fn() -> T>);
668
669impl<const LOCKING: bool, T: Component> TypedQueryFetch<'_, LOCKING> for Include<T> {
670    type Value = ();
671    type Access = ();
672
673    fn does_accept_archetype(archetype: &Archetype) -> bool {
674        archetype.has_type(TypeHash::of::<T>())
675    }
676
677    fn access(_: &Archetype) -> Result<Self::Access, QueryError> {
678        Ok(())
679    }
680
681    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
682        Some(())
683    }
684}
685
686impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Include<T> {
687    type Value = ();
688    type ValueOne = ();
689    type Access = &'a EntityDenseMap;
690
691    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
692        if archetype.has_type(TypeHash::of::<T>()) {
693            Some(archetype.entities())
694        } else {
695            None
696        }
697    }
698
699    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
700        if access.contains(entity) {
701            Some(())
702        } else {
703            None
704        }
705    }
706
707    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
708        if world.has_entity_component::<T>(entity) {
709            Some(())
710        } else {
711            None
712        }
713    }
714}
715
716pub struct Exclude<T: Component>(PhantomData<fn() -> T>);
717
718impl<const LOCKING: bool, T: Component> TypedQueryFetch<'_, LOCKING> for Exclude<T> {
719    type Value = ();
720    type Access = ();
721
722    fn does_accept_archetype(archetype: &Archetype) -> bool {
723        !archetype.has_type(TypeHash::of::<T>())
724    }
725
726    fn access(_: &Archetype) -> Result<Self::Access, QueryError> {
727        Ok(())
728    }
729
730    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
731        Some(())
732    }
733}
734
735impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Exclude<T> {
736    type Value = ();
737    type ValueOne = ();
738    type Access = &'a EntityDenseMap;
739
740    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
741        if !archetype.has_type(TypeHash::of::<T>()) {
742            Some(archetype.entities())
743        } else {
744            None
745        }
746    }
747
748    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
749        if access.contains(entity) {
750            Some(())
751        } else {
752            None
753        }
754    }
755
756    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
757        if !world.has_entity_component::<T>(entity) {
758            Some(())
759        } else {
760            None
761        }
762    }
763}
764
765pub struct Update<T: Component>(PhantomData<fn() -> T>);
766
767pub struct UpdatedAccess<'a, T>(Entity, &'a mut T);
768
769impl<'a, T> UpdatedAccess<'a, T> {
770    pub fn entity(&self) -> Entity {
771        self.0
772    }
773
774    pub fn read(&'a self) -> &'a T {
775        self.1
776    }
777
778    pub fn write(&'a mut self) -> &'a mut T {
779        self.1
780    }
781
782    pub fn notify(&self, world: &World) {
783        world.update::<T>(self.0);
784    }
785
786    pub fn write_notified(&'a mut self, world: &World) -> &'a mut T {
787        self.notify(world);
788        self.write()
789    }
790}
791
792pub struct UpdatedAccessComponent<'a, const LOCKING: bool, T: Component>(
793    Entity,
794    ComponentRefMut<'a, LOCKING, T>,
795);
796
797impl<'a, const LOCKING: bool, T: Component> UpdatedAccessComponent<'a, LOCKING, T> {
798    pub fn entity(&self) -> Entity {
799        self.0
800    }
801
802    pub fn read(&'a self) -> &'a T {
803        &self.1
804    }
805
806    pub fn write(&'a mut self) -> &'a mut T {
807        &mut self.1
808    }
809
810    pub fn notify(&self, world: &World) {
811        world.update::<T>(self.0);
812    }
813
814    pub fn write_notified(&'a mut self, world: &World) -> &'a mut T {
815        self.notify(world);
816        self.write()
817    }
818}
819
820impl<'a, const LOCKING: bool, T: Component> TypedQueryFetch<'a, LOCKING> for Update<T> {
821    type Value = UpdatedAccess<'a, T>;
822    type Access = Box<dyn Iterator<Item = (Entity, &'a mut T)> + 'a>;
823
824    fn does_accept_archetype(archetype: &Archetype) -> bool {
825        archetype.has_type(TypeHash::of::<T>())
826    }
827
828    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
829        Ok(Box::new(
830            archetype
831                .entities()
832                .iter()
833                .zip(archetype.column_write_iter::<LOCKING, T>()?),
834        ))
835    }
836
837    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
838        access
839            .next()
840            .map(|(entity, data)| UpdatedAccess(entity, data))
841    }
842
843    fn unique_access(output: &mut HashSet<TypeHash>) {
844        output.insert(TypeHash::of::<T>());
845    }
846}
847
848impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Update<T> {
849    type Value = UpdatedAccess<'a, T>;
850    type ValueOne = UpdatedAccessComponent<'a, LOCKING, T>;
851    type Access = (&'a EntityDenseMap, ArchetypeColumnAccess<'a, LOCKING, T>);
852
853    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
854        if archetype.has_type(TypeHash::of::<T>()) {
855            Some((
856                archetype.entities(),
857                archetype.column::<LOCKING, T>(true).ok()?,
858            ))
859        } else {
860            None
861        }
862    }
863
864    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
865        if let Some(index) = access.0.index_of(entity) {
866            access
867                .1
868                .write(index)
869                .map(|value| unsafe { std::mem::transmute(value) })
870                .map(|data| UpdatedAccess(entity, data))
871        } else {
872            None
873        }
874    }
875
876    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
877        world
878            .component_mut::<LOCKING, T>(entity)
879            .ok()
880            .map(|data| UpdatedAccessComponent(entity, data))
881    }
882
883    fn unique_access(output: &mut HashSet<TypeHash>) {
884        output.insert(TypeHash::of::<T>());
885    }
886}
887
888impl<'a> TypedRelationLookupFetch<'a> for () {
889    type Value = ();
890    type Access = ();
891
892    fn access(_: &'a World, _: Entity) -> Self::Access {}
893
894    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
895        Some(())
896    }
897}
898
899impl<'a> TypedRelationLookupFetch<'a> for Entity {
900    type Value = Entity;
901    type Access = Option<Entity>;
902
903    fn access(_: &'a World, entity: Entity) -> Self::Access {
904        Some(entity)
905    }
906
907    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
908        access.take()
909    }
910}
911
912impl<'a, const LOCKING: bool, Fetch> TypedRelationLookupFetch<'a> for Lookup<'a, LOCKING, Fetch>
913where
914    Fetch: TypedLookupFetch<'a, LOCKING>,
915{
916    type Value = Fetch::ValueOne;
917    type Access = Option<Fetch::ValueOne>;
918
919    fn access(world: &'a World, entity: Entity) -> Self::Access {
920        world.lookup_one::<LOCKING, Fetch>(entity)
921    }
922
923    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
924        access.take()
925    }
926}
927
928pub struct Related<'a, const LOCKING: bool, T, Transform>(PhantomData<fn() -> &'a (T, Transform)>)
929where
930    T: Component,
931    Transform: TypedRelationLookupTransform<'a, Input = Entity>;
932
933impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
934    for Related<'a, LOCKING, T, Transform>
935where
936    T: Component,
937    Transform: TypedRelationLookupTransform<'a, Input = Entity>,
938{
939    type Value = Transform::Output;
940    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
941
942    fn access(world: &'a World, entity: Entity) -> Self::Access {
943        Box::new(
944            world
945                .relations_outgoing::<LOCKING, T>(entity)
946                .flat_map(|(_, _, entity)| Transform::transform(world, entity)),
947        )
948    }
949
950    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
951        access.next()
952    }
953}
954
955pub struct RelatedPair<'a, const LOCKING: bool, T, Transform>(
956    PhantomData<fn() -> &'a (T, Transform)>,
957)
958where
959    T: Component,
960    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>;
961
962impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
963    for RelatedPair<'a, LOCKING, T, Transform>
964where
965    T: Component,
966    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>,
967{
968    type Value = Transform::Output;
969    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
970
971    fn access(world: &'a World, entity: Entity) -> Self::Access {
972        Box::new(
973            world
974                .relations_outgoing::<LOCKING, T>(entity)
975                .flat_map(|(from, _, to)| Transform::transform(world, (from, to))),
976        )
977    }
978
979    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
980        access.next()
981    }
982}
983
984pub struct Traverse<'a, const LOCKING: bool, T, Transform>(PhantomData<fn() -> &'a (T, Transform)>)
985where
986    T: Component,
987    Transform: TypedRelationLookupTransform<'a, Input = Entity>;
988
989impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
990    for Traverse<'a, LOCKING, T, Transform>
991where
992    T: Component,
993    Transform: TypedRelationLookupTransform<'a, Input = Entity>,
994{
995    type Value = Transform::Output;
996    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
997
998    fn access(world: &'a World, entity: Entity) -> Self::Access {
999        Box::new(
1000            world
1001                .traverse_outgoing::<LOCKING, T>([entity])
1002                .flat_map(|(_, to)| Transform::transform(world, to)),
1003        )
1004    }
1005
1006    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
1007        access.next()
1008    }
1009}
1010
1011pub struct TraversePair<'a, const LOCKING: bool, T, Transform>(
1012    PhantomData<fn() -> &'a (T, Transform)>,
1013)
1014where
1015    T: Component,
1016    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>;
1017
1018impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
1019    for TraversePair<'a, LOCKING, T, Transform>
1020where
1021    T: Component,
1022    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>,
1023{
1024    type Value = Transform::Output;
1025    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
1026
1027    fn access(world: &'a World, entity: Entity) -> Self::Access {
1028        Box::new(
1029            world
1030                .traverse_outgoing::<LOCKING, T>([entity])
1031                .flat_map(|(from, to)| Transform::transform(world, (from, to))),
1032        )
1033    }
1034
1035    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
1036        access.next()
1037    }
1038}
1039
1040pub struct Join<'a, A, B>(PhantomData<fn() -> &'a (A, B)>)
1041where
1042    A: TypedRelationLookupFetch<'a>,
1043    B: TypedRelationLookupFetch<'a>;
1044
1045impl<'a, A, B> TypedRelationLookupFetch<'a> for Join<'a, A, B>
1046where
1047    A: TypedRelationLookupFetch<'a>,
1048    B: TypedRelationLookupFetch<'a>,
1049{
1050    type Value = (Arc<A::Value>, B::Value);
1051    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
1052
1053    fn access(world: &'a World, entity: Entity) -> Self::Access {
1054        Box::new(
1055            TypedRelationLookupIter::<A>::access(A::access(world, entity)).flat_map(move |a| {
1056                let a = Arc::new(a);
1057                TypedRelationLookupIter::<B>::access(B::access(world, entity))
1058                    .map(move |b| (a.clone(), b))
1059            }),
1060        )
1061    }
1062
1063    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
1064        access.next()
1065    }
1066}
1067
1068impl<'a> TypedRelationLookupTransform<'a> for Entity {
1069    type Input = Entity;
1070    type Output = Entity;
1071
1072    fn transform(_: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1073        std::iter::once(input)
1074    }
1075}
1076
1077pub struct Is<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>(
1078    PhantomData<fn() -> &'a Fetch>,
1079);
1080
1081impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedRelationLookupTransform<'a>
1082    for Is<'a, LOCKING, Fetch>
1083{
1084    type Input = Entity;
1085    type Output = Entity;
1086
1087    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1088        world
1089            .lookup_one::<LOCKING, Fetch>(input)
1090            .is_some()
1091            .then_some(input)
1092            .into_iter()
1093    }
1094}
1095
1096pub struct IsNot<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>(
1097    PhantomData<fn() -> &'a Fetch>,
1098);
1099
1100impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedRelationLookupTransform<'a>
1101    for IsNot<'a, LOCKING, Fetch>
1102{
1103    type Input = Entity;
1104    type Output = Entity;
1105
1106    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1107        world
1108            .lookup_one::<LOCKING, Fetch>(input)
1109            .is_none()
1110            .then_some(input)
1111            .into_iter()
1112    }
1113}
1114
1115impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedRelationLookupTransform<'a>
1116    for Lookup<'a, LOCKING, Fetch>
1117{
1118    type Input = Entity;
1119    type Output = Fetch::ValueOne;
1120
1121    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1122        world.lookup_one::<LOCKING, Fetch>(input).into_iter()
1123    }
1124}
1125
1126pub struct Limit<'a, const COUNT: usize, Transform: TypedRelationLookupTransform<'a>>(
1127    PhantomData<fn() -> &'a Transform>,
1128);
1129
1130impl<'a, const COUNT: usize, Transform: TypedRelationLookupTransform<'a>>
1131    TypedRelationLookupTransform<'a> for Limit<'a, COUNT, Transform>
1132{
1133    type Input = Transform::Input;
1134    type Output = Transform::Output;
1135
1136    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1137        Transform::transform(world, input).take(COUNT)
1138    }
1139}
1140
1141pub type Single<'a, Transform> = Limit<'a, 1, Transform>;
1142
1143pub struct SelectEntity<const INDEX: usize>;
1144
1145impl<'a, const INDEX: usize> TypedRelationLookupTransform<'a> for SelectEntity<INDEX> {
1146    type Input = (Entity, Entity);
1147    type Output = Entity;
1148
1149    fn transform(_: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1150        if INDEX == 0 {
1151            std::iter::once(input.0)
1152        } else {
1153            std::iter::once(input.1)
1154        }
1155    }
1156}
1157
1158pub struct Follow<'a, const LOCKING: bool, Transform, Fetch>(
1159    PhantomData<fn() -> &'a (Transform, Fetch)>,
1160)
1161where
1162    Transform: TypedRelationLookupTransform<'a, Input = Entity, Output = Entity>,
1163    Fetch: TypedRelationLookupFetch<'a>;
1164
1165impl<'a, const LOCKING: bool, Transform, Fetch> TypedRelationLookupTransform<'a>
1166    for Follow<'a, LOCKING, Transform, Fetch>
1167where
1168    Transform: TypedRelationLookupTransform<'a, Input = Entity, Output = Entity>,
1169    Fetch: TypedRelationLookupFetch<'a>,
1170{
1171    type Input = Entity;
1172    type Output = Fetch::Value;
1173
1174    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1175        Transform::transform(world, input)
1176            .flat_map(|entity| world.relation_lookup::<LOCKING, Fetch>(entity))
1177    }
1178}
1179
1180macro_rules! impl_typed_query_fetch_tuple {
1181    ($($type:ident),+) => {
1182        impl<'a, const LOCKING: bool, $($type: TypedQueryFetch<'a, LOCKING>),+> TypedQueryFetch<'a, LOCKING> for ($($type,)+) {
1183            type Value = ($($type::Value,)+);
1184            type Access = ($($type::Access,)+);
1185
1186            fn does_accept_archetype(archetype: &Archetype) -> bool {
1187                $($type::does_accept_archetype(archetype))&&+
1188            }
1189
1190            fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
1191                Ok(($($type::access(archetype)?,)+))
1192            }
1193
1194            fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
1195                #[allow(non_snake_case)]
1196                let ($($type,)+) = access;
1197                Some(($($type::fetch($type)?,)+))
1198            }
1199
1200            fn unique_access(output: &mut HashSet<TypeHash>) {
1201                $(
1202                    $type::unique_access(output);
1203                )+
1204            }
1205        }
1206    };
1207}
1208
1209impl_typed_query_fetch_tuple!(A);
1210impl_typed_query_fetch_tuple!(A, B);
1211impl_typed_query_fetch_tuple!(A, B, C);
1212impl_typed_query_fetch_tuple!(A, B, C, D);
1213impl_typed_query_fetch_tuple!(A, B, C, D, E);
1214impl_typed_query_fetch_tuple!(A, B, C, D, E, F);
1215impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G);
1216impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H);
1217impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I);
1218impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J);
1219impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K);
1220impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
1221impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
1222impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1223impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1224impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
1225
1226macro_rules! impl_typed_lookup_fetch_tuple {
1227    ($($type:ident),+) => {
1228        impl<'a, const LOCKING: bool, $($type: TypedLookupFetch<'a, LOCKING>),+> TypedLookupFetch<'a, LOCKING> for ($($type,)+) {
1229            type Value = ($($type::Value,)+);
1230            type ValueOne = ($($type::ValueOne,)+);
1231            type Access = ($($type::Access,)+);
1232
1233            fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
1234                Some(($($type::try_access(archetype)?,)+))
1235            }
1236
1237            fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
1238                #[allow(non_snake_case)]
1239                let ($($type,)+) = access;
1240                Some(($($type::fetch($type, entity)?,)+))
1241            }
1242
1243            fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
1244                Some(($($type::fetch_one(world, entity)?,)+))
1245            }
1246
1247            fn unique_access(output: &mut HashSet<TypeHash>) {
1248                $(
1249                    $type::unique_access(output);
1250                )+
1251            }
1252        }
1253    };
1254}
1255
1256impl_typed_lookup_fetch_tuple!(A);
1257impl_typed_lookup_fetch_tuple!(A, B);
1258impl_typed_lookup_fetch_tuple!(A, B, C);
1259impl_typed_lookup_fetch_tuple!(A, B, C, D);
1260impl_typed_lookup_fetch_tuple!(A, B, C, D, E);
1261impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F);
1262impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G);
1263impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H);
1264impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I);
1265impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J);
1266impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K);
1267impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
1268impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
1269impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1270impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1271impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
1272
1273macro_rules! impl_typed_relation_fetch_tuple {
1274    ($($type:ident),+) => {
1275        impl<'a, $($type: TypedRelationLookupFetch<'a>),+> TypedRelationLookupFetch<'a> for ($($type,)+) {
1276            type Value = ($($type::Value,)+);
1277            type Access = ($($type::Access,)+);
1278
1279            fn access(world: &'a World, entity: Entity) -> Self::Access {
1280                ($($type::access(world, entity),)+)
1281            }
1282
1283            fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
1284                #[allow(non_snake_case)]
1285                let ($($type,)+) = access;
1286                Some(($($type::fetch($type)?,)+))
1287            }
1288        }
1289    };
1290}
1291
1292impl_typed_relation_fetch_tuple!(A);
1293impl_typed_relation_fetch_tuple!(A, B);
1294impl_typed_relation_fetch_tuple!(A, B, C);
1295impl_typed_relation_fetch_tuple!(A, B, C, D);
1296impl_typed_relation_fetch_tuple!(A, B, C, D, E);
1297impl_typed_relation_fetch_tuple!(A, B, C, D, E, F);
1298impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G);
1299impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H);
1300impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I);
1301impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J);
1302impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K);
1303impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
1304impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
1305impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O);
1306impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O, P);
1307
1308pub struct TypedQueryIter<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> {
1309    archetypes: Vec<&'a Archetype>,
1310    index: usize,
1311    access: Option<Fetch::Access>,
1312    _phantom: PhantomData<fn() -> Fetch>,
1313}
1314
1315impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>>
1316    TypedQueryIter<'a, LOCKING, Fetch>
1317{
1318    pub fn new(world: &'a World) -> Self {
1319        Self {
1320            archetypes: world
1321                .archetypes()
1322                .filter(|archetype| Fetch::does_accept_archetype(archetype))
1323                .collect(),
1324            index: 0,
1325            access: None,
1326            _phantom: PhantomData,
1327        }
1328    }
1329
1330    pub fn new_view(view: &'a WorldView) -> Self {
1331        Self {
1332            archetypes: view
1333                .archetypes()
1334                .filter(|archetype| Fetch::does_accept_archetype(archetype))
1335                .collect(),
1336            index: 0,
1337            access: None,
1338            _phantom: PhantomData,
1339        }
1340    }
1341}
1342
1343impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Iterator
1344    for TypedQueryIter<'a, LOCKING, Fetch>
1345{
1346    type Item = Fetch::Value;
1347
1348    fn next(&mut self) -> Option<Self::Item> {
1349        while self.index < self.archetypes.len() {
1350            match self.access.as_mut() {
1351                Some(access) => {
1352                    let item = Fetch::fetch(access);
1353                    if item.is_none() {
1354                        self.access = None;
1355                        self.index += 1;
1356                        continue;
1357                    }
1358                    return item;
1359                }
1360                None => {
1361                    if let Some(archetype) = self.archetypes.get(self.index) {
1362                        self.access = Some(Fetch::access(archetype).unwrap());
1363                    } else {
1364                        self.index += 1;
1365                    }
1366                    continue;
1367                }
1368            }
1369        }
1370        None
1371    }
1372}
1373
1374pub struct TypedLookupIter<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> {
1375    access: Vec<Fetch::Access>,
1376    entities: Box<dyn Iterator<Item = Entity> + 'a>,
1377    _phantom: PhantomData<fn() -> Fetch>,
1378}
1379
1380impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>
1381    TypedLookupIter<'a, LOCKING, Fetch>
1382{
1383    pub fn new(world: &'a World, entities: impl IntoIterator<Item = Entity> + 'a) -> Self {
1384        Self {
1385            access: world
1386                .archetypes()
1387                .filter_map(|archetype| Fetch::try_access(archetype))
1388                .collect(),
1389            entities: Box::new(entities.into_iter()),
1390            _phantom: PhantomData,
1391        }
1392    }
1393
1394    pub fn new_view(view: &'a WorldView, entities: impl IntoIterator<Item = Entity> + 'a) -> Self {
1395        Self {
1396            access: view
1397                .archetypes()
1398                .filter_map(|archetype| Fetch::try_access(archetype))
1399                .collect(),
1400            entities: Box::new(entities.into_iter()),
1401            _phantom: PhantomData,
1402        }
1403    }
1404}
1405
1406impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> Iterator
1407    for TypedLookupIter<'a, LOCKING, Fetch>
1408{
1409    type Item = Fetch::Value;
1410
1411    fn next(&mut self) -> Option<Self::Item> {
1412        let entity = self.entities.next()?;
1413        for access in &mut self.access {
1414            if let Some(result) = Fetch::fetch(access, entity) {
1415                return Some(result);
1416            }
1417        }
1418        None
1419    }
1420}
1421
1422pub struct TypedLookupAccess<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> {
1423    access: Vec<Fetch::Access>,
1424    _phantom: PhantomData<fn() -> Fetch>,
1425}
1426
1427impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>
1428    TypedLookupAccess<'a, LOCKING, Fetch>
1429{
1430    pub fn new(world: &'a World) -> Self {
1431        Self {
1432            access: world
1433                .archetypes()
1434                .filter_map(|archetype| Fetch::try_access(archetype))
1435                .collect(),
1436            _phantom: PhantomData,
1437        }
1438    }
1439
1440    pub fn new_view(view: &'a WorldView) -> Self {
1441        Self {
1442            access: view
1443                .archetypes()
1444                .filter_map(|archetype| Fetch::try_access(archetype))
1445                .collect(),
1446            _phantom: PhantomData,
1447        }
1448    }
1449
1450    pub fn access(&mut self, entity: Entity) -> Option<Fetch::Value> {
1451        for access in &mut self.access {
1452            if let Some(result) = Fetch::fetch(access, entity) {
1453                return Some(result);
1454            }
1455        }
1456        None
1457    }
1458}
1459
1460pub struct TypedRelationLookupIter<'a, Fetch: TypedRelationLookupFetch<'a>> {
1461    access: Fetch::Access,
1462}
1463
1464impl<'a, Fetch: TypedRelationLookupFetch<'a>> TypedRelationLookupIter<'a, Fetch> {
1465    pub fn new(world: &'a World, entity: Entity) -> Self {
1466        Self {
1467            access: Fetch::access(world, entity),
1468        }
1469    }
1470
1471    pub fn access(access: Fetch::Access) -> Self {
1472        Self { access }
1473    }
1474}
1475
1476impl<'a, Fetch: TypedRelationLookupFetch<'a>> Iterator for TypedRelationLookupIter<'a, Fetch> {
1477    type Item = Fetch::Value;
1478
1479    fn next(&mut self) -> Option<Self::Item> {
1480        Fetch::fetch(&mut self.access)
1481    }
1482}
1483
1484#[derive(Debug)]
1485enum DynamicQueryFilterMode {
1486    Read,
1487    Write,
1488    Include,
1489    Exclude,
1490}
1491
1492#[derive(Debug, Default)]
1493pub struct DynamicQueryFilter {
1494    filter: HashMap<TypeHash, DynamicQueryFilterMode>,
1495}
1496
1497impl DynamicQueryFilter {
1498    pub fn from_raw(
1499        read: &[TypeHash],
1500        write: &[TypeHash],
1501        include: &[TypeHash],
1502        exclude: &[TypeHash],
1503    ) -> Self {
1504        Self {
1505            filter: read
1506                .iter()
1507                .copied()
1508                .map(|type_hash| (type_hash, DynamicQueryFilterMode::Read))
1509                .chain(
1510                    write
1511                        .iter()
1512                        .copied()
1513                        .map(|type_hash| (type_hash, DynamicQueryFilterMode::Write)),
1514                )
1515                .chain(
1516                    include
1517                        .iter()
1518                        .copied()
1519                        .map(|type_hash| (type_hash, DynamicQueryFilterMode::Include)),
1520                )
1521                .chain(
1522                    exclude
1523                        .iter()
1524                        .copied()
1525                        .map(|type_hash| (type_hash, DynamicQueryFilterMode::Exclude)),
1526                )
1527                .collect(),
1528        }
1529    }
1530
1531    pub fn read<T>(self) -> Self {
1532        self.read_raw(TypeHash::of::<T>())
1533    }
1534
1535    pub fn read_raw(mut self, type_hash: TypeHash) -> Self {
1536        self.filter.insert(type_hash, DynamicQueryFilterMode::Read);
1537        self
1538    }
1539
1540    pub fn write<T>(self) -> Self {
1541        self.write_raw(TypeHash::of::<T>())
1542    }
1543
1544    pub fn write_raw(mut self, type_hash: TypeHash) -> Self {
1545        self.filter.insert(type_hash, DynamicQueryFilterMode::Write);
1546        self
1547    }
1548
1549    pub fn include<T>(self) -> Self {
1550        self.include_raw(TypeHash::of::<T>())
1551    }
1552
1553    pub fn include_raw(mut self, type_hash: TypeHash) -> Self {
1554        self.filter
1555            .insert(type_hash, DynamicQueryFilterMode::Include);
1556        self
1557    }
1558
1559    pub fn exclude<T>(self) -> Self {
1560        self.exclude_raw(TypeHash::of::<T>())
1561    }
1562
1563    pub fn exclude_raw(mut self, type_hash: TypeHash) -> Self {
1564        self.filter
1565            .insert(type_hash, DynamicQueryFilterMode::Exclude);
1566        self
1567    }
1568
1569    pub fn does_accept_archetype(&self, archetype: &Archetype) -> bool {
1570        self.filter.iter().all(|(type_hash, mode)| match mode {
1571            DynamicQueryFilterMode::Read
1572            | DynamicQueryFilterMode::Write
1573            | DynamicQueryFilterMode::Include => archetype.has_type(*type_hash),
1574            DynamicQueryFilterMode::Exclude => !archetype.has_type(*type_hash),
1575        })
1576    }
1577
1578    fn columns(&self) -> Vec<(TypeHash, bool)> {
1579        self.columns_iter().collect()
1580    }
1581
1582    fn columns_iter(&self) -> impl Iterator<Item = (TypeHash, bool)> + '_ {
1583        self.filter
1584            .iter()
1585            .filter_map(|(type_hash, mode)| match mode {
1586                DynamicQueryFilterMode::Read => Some((*type_hash, false)),
1587                DynamicQueryFilterMode::Write => Some((*type_hash, true)),
1588                _ => None,
1589            })
1590    }
1591
1592    pub fn unique_access(&self, output: &mut HashSet<TypeHash>) {
1593        for (type_hash, filter) in &self.filter {
1594            if matches!(filter, DynamicQueryFilterMode::Write) {
1595                output.insert(*type_hash);
1596            }
1597        }
1598    }
1599
1600    pub fn query<'a, const LOCKING: bool>(
1601        &self,
1602        world: &'a World,
1603    ) -> DynamicQueryIter<'a, LOCKING> {
1604        world.dynamic_query::<LOCKING>(self)
1605    }
1606
1607    pub fn lookup<'a, const LOCKING: bool>(
1608        &self,
1609        world: &'a World,
1610        entities: impl IntoIterator<Item = Entity> + 'a,
1611    ) -> DynamicLookupIter<'a, LOCKING> {
1612        world.dynamic_lookup::<LOCKING>(self, entities)
1613    }
1614
1615    pub fn lookup_access<'a, const LOCKING: bool>(
1616        &self,
1617        world: &'a World,
1618    ) -> DynamicLookupAccess<'a, LOCKING> {
1619        world.dynamic_lookup_access::<LOCKING>(self)
1620    }
1621}
1622
1623pub struct DynamicQueryItem<'a> {
1624    entity: Entity,
1625    columns: Vec<ArchetypeDynamicColumnItem<'a>>,
1626}
1627
1628impl<'a> DynamicQueryItem<'a> {
1629    pub fn entity(&self) -> Entity {
1630        self.entity
1631    }
1632
1633    pub fn read<T>(&self) -> Result<&ArchetypeDynamicColumnItem<'a>, QueryError> {
1634        self.read_raw(TypeHash::of::<T>())
1635    }
1636
1637    pub fn read_raw(
1638        &self,
1639        type_hash: TypeHash,
1640    ) -> Result<&ArchetypeDynamicColumnItem<'a>, QueryError> {
1641        self.columns
1642            .iter()
1643            .find(|column| column.type_hash() == type_hash)
1644            .ok_or(QueryError::TryingToReadUnavailableType { type_hash })
1645    }
1646
1647    pub fn write<T>(&mut self) -> Result<&mut ArchetypeDynamicColumnItem<'a>, QueryError> {
1648        self.write_raw(TypeHash::of::<T>())
1649    }
1650
1651    pub fn write_raw(
1652        &mut self,
1653        type_hash: TypeHash,
1654    ) -> Result<&mut ArchetypeDynamicColumnItem<'a>, QueryError> {
1655        self.columns
1656            .iter_mut()
1657            .find(|column| column.type_hash() == type_hash)
1658            .ok_or(QueryError::TryingToWriteUnavailableType { type_hash })
1659    }
1660}
1661
1662pub struct DynamicQueryIter<'a, const LOCKING: bool> {
1663    columns: Vec<(TypeHash, bool)>,
1665    archetypes: Vec<&'a Archetype>,
1666    index: usize,
1667    access: Option<(
1668        Box<dyn Iterator<Item = Entity> + 'a>,
1669        Vec<ArchetypeDynamicColumnIter<'a, LOCKING>>,
1670    )>,
1671}
1672
1673impl<'a, const LOCKING: bool> DynamicQueryIter<'a, LOCKING> {
1674    pub fn new(filter: &DynamicQueryFilter, world: &'a World) -> Self {
1675        Self {
1676            columns: filter.columns(),
1677            archetypes: world
1678                .archetypes()
1679                .filter(|archetype| filter.does_accept_archetype(archetype))
1680                .collect(),
1681            index: 0,
1682            access: None,
1683        }
1684    }
1685
1686    pub fn new_view(filter: &DynamicQueryFilter, view: &'a WorldView) -> Self {
1687        Self {
1688            columns: filter.columns(),
1689            archetypes: view
1690                .archetypes()
1691                .filter(|archetype| filter.does_accept_archetype(archetype))
1692                .collect(),
1693            index: 0,
1694            access: None,
1695        }
1696    }
1697}
1698
1699impl<'a, const LOCKING: bool> Iterator for DynamicQueryIter<'a, LOCKING> {
1700    type Item = DynamicQueryItem<'a>;
1701
1702    fn next(&mut self) -> Option<Self::Item> {
1703        while self.index < self.archetypes.len() {
1704            match self.access.as_mut() {
1705                Some((entities, columns)) => {
1706                    let entity = entities.next();
1707                    match columns
1708                        .iter_mut()
1709                        .map(|access| access.next())
1710                        .collect::<Option<_>>()
1711                        .and_then(|columns| Some((entity?, columns)))
1712                    {
1713                        Some((entity, columns)) => {
1714                            return Some(DynamicQueryItem { entity, columns });
1715                        }
1716                        None => {
1717                            self.access = None;
1718                            self.index += 1;
1719                            continue;
1720                        }
1721                    }
1722                }
1723                None => {
1724                    if let Some(archetype) = self.archetypes.get(self.index) {
1725                        self.access = Some((
1726                            Box::new(archetype.entities().iter()),
1727                            self.columns
1728                                .iter()
1729                                .copied()
1730                                .map(|(type_hash, unique)| {
1731                                    archetype.dynamic_column_iter(type_hash, unique).unwrap()
1732                                })
1733                                .collect(),
1734                        ));
1735                    } else {
1736                        self.index += 1;
1737                    }
1738                    continue;
1739                }
1740            }
1741        }
1742        None
1743    }
1744}
1745
1746pub struct DynamicLookupIter<'a, const LOCKING: bool> {
1747    columns: Vec<(TypeHash, bool)>,
1749    access: Vec<(
1750        &'a EntityDenseMap,
1751        ArchetypeDynamicColumnAccess<'a, LOCKING>,
1752    )>,
1753    entities: Box<dyn Iterator<Item = Entity> + 'a>,
1754}
1755
1756impl<'a, const LOCKING: bool> DynamicLookupIter<'a, LOCKING> {
1757    pub fn new(
1758        filter: &DynamicQueryFilter,
1759        world: &'a World,
1760        entities: impl IntoIterator<Item = Entity> + 'a,
1761    ) -> Self {
1762        Self {
1763            columns: filter.columns(),
1764            access: world
1765                .archetypes()
1766                .filter(|archetype| filter.does_accept_archetype(archetype))
1767                .flat_map(|archetype| {
1768                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1769                        Some((
1770                            archetype.entities(),
1771                            archetype.dynamic_column(type_hash, unique).ok()?,
1772                        ))
1773                    })
1774                })
1775                .collect(),
1776            entities: Box::new(entities.into_iter()),
1777        }
1778    }
1779
1780    pub fn new_view(
1781        filter: &DynamicQueryFilter,
1782        view: &'a WorldView,
1783        entities: impl IntoIterator<Item = Entity> + 'a,
1784    ) -> Self {
1785        Self {
1786            columns: filter.columns(),
1787            access: view
1788                .archetypes()
1789                .filter(|archetype| filter.does_accept_archetype(archetype))
1790                .flat_map(|archetype| {
1791                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1792                        Some((
1793                            archetype.entities(),
1794                            archetype.dynamic_column(type_hash, unique).ok()?,
1795                        ))
1796                    })
1797                })
1798                .collect(),
1799            entities: Box::new(entities.into_iter()),
1800        }
1801    }
1802}
1803
1804impl<'a, const LOCKING: bool> Iterator for DynamicLookupIter<'a, LOCKING> {
1805    type Item = DynamicQueryItem<'a>;
1806
1807    fn next(&mut self) -> Option<Self::Item> {
1808        let entity = self.entities.next()?;
1809        let columns = self
1810            .columns
1811            .iter()
1812            .map(|(type_hash, unique)| {
1813                self.access
1814                    .iter()
1815                    .find(|(map, access)| {
1816                        map.contains(entity)
1817                            && access.info().type_hash() == *type_hash
1818                            && access.is_unique() == *unique
1819                    })
1820                    .and_then(|(map, access)| unsafe {
1821                        std::mem::transmute(access.dynamic_item(map.index_of(entity).unwrap()).ok())
1822                    })
1823            })
1824            .collect::<Option<Vec<_>>>()?;
1825        Some(DynamicQueryItem { entity, columns })
1826    }
1827}
1828
1829pub struct DynamicLookupAccess<'a, const LOCKING: bool> {
1830    columns: Vec<(TypeHash, bool)>,
1832    access: Vec<(
1833        &'a EntityDenseMap,
1834        ArchetypeDynamicColumnAccess<'a, LOCKING>,
1835    )>,
1836}
1837
1838impl<'a, const LOCKING: bool> DynamicLookupAccess<'a, LOCKING> {
1839    pub fn new(filter: &DynamicQueryFilter, world: &'a World) -> Self {
1840        Self {
1841            columns: filter.columns(),
1842            access: world
1843                .archetypes()
1844                .filter(|archetype| filter.does_accept_archetype(archetype))
1845                .flat_map(|archetype| {
1846                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1847                        Some((
1848                            archetype.entities(),
1849                            archetype.dynamic_column(type_hash, unique).ok()?,
1850                        ))
1851                    })
1852                })
1853                .collect(),
1854        }
1855    }
1856
1857    pub fn new_view(filter: &DynamicQueryFilter, view: &'a WorldView) -> Self {
1858        Self {
1859            columns: filter.columns(),
1860            access: view
1861                .archetypes()
1862                .filter(|archetype| filter.does_accept_archetype(archetype))
1863                .flat_map(|archetype| {
1864                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1865                        Some((
1866                            archetype.entities(),
1867                            archetype.dynamic_column(type_hash, unique).ok()?,
1868                        ))
1869                    })
1870                })
1871                .collect(),
1872        }
1873    }
1874
1875    pub fn access(&'_ self, entity: Entity) -> Option<DynamicQueryItem<'_>> {
1876        let columns = self
1877            .columns
1878            .iter()
1879            .map(|(type_hash, unique)| {
1880                self.access
1881                    .iter()
1882                    .find(|(map, access)| {
1883                        map.contains(entity)
1884                            && access.info().type_hash() == *type_hash
1885                            && access.is_unique() == *unique
1886                    })
1887                    .and_then(|(map, access)| unsafe {
1888                        std::mem::transmute(access.dynamic_item(map.index_of(entity).unwrap()).ok())
1889                    })
1890            })
1891            .collect::<Option<Vec<_>>>()?;
1892        Some(DynamicQueryItem { entity, columns })
1893    }
1894}