anput/
query.rs

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            // TODO: might be fucked up here.
459            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            // TODO: might be fucked up here.
480            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            // TODO: might be fucked up here.
515            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            // TODO: might be fucked up here.
540            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 Include<T: Component>(PhantomData<fn() -> T>);
562
563impl<const LOCKING: bool, T: Component> TypedQueryFetch<'_, LOCKING> for Include<T> {
564    type Value = ();
565    type Access = ();
566
567    fn does_accept_archetype(archetype: &Archetype) -> bool {
568        archetype.has_type(TypeHash::of::<T>())
569    }
570
571    fn access(_: &Archetype) -> Result<Self::Access, QueryError> {
572        Ok(())
573    }
574
575    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
576        Some(())
577    }
578}
579
580impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Include<T> {
581    type Value = ();
582    type ValueOne = ();
583    type Access = &'a EntityDenseMap;
584
585    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
586        if archetype.has_type(TypeHash::of::<T>()) {
587            Some(archetype.entities())
588        } else {
589            None
590        }
591    }
592
593    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
594        if access.contains(entity) {
595            Some(())
596        } else {
597            None
598        }
599    }
600
601    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
602        if world.has_entity_component::<T>(entity) {
603            Some(())
604        } else {
605            None
606        }
607    }
608}
609
610pub struct Exclude<T: Component>(PhantomData<fn() -> T>);
611
612impl<const LOCKING: bool, T: Component> TypedQueryFetch<'_, LOCKING> for Exclude<T> {
613    type Value = ();
614    type Access = ();
615
616    fn does_accept_archetype(archetype: &Archetype) -> bool {
617        !archetype.has_type(TypeHash::of::<T>())
618    }
619
620    fn access(_: &Archetype) -> Result<Self::Access, QueryError> {
621        Ok(())
622    }
623
624    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
625        Some(())
626    }
627}
628
629impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Exclude<T> {
630    type Value = ();
631    type ValueOne = ();
632    type Access = &'a EntityDenseMap;
633
634    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
635        if !archetype.has_type(TypeHash::of::<T>()) {
636            Some(archetype.entities())
637        } else {
638            None
639        }
640    }
641
642    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
643        if access.contains(entity) {
644            Some(())
645        } else {
646            None
647        }
648    }
649
650    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
651        if !world.has_entity_component::<T>(entity) {
652            Some(())
653        } else {
654            None
655        }
656    }
657}
658
659pub struct Update<T: Component>(PhantomData<fn() -> T>);
660
661pub struct UpdatedAccess<'a, T>(Entity, &'a mut T);
662
663impl<'a, T> UpdatedAccess<'a, T> {
664    pub fn entity(&self) -> Entity {
665        self.0
666    }
667
668    pub fn read(&'a self) -> &'a T {
669        self.1
670    }
671
672    pub fn write(&'a mut self) -> &'a mut T {
673        self.1
674    }
675
676    pub fn notify(&self, world: &World) {
677        world.update::<T>(self.0);
678    }
679
680    pub fn write_notified(&'a mut self, world: &World) -> &'a mut T {
681        self.notify(world);
682        self.write()
683    }
684}
685
686pub struct UpdatedAccessComponent<'a, const LOCKING: bool, T: Component>(
687    Entity,
688    ComponentRefMut<'a, LOCKING, T>,
689);
690
691impl<'a, const LOCKING: bool, T: Component> UpdatedAccessComponent<'a, LOCKING, T> {
692    pub fn entity(&self) -> Entity {
693        self.0
694    }
695
696    pub fn read(&'a self) -> &'a T {
697        &self.1
698    }
699
700    pub fn write(&'a mut self) -> &'a mut T {
701        &mut self.1
702    }
703
704    pub fn notify(&self, world: &World) {
705        world.update::<T>(self.0);
706    }
707
708    pub fn write_notified(&'a mut self, world: &World) -> &'a mut T {
709        self.notify(world);
710        self.write()
711    }
712}
713
714impl<'a, const LOCKING: bool, T: Component> TypedQueryFetch<'a, LOCKING> for Update<T> {
715    type Value = UpdatedAccess<'a, T>;
716    type Access = Box<dyn Iterator<Item = (Entity, &'a mut T)> + 'a>;
717
718    fn does_accept_archetype(archetype: &Archetype) -> bool {
719        archetype.has_type(TypeHash::of::<T>())
720    }
721
722    fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
723        Ok(Box::new(
724            archetype
725                .entities()
726                .iter()
727                .zip(archetype.column_write_iter::<LOCKING, T>()?),
728        ))
729    }
730
731    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
732        access
733            .next()
734            .map(|(entity, data)| UpdatedAccess(entity, data))
735    }
736
737    fn unique_access(output: &mut HashSet<TypeHash>) {
738        output.insert(TypeHash::of::<T>());
739    }
740}
741
742impl<'a, const LOCKING: bool, T: Component> TypedLookupFetch<'a, LOCKING> for Update<T> {
743    type Value = UpdatedAccess<'a, T>;
744    type ValueOne = UpdatedAccessComponent<'a, LOCKING, T>;
745    type Access = (&'a EntityDenseMap, ArchetypeColumnAccess<'a, LOCKING, T>);
746
747    fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
748        if archetype.has_type(TypeHash::of::<T>()) {
749            Some((
750                archetype.entities(),
751                archetype.column::<LOCKING, T>(true).ok()?,
752            ))
753        } else {
754            None
755        }
756    }
757
758    fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
759        if let Some(index) = access.0.index_of(entity) {
760            access
761                .1
762                .write(index)
763                .map(|value| unsafe { std::mem::transmute(value) })
764                .map(|data| UpdatedAccess(entity, data))
765        } else {
766            None
767        }
768    }
769
770    fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
771        world
772            .component_mut::<LOCKING, T>(entity)
773            .ok()
774            .map(|data| UpdatedAccessComponent(entity, data))
775    }
776
777    fn unique_access(output: &mut HashSet<TypeHash>) {
778        output.insert(TypeHash::of::<T>());
779    }
780}
781
782impl<'a> TypedRelationLookupFetch<'a> for () {
783    type Value = ();
784    type Access = ();
785
786    fn access(_: &'a World, _: Entity) -> Self::Access {}
787
788    fn fetch(_: &mut Self::Access) -> Option<Self::Value> {
789        Some(())
790    }
791}
792
793impl<'a> TypedRelationLookupFetch<'a> for Entity {
794    type Value = Entity;
795    type Access = Option<Entity>;
796
797    fn access(_: &'a World, entity: Entity) -> Self::Access {
798        Some(entity)
799    }
800
801    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
802        access.take()
803    }
804}
805
806impl<'a, const LOCKING: bool, Fetch> TypedRelationLookupFetch<'a> for Lookup<'a, LOCKING, Fetch>
807where
808    Fetch: TypedLookupFetch<'a, LOCKING>,
809{
810    type Value = Fetch::ValueOne;
811    type Access = Option<Fetch::ValueOne>;
812
813    fn access(world: &'a World, entity: Entity) -> Self::Access {
814        world.lookup_one::<LOCKING, Fetch>(entity)
815    }
816
817    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
818        access.take()
819    }
820}
821
822pub struct Related<'a, const LOCKING: bool, T, Transform>(PhantomData<fn() -> &'a (T, Transform)>)
823where
824    T: Component,
825    Transform: TypedRelationLookupTransform<'a, Input = Entity>;
826
827impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
828    for Related<'a, LOCKING, T, Transform>
829where
830    T: Component,
831    Transform: TypedRelationLookupTransform<'a, Input = Entity>,
832{
833    type Value = Transform::Output;
834    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
835
836    fn access(world: &'a World, entity: Entity) -> Self::Access {
837        Box::new(
838            world
839                .relations_outgoing::<LOCKING, T>(entity)
840                .flat_map(|(_, _, entity)| Transform::transform(world, entity)),
841        )
842    }
843
844    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
845        access.next()
846    }
847}
848
849pub struct RelatedPair<'a, const LOCKING: bool, T, Transform>(
850    PhantomData<fn() -> &'a (T, Transform)>,
851)
852where
853    T: Component,
854    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>;
855
856impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
857    for RelatedPair<'a, LOCKING, T, Transform>
858where
859    T: Component,
860    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>,
861{
862    type Value = Transform::Output;
863    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
864
865    fn access(world: &'a World, entity: Entity) -> Self::Access {
866        Box::new(
867            world
868                .relations_outgoing::<LOCKING, T>(entity)
869                .flat_map(|(from, _, to)| Transform::transform(world, (from, to))),
870        )
871    }
872
873    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
874        access.next()
875    }
876}
877
878pub struct Traverse<'a, const LOCKING: bool, T, Transform>(PhantomData<fn() -> &'a (T, Transform)>)
879where
880    T: Component,
881    Transform: TypedRelationLookupTransform<'a, Input = Entity>;
882
883impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
884    for Traverse<'a, LOCKING, T, Transform>
885where
886    T: Component,
887    Transform: TypedRelationLookupTransform<'a, Input = Entity>,
888{
889    type Value = Transform::Output;
890    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
891
892    fn access(world: &'a World, entity: Entity) -> Self::Access {
893        Box::new(
894            world
895                .traverse_outgoing::<LOCKING, T>([entity])
896                .flat_map(|(_, to)| Transform::transform(world, to)),
897        )
898    }
899
900    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
901        access.next()
902    }
903}
904
905pub struct TraversePair<'a, const LOCKING: bool, T, Transform>(
906    PhantomData<fn() -> &'a (T, Transform)>,
907)
908where
909    T: Component,
910    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>;
911
912impl<'a, const LOCKING: bool, T, Transform> TypedRelationLookupFetch<'a>
913    for TraversePair<'a, LOCKING, T, Transform>
914where
915    T: Component,
916    Transform: TypedRelationLookupTransform<'a, Input = (Entity, Entity)>,
917{
918    type Value = Transform::Output;
919    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
920
921    fn access(world: &'a World, entity: Entity) -> Self::Access {
922        Box::new(
923            world
924                .traverse_outgoing::<LOCKING, T>([entity])
925                .flat_map(|(from, to)| Transform::transform(world, (from, to))),
926        )
927    }
928
929    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
930        access.next()
931    }
932}
933
934pub struct Join<'a, A, B>(PhantomData<fn() -> &'a (A, B)>)
935where
936    A: TypedRelationLookupFetch<'a>,
937    B: TypedRelationLookupFetch<'a>;
938
939impl<'a, A, B> TypedRelationLookupFetch<'a> for Join<'a, A, B>
940where
941    A: TypedRelationLookupFetch<'a>,
942    B: TypedRelationLookupFetch<'a>,
943{
944    type Value = (Arc<A::Value>, B::Value);
945    type Access = Box<dyn Iterator<Item = Self::Value> + 'a>;
946
947    fn access(world: &'a World, entity: Entity) -> Self::Access {
948        Box::new(
949            TypedRelationLookupIter::<A>::access(A::access(world, entity)).flat_map(move |a| {
950                let a = Arc::new(a);
951                TypedRelationLookupIter::<B>::access(B::access(world, entity))
952                    .map(move |b| (a.clone(), b))
953            }),
954        )
955    }
956
957    fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
958        access.next()
959    }
960}
961
962impl<'a> TypedRelationLookupTransform<'a> for Entity {
963    type Input = Entity;
964    type Output = Entity;
965
966    fn transform(_: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
967        std::iter::once(input)
968    }
969}
970
971pub struct Is<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>(
972    PhantomData<fn() -> &'a Fetch>,
973);
974
975impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedRelationLookupTransform<'a>
976    for Is<'a, LOCKING, Fetch>
977{
978    type Input = Entity;
979    type Output = Entity;
980
981    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
982        world
983            .lookup_one::<LOCKING, Fetch>(input)
984            .is_some()
985            .then_some(input)
986            .into_iter()
987    }
988}
989
990pub struct IsNot<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>(
991    PhantomData<fn() -> &'a Fetch>,
992);
993
994impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedRelationLookupTransform<'a>
995    for IsNot<'a, LOCKING, Fetch>
996{
997    type Input = Entity;
998    type Output = Entity;
999
1000    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1001        world
1002            .lookup_one::<LOCKING, Fetch>(input)
1003            .is_none()
1004            .then_some(input)
1005            .into_iter()
1006    }
1007}
1008
1009impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> TypedRelationLookupTransform<'a>
1010    for Lookup<'a, LOCKING, Fetch>
1011{
1012    type Input = Entity;
1013    type Output = Fetch::ValueOne;
1014
1015    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1016        world.lookup_one::<LOCKING, Fetch>(input).into_iter()
1017    }
1018}
1019
1020pub struct Limit<'a, const COUNT: usize, Transform: TypedRelationLookupTransform<'a>>(
1021    PhantomData<fn() -> &'a Transform>,
1022);
1023
1024impl<'a, const COUNT: usize, Transform: TypedRelationLookupTransform<'a>>
1025    TypedRelationLookupTransform<'a> for Limit<'a, COUNT, Transform>
1026{
1027    type Input = Transform::Input;
1028    type Output = Transform::Output;
1029
1030    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1031        Transform::transform(world, input).take(COUNT)
1032    }
1033}
1034
1035pub type Single<'a, Transform> = Limit<'a, 1, Transform>;
1036
1037pub struct SelectEntity<const INDEX: usize>;
1038
1039impl<'a, const INDEX: usize> TypedRelationLookupTransform<'a> for SelectEntity<INDEX> {
1040    type Input = (Entity, Entity);
1041    type Output = Entity;
1042
1043    fn transform(_: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1044        if INDEX == 0 {
1045            std::iter::once(input.0)
1046        } else {
1047            std::iter::once(input.1)
1048        }
1049    }
1050}
1051
1052pub struct Follow<'a, const LOCKING: bool, Transform, Fetch>(
1053    PhantomData<fn() -> &'a (Transform, Fetch)>,
1054)
1055where
1056    Transform: TypedRelationLookupTransform<'a, Input = Entity, Output = Entity>,
1057    Fetch: TypedRelationLookupFetch<'a>;
1058
1059impl<'a, const LOCKING: bool, Transform, Fetch> TypedRelationLookupTransform<'a>
1060    for Follow<'a, LOCKING, Transform, Fetch>
1061where
1062    Transform: TypedRelationLookupTransform<'a, Input = Entity, Output = Entity>,
1063    Fetch: TypedRelationLookupFetch<'a>,
1064{
1065    type Input = Entity;
1066    type Output = Fetch::Value;
1067
1068    fn transform(world: &'a World, input: Self::Input) -> impl Iterator<Item = Self::Output> {
1069        Transform::transform(world, input)
1070            .flat_map(|entity| world.relation_lookup::<LOCKING, Fetch>(entity))
1071    }
1072}
1073
1074macro_rules! impl_typed_query_fetch_tuple {
1075    ($($type:ident),+) => {
1076        impl<'a, const LOCKING: bool, $($type: TypedQueryFetch<'a, LOCKING>),+> TypedQueryFetch<'a, LOCKING> for ($($type,)+) {
1077            type Value = ($($type::Value,)+);
1078            type Access = ($($type::Access,)+);
1079
1080            fn does_accept_archetype(archetype: &Archetype) -> bool {
1081                $($type::does_accept_archetype(archetype))&&+
1082            }
1083
1084            fn access(archetype: &'a Archetype) -> Result<Self::Access, QueryError> {
1085                Ok(($($type::access(archetype)?,)+))
1086            }
1087
1088            fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
1089                #[allow(non_snake_case)]
1090                let ($($type,)+) = access;
1091                Some(($($type::fetch($type)?,)+))
1092            }
1093
1094            fn unique_access(output: &mut HashSet<TypeHash>) {
1095                $(
1096                    $type::unique_access(output);
1097                )+
1098            }
1099        }
1100    };
1101}
1102
1103impl_typed_query_fetch_tuple!(A);
1104impl_typed_query_fetch_tuple!(A, B);
1105impl_typed_query_fetch_tuple!(A, B, C);
1106impl_typed_query_fetch_tuple!(A, B, C, D);
1107impl_typed_query_fetch_tuple!(A, B, C, D, E);
1108impl_typed_query_fetch_tuple!(A, B, C, D, E, F);
1109impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G);
1110impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H);
1111impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I);
1112impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J);
1113impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K);
1114impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
1115impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
1116impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1117impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1118impl_typed_query_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
1119
1120macro_rules! impl_typed_lookup_fetch_tuple {
1121    ($($type:ident),+) => {
1122        impl<'a, const LOCKING: bool, $($type: TypedLookupFetch<'a, LOCKING>),+> TypedLookupFetch<'a, LOCKING> for ($($type,)+) {
1123            type Value = ($($type::Value,)+);
1124            type ValueOne = ($($type::ValueOne,)+);
1125            type Access = ($($type::Access,)+);
1126
1127            fn try_access(archetype: &'a Archetype) -> Option<Self::Access> {
1128                Some(($($type::try_access(archetype)?,)+))
1129            }
1130
1131            fn fetch(access: &mut Self::Access, entity: Entity) -> Option<Self::Value> {
1132                #[allow(non_snake_case)]
1133                let ($($type,)+) = access;
1134                Some(($($type::fetch($type, entity)?,)+))
1135            }
1136
1137            fn fetch_one(world: &'a World, entity: Entity) -> Option<Self::ValueOne> {
1138                Some(($($type::fetch_one(world, entity)?,)+))
1139            }
1140
1141            fn unique_access(output: &mut HashSet<TypeHash>) {
1142                $(
1143                    $type::unique_access(output);
1144                )+
1145            }
1146        }
1147    };
1148}
1149
1150impl_typed_lookup_fetch_tuple!(A);
1151impl_typed_lookup_fetch_tuple!(A, B);
1152impl_typed_lookup_fetch_tuple!(A, B, C);
1153impl_typed_lookup_fetch_tuple!(A, B, C, D);
1154impl_typed_lookup_fetch_tuple!(A, B, C, D, E);
1155impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F);
1156impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G);
1157impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H);
1158impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I);
1159impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J);
1160impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K);
1161impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
1162impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
1163impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1164impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1165impl_typed_lookup_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
1166
1167macro_rules! impl_typed_relation_fetch_tuple {
1168    ($($type:ident),+) => {
1169        impl<'a, $($type: TypedRelationLookupFetch<'a>),+> TypedRelationLookupFetch<'a> for ($($type,)+) {
1170            type Value = ($($type::Value,)+);
1171            type Access = ($($type::Access,)+);
1172
1173            fn access(world: &'a World, entity: Entity) -> Self::Access {
1174                ($($type::access(world, entity),)+)
1175            }
1176
1177            fn fetch(access: &mut Self::Access) -> Option<Self::Value> {
1178                #[allow(non_snake_case)]
1179                let ($($type,)+) = access;
1180                Some(($($type::fetch($type)?,)+))
1181            }
1182        }
1183    };
1184}
1185
1186impl_typed_relation_fetch_tuple!(A);
1187impl_typed_relation_fetch_tuple!(A, B);
1188impl_typed_relation_fetch_tuple!(A, B, C);
1189impl_typed_relation_fetch_tuple!(A, B, C, D);
1190impl_typed_relation_fetch_tuple!(A, B, C, D, E);
1191impl_typed_relation_fetch_tuple!(A, B, C, D, E, F);
1192impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G);
1193impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H);
1194impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I);
1195impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J);
1196impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K);
1197impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
1198impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
1199impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O);
1200impl_typed_relation_fetch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, O, P);
1201
1202pub struct TypedQueryIter<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> {
1203    archetypes: Vec<&'a Archetype>,
1204    index: usize,
1205    access: Option<Fetch::Access>,
1206    _phantom: PhantomData<fn() -> Fetch>,
1207}
1208
1209impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>>
1210    TypedQueryIter<'a, LOCKING, Fetch>
1211{
1212    pub fn new(world: &'a World) -> Self {
1213        Self {
1214            archetypes: world
1215                .archetypes()
1216                .filter(|archetype| Fetch::does_accept_archetype(archetype))
1217                .collect(),
1218            index: 0,
1219            access: None,
1220            _phantom: PhantomData,
1221        }
1222    }
1223
1224    pub fn new_view(view: &'a WorldView) -> Self {
1225        Self {
1226            archetypes: view
1227                .archetypes()
1228                .filter(|archetype| Fetch::does_accept_archetype(archetype))
1229                .collect(),
1230            index: 0,
1231            access: None,
1232            _phantom: PhantomData,
1233        }
1234    }
1235}
1236
1237impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Iterator
1238    for TypedQueryIter<'a, LOCKING, Fetch>
1239{
1240    type Item = Fetch::Value;
1241
1242    fn next(&mut self) -> Option<Self::Item> {
1243        while self.index < self.archetypes.len() {
1244            match self.access.as_mut() {
1245                Some(access) => {
1246                    let item = Fetch::fetch(access);
1247                    if item.is_none() {
1248                        self.access = None;
1249                        self.index += 1;
1250                        continue;
1251                    }
1252                    return item;
1253                }
1254                None => {
1255                    if let Some(archetype) = self.archetypes.get(self.index) {
1256                        self.access = Some(Fetch::access(archetype).unwrap());
1257                    } else {
1258                        self.index += 1;
1259                    }
1260                    continue;
1261                }
1262            }
1263        }
1264        None
1265    }
1266}
1267
1268pub struct TypedLookupIter<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> {
1269    access: Vec<Fetch::Access>,
1270    entities: Box<dyn Iterator<Item = Entity> + 'a>,
1271    _phantom: PhantomData<fn() -> Fetch>,
1272}
1273
1274impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>
1275    TypedLookupIter<'a, LOCKING, Fetch>
1276{
1277    pub fn new(world: &'a World, entities: impl IntoIterator<Item = Entity> + 'a) -> Self {
1278        Self {
1279            access: world
1280                .archetypes()
1281                .filter_map(|archetype| Fetch::try_access(archetype))
1282                .collect(),
1283            entities: Box::new(entities.into_iter()),
1284            _phantom: PhantomData,
1285        }
1286    }
1287
1288    pub fn new_view(view: &'a WorldView, entities: impl IntoIterator<Item = Entity> + 'a) -> Self {
1289        Self {
1290            access: view
1291                .archetypes()
1292                .filter_map(|archetype| Fetch::try_access(archetype))
1293                .collect(),
1294            entities: Box::new(entities.into_iter()),
1295            _phantom: PhantomData,
1296        }
1297    }
1298}
1299
1300impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> Iterator
1301    for TypedLookupIter<'a, LOCKING, Fetch>
1302{
1303    type Item = Fetch::Value;
1304
1305    fn next(&mut self) -> Option<Self::Item> {
1306        let entity = self.entities.next()?;
1307        for access in &mut self.access {
1308            if let Some(result) = Fetch::fetch(access, entity) {
1309                return Some(result);
1310            }
1311        }
1312        None
1313    }
1314}
1315
1316pub struct TypedLookupAccess<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>> {
1317    access: Vec<Fetch::Access>,
1318    _phantom: PhantomData<fn() -> Fetch>,
1319}
1320
1321impl<'a, const LOCKING: bool, Fetch: TypedLookupFetch<'a, LOCKING>>
1322    TypedLookupAccess<'a, LOCKING, Fetch>
1323{
1324    pub fn new(world: &'a World) -> Self {
1325        Self {
1326            access: world
1327                .archetypes()
1328                .filter_map(|archetype| Fetch::try_access(archetype))
1329                .collect(),
1330            _phantom: PhantomData,
1331        }
1332    }
1333
1334    pub fn new_view(view: &'a WorldView) -> Self {
1335        Self {
1336            access: view
1337                .archetypes()
1338                .filter_map(|archetype| Fetch::try_access(archetype))
1339                .collect(),
1340            _phantom: PhantomData,
1341        }
1342    }
1343
1344    pub fn access(&mut self, entity: Entity) -> Option<Fetch::Value> {
1345        for access in &mut self.access {
1346            if let Some(result) = Fetch::fetch(access, entity) {
1347                return Some(result);
1348            }
1349        }
1350        None
1351    }
1352}
1353
1354pub struct TypedRelationLookupIter<'a, Fetch: TypedRelationLookupFetch<'a>> {
1355    access: Fetch::Access,
1356}
1357
1358impl<'a, Fetch: TypedRelationLookupFetch<'a>> TypedRelationLookupIter<'a, Fetch> {
1359    pub fn new(world: &'a World, entity: Entity) -> Self {
1360        Self {
1361            access: Fetch::access(world, entity),
1362        }
1363    }
1364
1365    pub fn access(access: Fetch::Access) -> Self {
1366        Self { access }
1367    }
1368}
1369
1370impl<'a, Fetch: TypedRelationLookupFetch<'a>> Iterator for TypedRelationLookupIter<'a, Fetch> {
1371    type Item = Fetch::Value;
1372
1373    fn next(&mut self) -> Option<Self::Item> {
1374        Fetch::fetch(&mut self.access)
1375    }
1376}
1377
1378#[derive(Debug)]
1379enum DynamicQueryFilterMode {
1380    Read,
1381    Write,
1382    Include,
1383    Exclude,
1384}
1385
1386#[derive(Debug, Default)]
1387pub struct DynamicQueryFilter {
1388    filter: HashMap<TypeHash, DynamicQueryFilterMode>,
1389}
1390
1391impl DynamicQueryFilter {
1392    pub fn from_raw(
1393        read: &[TypeHash],
1394        write: &[TypeHash],
1395        include: &[TypeHash],
1396        exclude: &[TypeHash],
1397    ) -> Self {
1398        Self {
1399            filter: read
1400                .iter()
1401                .copied()
1402                .map(|type_hash| (type_hash, DynamicQueryFilterMode::Read))
1403                .chain(
1404                    write
1405                        .iter()
1406                        .copied()
1407                        .map(|type_hash| (type_hash, DynamicQueryFilterMode::Write)),
1408                )
1409                .chain(
1410                    include
1411                        .iter()
1412                        .copied()
1413                        .map(|type_hash| (type_hash, DynamicQueryFilterMode::Include)),
1414                )
1415                .chain(
1416                    exclude
1417                        .iter()
1418                        .copied()
1419                        .map(|type_hash| (type_hash, DynamicQueryFilterMode::Exclude)),
1420                )
1421                .collect(),
1422        }
1423    }
1424
1425    pub fn read<T>(self) -> Self {
1426        self.read_raw(TypeHash::of::<T>())
1427    }
1428
1429    pub fn read_raw(mut self, type_hash: TypeHash) -> Self {
1430        self.filter.insert(type_hash, DynamicQueryFilterMode::Read);
1431        self
1432    }
1433
1434    pub fn write<T>(self) -> Self {
1435        self.write_raw(TypeHash::of::<T>())
1436    }
1437
1438    pub fn write_raw(mut self, type_hash: TypeHash) -> Self {
1439        self.filter.insert(type_hash, DynamicQueryFilterMode::Write);
1440        self
1441    }
1442
1443    pub fn include<T>(self) -> Self {
1444        self.include_raw(TypeHash::of::<T>())
1445    }
1446
1447    pub fn include_raw(mut self, type_hash: TypeHash) -> Self {
1448        self.filter
1449            .insert(type_hash, DynamicQueryFilterMode::Include);
1450        self
1451    }
1452
1453    pub fn exclude<T>(self) -> Self {
1454        self.exclude_raw(TypeHash::of::<T>())
1455    }
1456
1457    pub fn exclude_raw(mut self, type_hash: TypeHash) -> Self {
1458        self.filter
1459            .insert(type_hash, DynamicQueryFilterMode::Exclude);
1460        self
1461    }
1462
1463    pub fn does_accept_archetype(&self, archetype: &Archetype) -> bool {
1464        self.filter.iter().all(|(type_hash, mode)| match mode {
1465            DynamicQueryFilterMode::Read
1466            | DynamicQueryFilterMode::Write
1467            | DynamicQueryFilterMode::Include => archetype.has_type(*type_hash),
1468            DynamicQueryFilterMode::Exclude => !archetype.has_type(*type_hash),
1469        })
1470    }
1471
1472    fn columns(&self) -> Vec<(TypeHash, bool)> {
1473        self.columns_iter().collect()
1474    }
1475
1476    fn columns_iter(&self) -> impl Iterator<Item = (TypeHash, bool)> + '_ {
1477        self.filter
1478            .iter()
1479            .filter_map(|(type_hash, mode)| match mode {
1480                DynamicQueryFilterMode::Read => Some((*type_hash, false)),
1481                DynamicQueryFilterMode::Write => Some((*type_hash, true)),
1482                _ => None,
1483            })
1484    }
1485
1486    pub fn unique_access(&self, output: &mut HashSet<TypeHash>) {
1487        for (type_hash, filter) in &self.filter {
1488            if matches!(filter, DynamicQueryFilterMode::Write) {
1489                output.insert(*type_hash);
1490            }
1491        }
1492    }
1493
1494    pub fn query<'a, const LOCKING: bool>(
1495        &self,
1496        world: &'a World,
1497    ) -> DynamicQueryIter<'a, LOCKING> {
1498        world.dynamic_query::<LOCKING>(self)
1499    }
1500
1501    pub fn lookup<'a, const LOCKING: bool>(
1502        &self,
1503        world: &'a World,
1504        entities: impl IntoIterator<Item = Entity> + 'a,
1505    ) -> DynamicLookupIter<'a, LOCKING> {
1506        world.dynamic_lookup::<LOCKING>(self, entities)
1507    }
1508
1509    pub fn lookup_access<'a, const LOCKING: bool>(
1510        &self,
1511        world: &'a World,
1512    ) -> DynamicLookupAccess<'a, LOCKING> {
1513        world.dynamic_lookup_access::<LOCKING>(self)
1514    }
1515}
1516
1517pub struct DynamicQueryItem<'a> {
1518    entity: Entity,
1519    columns: Vec<ArchetypeDynamicColumnItem<'a>>,
1520}
1521
1522impl<'a> DynamicQueryItem<'a> {
1523    pub fn entity(&self) -> Entity {
1524        self.entity
1525    }
1526
1527    pub fn read<T>(&self) -> Result<&ArchetypeDynamicColumnItem<'a>, QueryError> {
1528        self.read_raw(TypeHash::of::<T>())
1529    }
1530
1531    pub fn read_raw(
1532        &self,
1533        type_hash: TypeHash,
1534    ) -> Result<&ArchetypeDynamicColumnItem<'a>, QueryError> {
1535        self.columns
1536            .iter()
1537            .find(|column| column.type_hash() == type_hash)
1538            .ok_or(QueryError::TryingToReadUnavailableType { type_hash })
1539    }
1540
1541    pub fn write<T>(&mut self) -> Result<&mut ArchetypeDynamicColumnItem<'a>, QueryError> {
1542        self.write_raw(TypeHash::of::<T>())
1543    }
1544
1545    pub fn write_raw(
1546        &mut self,
1547        type_hash: TypeHash,
1548    ) -> Result<&mut ArchetypeDynamicColumnItem<'a>, QueryError> {
1549        self.columns
1550            .iter_mut()
1551            .find(|column| column.type_hash() == type_hash)
1552            .ok_or(QueryError::TryingToWriteUnavailableType { type_hash })
1553    }
1554}
1555
1556pub struct DynamicQueryIter<'a, const LOCKING: bool> {
1557    /// [(column type, unique access)]
1558    columns: Vec<(TypeHash, bool)>,
1559    archetypes: Vec<&'a Archetype>,
1560    index: usize,
1561    access: Option<(
1562        Box<dyn Iterator<Item = Entity> + 'a>,
1563        Vec<ArchetypeDynamicColumnIter<'a, LOCKING>>,
1564    )>,
1565}
1566
1567impl<'a, const LOCKING: bool> DynamicQueryIter<'a, LOCKING> {
1568    pub fn new(filter: &DynamicQueryFilter, world: &'a World) -> Self {
1569        Self {
1570            columns: filter.columns(),
1571            archetypes: world
1572                .archetypes()
1573                .filter(|archetype| filter.does_accept_archetype(archetype))
1574                .collect(),
1575            index: 0,
1576            access: None,
1577        }
1578    }
1579
1580    pub fn new_view(filter: &DynamicQueryFilter, view: &'a WorldView) -> Self {
1581        Self {
1582            columns: filter.columns(),
1583            archetypes: view
1584                .archetypes()
1585                .filter(|archetype| filter.does_accept_archetype(archetype))
1586                .collect(),
1587            index: 0,
1588            access: None,
1589        }
1590    }
1591}
1592
1593impl<'a, const LOCKING: bool> Iterator for DynamicQueryIter<'a, LOCKING> {
1594    type Item = DynamicQueryItem<'a>;
1595
1596    fn next(&mut self) -> Option<Self::Item> {
1597        while self.index < self.archetypes.len() {
1598            match self.access.as_mut() {
1599                Some((entities, columns)) => {
1600                    let entity = entities.next();
1601                    match columns
1602                        .iter_mut()
1603                        .map(|access| access.next())
1604                        .collect::<Option<_>>()
1605                        .and_then(|columns| Some((entity?, columns)))
1606                    {
1607                        Some((entity, columns)) => {
1608                            return Some(DynamicQueryItem { entity, columns });
1609                        }
1610                        None => {
1611                            self.access = None;
1612                            self.index += 1;
1613                            continue;
1614                        }
1615                    }
1616                }
1617                None => {
1618                    if let Some(archetype) = self.archetypes.get(self.index) {
1619                        self.access = Some((
1620                            Box::new(archetype.entities().iter()),
1621                            self.columns
1622                                .iter()
1623                                .copied()
1624                                .map(|(type_hash, unique)| {
1625                                    archetype.dynamic_column_iter(type_hash, unique).unwrap()
1626                                })
1627                                .collect(),
1628                        ));
1629                    } else {
1630                        self.index += 1;
1631                    }
1632                    continue;
1633                }
1634            }
1635        }
1636        None
1637    }
1638}
1639
1640pub struct DynamicLookupIter<'a, const LOCKING: bool> {
1641    /// [(column type, unique access)]
1642    columns: Vec<(TypeHash, bool)>,
1643    access: Vec<(
1644        &'a EntityDenseMap,
1645        ArchetypeDynamicColumnAccess<'a, LOCKING>,
1646    )>,
1647    entities: Box<dyn Iterator<Item = Entity> + 'a>,
1648}
1649
1650impl<'a, const LOCKING: bool> DynamicLookupIter<'a, LOCKING> {
1651    pub fn new(
1652        filter: &DynamicQueryFilter,
1653        world: &'a World,
1654        entities: impl IntoIterator<Item = Entity> + 'a,
1655    ) -> Self {
1656        Self {
1657            columns: filter.columns(),
1658            access: world
1659                .archetypes()
1660                .filter(|archetype| filter.does_accept_archetype(archetype))
1661                .flat_map(|archetype| {
1662                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1663                        Some((
1664                            archetype.entities(),
1665                            archetype.dynamic_column(type_hash, unique).ok()?,
1666                        ))
1667                    })
1668                })
1669                .collect(),
1670            entities: Box::new(entities.into_iter()),
1671        }
1672    }
1673
1674    pub fn new_view(
1675        filter: &DynamicQueryFilter,
1676        view: &'a WorldView,
1677        entities: impl IntoIterator<Item = Entity> + 'a,
1678    ) -> Self {
1679        Self {
1680            columns: filter.columns(),
1681            access: view
1682                .archetypes()
1683                .filter(|archetype| filter.does_accept_archetype(archetype))
1684                .flat_map(|archetype| {
1685                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1686                        Some((
1687                            archetype.entities(),
1688                            archetype.dynamic_column(type_hash, unique).ok()?,
1689                        ))
1690                    })
1691                })
1692                .collect(),
1693            entities: Box::new(entities.into_iter()),
1694        }
1695    }
1696}
1697
1698impl<'a, const LOCKING: bool> Iterator for DynamicLookupIter<'a, LOCKING> {
1699    type Item = DynamicQueryItem<'a>;
1700
1701    fn next(&mut self) -> Option<Self::Item> {
1702        let entity = self.entities.next()?;
1703        let columns = self
1704            .columns
1705            .iter()
1706            .map(|(type_hash, unique)| {
1707                self.access
1708                    .iter()
1709                    .find(|(map, access)| {
1710                        map.contains(entity)
1711                            && access.info().type_hash() == *type_hash
1712                            && access.is_unique() == *unique
1713                    })
1714                    .and_then(|(map, access)| unsafe {
1715                        std::mem::transmute(access.dynamic_item(map.index_of(entity).unwrap()).ok())
1716                    })
1717            })
1718            .collect::<Option<Vec<_>>>()?;
1719        Some(DynamicQueryItem { entity, columns })
1720    }
1721}
1722
1723pub struct DynamicLookupAccess<'a, const LOCKING: bool> {
1724    /// [(column type, unique access)]
1725    columns: Vec<(TypeHash, bool)>,
1726    access: Vec<(
1727        &'a EntityDenseMap,
1728        ArchetypeDynamicColumnAccess<'a, LOCKING>,
1729    )>,
1730}
1731
1732impl<'a, const LOCKING: bool> DynamicLookupAccess<'a, LOCKING> {
1733    pub fn new(filter: &DynamicQueryFilter, world: &'a World) -> Self {
1734        Self {
1735            columns: filter.columns(),
1736            access: world
1737                .archetypes()
1738                .filter(|archetype| filter.does_accept_archetype(archetype))
1739                .flat_map(|archetype| {
1740                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1741                        Some((
1742                            archetype.entities(),
1743                            archetype.dynamic_column(type_hash, unique).ok()?,
1744                        ))
1745                    })
1746                })
1747                .collect(),
1748        }
1749    }
1750
1751    pub fn new_view(filter: &DynamicQueryFilter, view: &'a WorldView) -> Self {
1752        Self {
1753            columns: filter.columns(),
1754            access: view
1755                .archetypes()
1756                .filter(|archetype| filter.does_accept_archetype(archetype))
1757                .flat_map(|archetype| {
1758                    filter.columns_iter().filter_map(|(type_hash, unique)| {
1759                        Some((
1760                            archetype.entities(),
1761                            archetype.dynamic_column(type_hash, unique).ok()?,
1762                        ))
1763                    })
1764                })
1765                .collect(),
1766        }
1767    }
1768
1769    pub fn access(&self, entity: Entity) -> Option<DynamicQueryItem> {
1770        let columns = self
1771            .columns
1772            .iter()
1773            .map(|(type_hash, unique)| {
1774                self.access
1775                    .iter()
1776                    .find(|(map, access)| {
1777                        map.contains(entity)
1778                            && access.info().type_hash() == *type_hash
1779                            && access.is_unique() == *unique
1780                    })
1781                    .and_then(|(map, access)| unsafe {
1782                        std::mem::transmute(access.dynamic_item(map.index_of(entity).unwrap()).ok())
1783                    })
1784            })
1785            .collect::<Option<Vec<_>>>()?;
1786        Some(DynamicQueryItem { entity, columns })
1787    }
1788}