legion_core/
query.rs

1use crate::borrow::RefIter;
2use crate::borrow::RefIterMut;
3use crate::borrow::RefMap;
4use crate::borrow::RefMapMut;
5use crate::borrow::RefMapMutSet;
6use crate::borrow::RefMapSet;
7use crate::borrow::TryRefIter;
8use crate::borrow::TryRefIterMut;
9use crate::entity::Entity;
10use crate::filter::And;
11use crate::filter::ArchetypeFilterData;
12use crate::filter::ChunkFilterData;
13use crate::filter::ChunksetFilterData;
14use crate::filter::ComponentFilter;
15use crate::filter::EntityFilter;
16use crate::filter::EntityFilterTuple;
17use crate::filter::Filter;
18use crate::filter::FilterResult;
19use crate::filter::Passthrough;
20use crate::filter::TagFilter;
21use crate::index::ChunkIndex;
22use crate::index::{ArchetypeIndex, SetIndex};
23#[cfg(feature = "par-iter")]
24use crate::iterator::{FissileEnumerate, FissileIterator};
25use crate::storage::ArchetypeData;
26use crate::storage::Component;
27use crate::storage::ComponentStorage;
28use crate::storage::ComponentTypeId;
29use crate::storage::Tag;
30use crate::storage::TagTypeId;
31use crate::subworld::{ComponentAccess, StorageAccessor};
32use crate::{permission::Permissions, world::EntityStore};
33use derivative::Derivative;
34use std::any::TypeId;
35use std::iter::Enumerate;
36use std::iter::Repeat;
37use std::iter::Take;
38use std::marker::PhantomData;
39use std::slice::Iter;
40use std::slice::IterMut;
41
42#[cfg(feature = "par-iter")]
43use rayon::{
44    iter::plumbing::{bridge_unindexed, Folder, UnindexedConsumer, UnindexedProducer},
45    prelude::*,
46};
47
48/// A type which can fetch a strongly-typed view of the data contained
49/// within a chunk.
50pub trait View<'a>: Sized + Send + Sync + 'static {
51    /// The iterator over the chunk data.
52    type Iter: Iterator + 'a;
53
54    /// Pulls data out of a chunk.
55    fn fetch(
56        archetype: &'a ArchetypeData,
57        chunk: &'a ComponentStorage,
58        chunk_index: ChunkIndex,
59        set_index: SetIndex,
60    ) -> Self::Iter;
61
62    /// Validates that the view does not break any component borrowing rules.
63    fn validate() -> bool;
64
65    /// Determines if the given component access includes all permissions required by the view.
66    fn validate_access(access: &ComponentAccess) -> bool;
67
68    /// Determines if the view reads the specified data type.
69    fn reads<T: Component>() -> bool;
70
71    /// Determines if the view writes to the specified data type.
72    fn writes<T: Component>() -> bool;
73
74    /// Returns the set of permissions required by the view.
75    fn requires_permissions() -> Permissions<ComponentTypeId>;
76}
77
78/// A type which can construct a default entity filter.
79pub trait DefaultFilter {
80    /// The type of entity filter constructed.
81    type Filter: EntityFilter;
82
83    /// constructs an entity filter.
84    fn filter() -> Self::Filter;
85}
86
87#[doc(hidden)]
88pub trait ReadOnly {}
89
90#[doc(hidden)]
91pub trait ViewElement {
92    type Component;
93}
94
95/// Converts a `View` into a `Query`.
96pub trait IntoQuery: DefaultFilter + for<'a> View<'a> {
97    /// Converts the `View` type into a `Query`.
98    fn query() -> Query<Self, <Self as DefaultFilter>::Filter>;
99}
100
101impl<T: DefaultFilter + for<'a> View<'a>> IntoQuery for T {
102    fn query() -> Query<Self, <Self as DefaultFilter>::Filter> {
103        if !Self::validate() {
104            panic!("invalid view, please ensure the view contains no duplicate component types");
105        }
106
107        Query {
108            view: PhantomData,
109            filter: Self::filter(),
110        }
111    }
112}
113
114/// Reads a single entity data component type from a chunk.
115#[derive(Derivative, Debug)]
116#[derivative(Default(bound = ""))]
117pub struct Read<T: Component>(PhantomData<T>);
118
119impl<T: Component> ReadOnly for Read<T> {}
120impl<T: Component> Copy for Read<T> {}
121impl<T: Component> Clone for Read<T> {
122    fn clone(&self) -> Self { *self }
123}
124
125impl<'a, T: Component> DefaultFilter for Read<T> {
126    type Filter = EntityFilterTuple<ComponentFilter<T>, Passthrough, Passthrough>;
127
128    fn filter() -> Self::Filter { super::filter::filter_fns::component() }
129}
130
131impl<'a, T: Component> View<'a> for Read<T> {
132    type Iter = RefIter<'a, T, Iter<'a, T>>;
133
134    fn fetch(
135        _: &'a ArchetypeData,
136        chunk: &'a ComponentStorage,
137        _: ChunkIndex,
138        _: SetIndex,
139    ) -> Self::Iter {
140        let (slice_borrow, slice) = unsafe {
141            chunk
142                .components(ComponentTypeId::of::<T>())
143                .unwrap_or_else(|| {
144                    panic!(
145                        "Component of type {:?} not found in chunk when fetching Read view",
146                        std::any::type_name::<T>()
147                    )
148                })
149                .data_slice::<T>()
150                .deconstruct()
151        };
152        RefIter::new(slice_borrow, slice.iter())
153    }
154
155    fn validate() -> bool { true }
156
157    fn reads<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
158
159    fn writes<D: Component>() -> bool { false }
160
161    fn validate_access(access: &ComponentAccess) -> bool {
162        access.allows_read(ComponentTypeId::of::<T>())
163    }
164
165    fn requires_permissions() -> Permissions<ComponentTypeId> {
166        let mut permissions = Permissions::new();
167        permissions.push_read(ComponentTypeId::of::<T>());
168        permissions
169    }
170}
171
172impl<T: Component> ViewElement for Read<T> {
173    type Component = T;
174}
175
176/// Reads a single entity data component type from a chunk, if it's present.
177#[derive(Derivative, Debug)]
178#[derivative(Default(bound = ""))]
179pub struct TryRead<T: Component>(PhantomData<T>);
180
181impl<T: Component> ReadOnly for TryRead<T> {}
182
183impl<T: Component> Copy for TryRead<T> {}
184impl<T: Component> Clone for TryRead<T> {
185    fn clone(&self) -> Self { *self }
186}
187
188impl<'a, T: Component> DefaultFilter for TryRead<T> {
189    type Filter = EntityFilterTuple<Passthrough, Passthrough, Passthrough>;
190
191    fn filter() -> Self::Filter { super::filter::filter_fns::passthrough() }
192}
193
194impl<'a, T: Component> View<'a> for TryRead<T> {
195    type Iter = TryRefIter<'a, T, Iter<'a, T>>;
196
197    fn fetch(
198        _: &'a ArchetypeData,
199        chunk: &'a ComponentStorage,
200        _: ChunkIndex,
201        _: SetIndex,
202    ) -> Self::Iter {
203        unsafe {
204            chunk
205                .components(ComponentTypeId::of::<T>())
206                .map(|x| {
207                    let (borrow, slice) = x.data_slice::<T>().deconstruct();
208                    TryRefIter::found(borrow, slice.iter())
209                })
210                .unwrap_or_else(|| TryRefIter::missing(chunk.len()))
211        }
212    }
213
214    fn validate() -> bool { true }
215
216    fn reads<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
217
218    fn writes<D: Component>() -> bool { false }
219
220    fn requires_permissions() -> Permissions<ComponentTypeId> {
221        let mut permissions = Permissions::new();
222        permissions.push_read(ComponentTypeId::of::<T>());
223        permissions
224    }
225
226    fn validate_access(access: &ComponentAccess) -> bool {
227        access.allows_read(ComponentTypeId::of::<T>())
228    }
229}
230
231impl<T: Component> ViewElement for TryRead<T> {
232    type Component = T;
233}
234
235/// Writes to a single entity data component type from a chunk.
236#[derive(Derivative, Debug)]
237#[derivative(Default(bound = ""))]
238pub struct Write<T: Component>(PhantomData<T>);
239
240impl<T: Component> Copy for Write<T> {}
241impl<T: Component> Clone for Write<T> {
242    fn clone(&self) -> Self { *self }
243}
244
245impl<'a, T: Component> DefaultFilter for Write<T> {
246    type Filter = EntityFilterTuple<ComponentFilter<T>, Passthrough, Passthrough>;
247
248    fn filter() -> Self::Filter { super::filter::filter_fns::component() }
249}
250
251impl<'a, T: Component> View<'a> for Write<T> {
252    type Iter = RefIterMut<'a, T, IterMut<'a, T>>;
253
254    #[inline]
255    fn fetch(
256        _: &'a ArchetypeData,
257        chunk: &'a ComponentStorage,
258        _: ChunkIndex,
259        _: SetIndex,
260    ) -> Self::Iter {
261        let (slice_borrow, slice) = unsafe {
262            chunk
263                .components(ComponentTypeId::of::<T>())
264                .unwrap_or_else(|| {
265                    panic!(
266                        "Component of type {:?} not found in chunk when fetching Write view",
267                        std::any::type_name::<T>()
268                    )
269                })
270                .data_slice_mut::<T>()
271                .deconstruct()
272        };
273        RefIterMut::new(slice_borrow, slice.iter_mut())
274    }
275
276    #[inline]
277    fn validate() -> bool { true }
278
279    #[inline]
280    fn reads<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
281
282    #[inline]
283    fn writes<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
284
285    fn requires_permissions() -> Permissions<ComponentTypeId> {
286        let mut permissions = Permissions::new();
287        permissions.push(ComponentTypeId::of::<T>());
288        permissions
289    }
290
291    fn validate_access(access: &ComponentAccess) -> bool {
292        access.allows_write(ComponentTypeId::of::<T>())
293    }
294}
295
296impl<T: Component> ViewElement for Write<T> {
297    type Component = T;
298}
299
300/// Writes a single entity data component type from a chunk, if it's present.
301#[derive(Derivative, Debug)]
302#[derivative(Default(bound = ""))]
303pub struct TryWrite<T: Component>(PhantomData<T>);
304
305impl<T: Component> Copy for TryWrite<T> {}
306impl<T: Component> Clone for TryWrite<T> {
307    fn clone(&self) -> Self { *self }
308}
309
310impl<'a, T: Component> DefaultFilter for TryWrite<T> {
311    type Filter = EntityFilterTuple<Passthrough, Passthrough, Passthrough>;
312
313    fn filter() -> Self::Filter { super::filter::filter_fns::passthrough() }
314}
315
316impl<'a, T: Component> View<'a> for TryWrite<T> {
317    type Iter = TryRefIterMut<'a, T, IterMut<'a, T>>;
318
319    fn fetch(
320        _: &'a ArchetypeData,
321        chunk: &'a ComponentStorage,
322        _: ChunkIndex,
323        _: SetIndex,
324    ) -> Self::Iter {
325        unsafe {
326            chunk
327                .components(ComponentTypeId::of::<T>())
328                .map(|x| {
329                    let (borrow, slice) = x.data_slice_mut::<T>().deconstruct();
330                    TryRefIterMut::found(borrow, slice.iter_mut())
331                })
332                .unwrap_or_else(|| TryRefIterMut::missing(chunk.len()))
333        }
334    }
335
336    fn validate() -> bool { true }
337
338    #[inline]
339    fn reads<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
340
341    #[inline]
342    fn writes<D: Component>() -> bool { TypeId::of::<T>() == TypeId::of::<D>() }
343
344    fn requires_permissions() -> Permissions<ComponentTypeId> {
345        let mut permissions = Permissions::new();
346        permissions.push(ComponentTypeId::of::<T>());
347        permissions
348    }
349
350    fn validate_access(access: &ComponentAccess) -> bool {
351        access.allows_write(ComponentTypeId::of::<T>())
352    }
353}
354
355impl<T: Component> ViewElement for TryWrite<T> {
356    type Component = T;
357}
358
359/// Reads a single shared data component type in a chunk.
360#[derive(Debug)]
361pub struct Tagged<T: Tag>(PhantomData<T>);
362
363impl<T: Tag> ReadOnly for Tagged<T> {}
364
365impl<T: Tag> Copy for Tagged<T> {}
366impl<T: Tag> Clone for Tagged<T> {
367    fn clone(&self) -> Self { *self }
368}
369
370impl<'a, T: Tag> DefaultFilter for Tagged<T> {
371    type Filter = EntityFilterTuple<TagFilter<T>, Passthrough, Passthrough>;
372
373    fn filter() -> Self::Filter { super::filter::filter_fns::tag() }
374}
375
376impl<'a, T: Tag> View<'a> for Tagged<T> {
377    type Iter = Take<Repeat<&'a T>>;
378
379    #[inline]
380    fn fetch(
381        archetype: &'a ArchetypeData,
382        chunk: &'a ComponentStorage,
383        _: ChunkIndex,
384        SetIndex(set_index): SetIndex,
385    ) -> Self::Iter {
386        let data = unsafe {
387            archetype
388                .tags()
389                .get(TagTypeId::of::<T>())
390                .unwrap_or_else(|| {
391                    panic!(
392                        "Component of type {:?} not found in archetype when fetching Tagged view",
393                        std::any::type_name::<T>()
394                    )
395                })
396                .data_slice::<T>()
397                .get_unchecked(set_index)
398        };
399        std::iter::repeat(data).take(chunk.len())
400    }
401
402    #[inline]
403    fn validate() -> bool { true }
404
405    #[inline]
406    fn reads<D: Component>() -> bool { false }
407
408    #[inline]
409    fn writes<D: Component>() -> bool { false }
410
411    fn requires_permissions() -> Permissions<ComponentTypeId> { Permissions::new() }
412
413    #[inline]
414    fn validate_access(_: &ComponentAccess) -> bool { true }
415}
416
417impl<T: Tag> ViewElement for Tagged<T> {
418    type Component = Tagged<T>;
419}
420
421macro_rules! impl_view_tuple {
422    ( $( $ty: ident ),* ) => {
423        impl<$( $ty: ViewElement + DefaultFilter ),*> DefaultFilter for ($( $ty, )*) {
424            type Filter = EntityFilterTuple<
425                And<($( <$ty::Filter as EntityFilter>::ArchetypeFilter, )*)>,
426                And<($( <$ty::Filter as EntityFilter>::ChunksetFilter, )*)>,
427                And<($( <$ty::Filter as EntityFilter>::ChunkFilter, )*)>,
428            >;
429
430            fn filter() -> Self::Filter {
431                #![allow(non_snake_case)]
432                $( let $ty = $ty::filter().into_filters(); )*
433                EntityFilterTuple::new(
434                    And { filters: ($( $ty.0, )*) },
435                    And { filters: ($( $ty.1, )*) },
436                    And { filters: ($( $ty.2, )*) },
437                )
438            }
439        }
440
441        impl<$( $ty: ReadOnly ),* > ReadOnly for ($( $ty, )*) {}
442
443        impl<$( $ty: ViewElement ),*> ViewElement for ($( $ty, )*) {
444            type Component = ($( $ty::Component, )*);
445        }
446
447        impl<'a, $( $ty: ViewElement + View<'a> ),* > View<'a> for ($( $ty, )*) {
448            type Iter = crate::zip::Zip<($( $ty::Iter, )*)>;
449
450            #[inline]
451            fn fetch(
452                archetype: &'a ArchetypeData,
453                chunk: &'a ComponentStorage,
454                chunk_index: ChunkIndex,
455                set_index: SetIndex,
456            ) -> Self::Iter {
457                crate::zip::multizip(($( $ty::fetch(archetype.clone(), chunk.clone(), chunk_index, set_index), )*))
458            }
459
460            fn validate() -> bool {
461                let types = &[$( TypeId::of::<$ty::Component>() ),*];
462                for i in 0..types.len() {
463                    for j in (i + 1)..types.len() {
464                        if unsafe { types.get_unchecked(i) == types.get_unchecked(j) } {
465                            return false;
466                        }
467                    }
468                }
469
470                true
471            }
472
473            fn validate_access(access: &ComponentAccess) -> bool {
474                $( $ty::validate_access(access) )&&*
475            }
476
477            fn reads<Data: Component>() -> bool {
478                $( $ty::reads::<Data>() )||*
479            }
480
481            fn writes<Data: Component>() -> bool {
482                $( $ty::writes::<Data>() )||*
483            }
484
485            fn requires_permissions() -> Permissions<ComponentTypeId> {
486                let mut permissions = Permissions::new();
487                $( permissions.add($ty::requires_permissions()); )*
488                permissions
489            }
490        }
491    };
492}
493
494impl_view_tuple!(A);
495impl_view_tuple!(A, B);
496impl_view_tuple!(A, B, C);
497impl_view_tuple!(A, B, C, D);
498impl_view_tuple!(A, B, C, D, E);
499impl_view_tuple!(A, B, C, D, E, F);
500impl_view_tuple!(A, B, C, D, E, F, G);
501impl_view_tuple!(A, B, C, D, E, F, G, H);
502impl_view_tuple!(A, B, C, D, E, F, G, H, I);
503impl_view_tuple!(A, B, C, D, E, F, G, H, I, J);
504impl_view_tuple!(A, B, C, D, E, F, G, H, I, J, K);
505impl_view_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
506
507/// A type-safe view of a chunk of entities all of the same data layout.
508pub struct Chunk<'a, V: for<'b> View<'b>> {
509    archetype: &'a ArchetypeData,
510    components: &'a ComponentStorage,
511    chunk_index: ChunkIndex,
512    set_index: SetIndex,
513    view: PhantomData<V>,
514}
515
516impl<'a, V: for<'b> View<'b>> Chunk<'a, V> {
517    pub fn new(archetype: &'a ArchetypeData, set_index: SetIndex, chunk_index: ChunkIndex) -> Self {
518        Self {
519            components: unsafe {
520                archetype
521                    .chunkset_unchecked(set_index)
522                    .chunk_unchecked(chunk_index)
523            },
524            archetype,
525            chunk_index,
526            set_index,
527            view: PhantomData,
528        }
529    }
530
531    /// Get a slice of all entities contained within the chunk.
532    #[inline]
533    pub fn entities(&self) -> &'a [Entity] { self.components.entities() }
534
535    /// Get an iterator of all data contained within the chunk.
536    #[inline]
537    pub fn iter_mut(&mut self) -> <V as View<'a>>::Iter {
538        V::fetch(
539            self.archetype,
540            self.components,
541            self.chunk_index,
542            self.set_index,
543        )
544    }
545
546    /// Get an iterator of all data and entity IDs contained within the chunk.
547    #[inline]
548    pub fn iter_entities_mut(&mut self) -> ZipEntities<'a, V> {
549        ZipEntities {
550            entities: self.entities(),
551            data: V::fetch(
552                self.archetype,
553                self.components,
554                self.chunk_index,
555                self.set_index,
556            ),
557            index: 0,
558            view: PhantomData,
559        }
560    }
561
562    /// Get a tag value.
563    pub fn tag<T: Tag>(&self) -> Option<&T> {
564        self.archetype
565            .tags()
566            .get(TagTypeId::of::<T>())
567            .map(|tags| unsafe { tags.data_slice::<T>() })
568            .map(|slice| unsafe { slice.get_unchecked(*self.set_index) })
569    }
570
571    /// Get a slice of component data.
572    ///
573    /// # Panics
574    ///
575    /// This method performs runtime borrow checking. It will panic if
576    /// any other code is concurrently writing to the data slice.
577    pub fn components<T: Component>(&self) -> Option<RefMap<'a, &[T]>> {
578        if !V::reads::<T>() {
579            panic!("data type not readable via this query");
580        }
581        self.components
582            .components(ComponentTypeId::of::<T>())
583            .map(|c| unsafe { c.data_slice::<T>() })
584    }
585
586    /// Get a mutable slice of component data.
587    ///
588    /// # Panics
589    ///
590    /// This method performs runtime borrow checking. It will panic if
591    /// any other code is concurrently accessing the data slice.
592    pub fn components_mut<T: Component>(&self) -> Option<RefMapMut<'a, &mut [T]>> {
593        if !V::writes::<T>() {
594            panic!("data type not writable via this query");
595        }
596        self.components
597            .components(ComponentTypeId::of::<T>())
598            .map(|c| unsafe { c.data_slice_mut::<T>() })
599    }
600}
601
602/// An iterator which yields view data tuples and entity IDs from a `Chunk`.
603pub struct ZipEntities<'data, V: View<'data>> {
604    entities: &'data [Entity],
605    data: <V as View<'data>>::Iter,
606    index: usize,
607    view: PhantomData<V>,
608}
609
610impl<'data, V: View<'data>> Iterator for ZipEntities<'data, V> {
611    type Item = (Entity, <V::Iter as Iterator>::Item);
612
613    #[inline]
614    fn next(&mut self) -> Option<Self::Item> {
615        if let Some(data) = self.data.next() {
616            let i = self.index;
617            self.index += 1;
618            unsafe { Some((*self.entities.get_unchecked(i), data)) }
619        } else {
620            None
621        }
622    }
623
624    #[inline]
625    fn size_hint(&self) -> (usize, Option<usize>) {
626        let len = self.entities.len() - self.index;
627        (len, Some(len))
628    }
629}
630
631/// An iterator over all chunks that match a given query.
632pub struct ChunkViewIter<'data, 'filter, V, FArch, FChunkset, FChunk>
633where
634    V: for<'a> View<'a>,
635    FArch: Filter<ArchetypeFilterData<'data>>,
636    FChunkset: Filter<ChunksetFilterData<'data>>,
637    FChunk: Filter<ChunkFilterData<'data>>,
638{
639    _view: PhantomData<V>,
640    storage: StorageAccessor<'data>,
641    arch_filter: &'filter FArch,
642    chunkset_filter: &'filter FChunkset,
643    chunk_filter: &'filter FChunk,
644    archetypes: Enumerate<FArch::Iter>,
645    set_frontier: Option<(&'data ArchetypeData, Take<Enumerate<FChunkset::Iter>>)>,
646    chunk_frontier: Option<(
647        &'data ArchetypeData,
648        SetIndex,
649        Take<Enumerate<FChunk::Iter>>,
650    )>,
651}
652
653impl<'data, 'filter, V, FArch, FChunkset, FChunk>
654    ChunkViewIter<'data, 'filter, V, FArch, FChunkset, FChunk>
655where
656    V: for<'a> View<'a>,
657    FArch: Filter<ArchetypeFilterData<'data>>,
658    FChunkset: Filter<ChunksetFilterData<'data>>,
659    FChunk: Filter<ChunkFilterData<'data>>,
660{
661    fn next_set(&mut self) -> Option<(&'data ArchetypeData, SetIndex)> {
662        loop {
663            // if we are looping through an archetype, find the next set
664            if let Some((ref arch, ref mut chunks)) = self.set_frontier {
665                for (set_index, filter_data) in chunks {
666                    if self.chunkset_filter.is_match(&filter_data).is_pass() {
667                        return Some((arch, SetIndex(set_index)));
668                    }
669                }
670            }
671
672            // we have completed the current set, find the next one
673            loop {
674                match self.archetypes.next() {
675                    Some((arch_index, arch_data)) => {
676                        if self.arch_filter.is_match(&arch_data).is_pass() {
677                            // validate that we are allowed to access this archetype
678                            if !self
679                                .storage
680                                .can_access_archetype(ArchetypeIndex(arch_index))
681                            {
682                                panic!(
683                                    "query attempted to access archetype unavailable via sub world"
684                                );
685                            }
686                            // we have found another set
687                            self.set_frontier = {
688                                let chunks = unsafe {
689                                    self.storage.inner().archetypes().get_unchecked(arch_index)
690                                };
691                                let data = ChunksetFilterData {
692                                    archetype_data: chunks,
693                                };
694
695                                Some((
696                                    chunks,
697                                    self.chunkset_filter
698                                        .collect(data)
699                                        .enumerate()
700                                        .take(chunks.len()),
701                                ))
702                            };
703                            break;
704                        }
705                    }
706                    // there are no more sets
707                    None => return None,
708                }
709            }
710        }
711    }
712}
713
714impl<'data, 'filter, V, FArch, FChunkset, FChunk> Iterator
715    for ChunkViewIter<'data, 'filter, V, FArch, FChunkset, FChunk>
716where
717    V: for<'a> View<'a>,
718    FArch: Filter<ArchetypeFilterData<'data>>,
719    FChunkset: Filter<ChunksetFilterData<'data>>,
720    FChunk: Filter<ChunkFilterData<'data>>,
721{
722    type Item = Chunk<'data, V>;
723
724    fn next(&mut self) -> Option<Self::Item> {
725        loop {
726            // if we are looping through a set, then yield the next chunk
727            if let Some((ref arch, set_index, ref mut set)) = self.chunk_frontier {
728                for (chunk_index, filter_data) in set {
729                    if self.chunk_filter.is_match(&filter_data).is_pass() {
730                        return Some(Chunk::new(arch, set_index, ChunkIndex(chunk_index)));
731                    }
732                }
733            }
734
735            // we have completed the set, find the next
736            if let Some((ref arch, set_index)) = self.next_set() {
737                let chunks = unsafe { arch.chunkset_unchecked(set_index) }.occupied();
738                self.chunk_frontier = Some((
739                    arch,
740                    set_index,
741                    self.chunk_filter
742                        .collect(ChunkFilterData { chunks })
743                        .enumerate()
744                        .take(chunks.len()),
745                ))
746            } else {
747                return None;
748            }
749        }
750    }
751}
752
753// An iterator which iterates through all entity data in all chunks.
754pub struct ChunkDataIter<'data, V, I>
755where
756    V: for<'a> View<'a>,
757    I: Iterator<Item = Chunk<'data, V>>,
758{
759    iter: I,
760    frontier: Option<<V as View<'data>>::Iter>,
761    _view: PhantomData<V>,
762}
763
764impl<'data, V, I> Iterator for ChunkDataIter<'data, V, I>
765where
766    V: for<'a> View<'a>,
767    I: Iterator<Item = Chunk<'data, V>>,
768{
769    type Item = <<V as View<'data>>::Iter as Iterator>::Item;
770
771    #[inline(always)]
772    fn next(&mut self) -> Option<Self::Item> {
773        loop {
774            if let Some(ref mut inner) = self.frontier {
775                if let elt @ Some(_) = inner.next() {
776                    return elt;
777                }
778            }
779            match self.iter.next() {
780                Some(mut inner) => self.frontier = Some(inner.iter_mut()),
781                None => return None,
782            }
783        }
784    }
785}
786
787/// An iterator which iterates through all entity data in all chunks, zipped with entity ID.
788pub struct ChunkEntityIter<'data, V, I>
789where
790    V: for<'a> View<'a>,
791    I: Iterator<Item = Chunk<'data, V>>,
792{
793    iter: I,
794    frontier: Option<ZipEntities<'data, V>>,
795    _view: PhantomData<V>,
796}
797
798impl<'data, 'query, V, I> Iterator for ChunkEntityIter<'data, V, I>
799where
800    V: for<'a> View<'a>,
801    I: Iterator<Item = Chunk<'data, V>>,
802{
803    type Item = (Entity, <<V as View<'data>>::Iter as Iterator>::Item);
804
805    #[inline]
806    fn next(&mut self) -> Option<Self::Item> {
807        loop {
808            if let Some(ref mut inner) = self.frontier {
809                if let elt @ Some(_) = inner.next() {
810                    return elt;
811                }
812            }
813            match self.iter.next() {
814                Some(mut inner) => self.frontier = Some(inner.iter_entities_mut()),
815                None => return None,
816            }
817        }
818    }
819}
820
821/// Queries for entities within a `World`.
822///
823/// # Examples
824///
825/// Queries can be constructed from any `View` type, including tuples of `View`s.
826///
827/// ```rust
828/// # use legion_core::prelude::*;
829/// # #[derive(Copy, Clone, Debug, PartialEq)]
830/// # struct Position;
831/// # #[derive(Copy, Clone, Debug, PartialEq)]
832/// # struct Velocity;
833/// # #[derive(Copy, Clone, Debug, PartialEq)]
834/// # struct Model;
835/// // A query which matches any entity with a `Position` component
836/// let mut query = Read::<Position>::query();
837///
838/// // A query which matches any entity with both a `Position` and a `Velocity` component
839/// let mut query = <(Read<Position>, Read<Velocity>)>::query();
840/// ```
841///
842/// The view determines what data is accessed, and whether it is accessed mutably or not.
843///
844/// ```rust
845/// # use legion_core::prelude::*;
846/// # #[derive(Copy, Clone, Debug, PartialEq)]
847/// # struct Position;
848/// # #[derive(Copy, Clone, Debug, PartialEq)]
849/// # struct Velocity;
850/// # #[derive(Copy, Clone, Debug, PartialEq)]
851/// # struct Model;
852/// // A query which writes `Position`, reads `Velocity` and reads `Model`
853/// // Tags are read-only, and is distinguished from entity data reads with `Tagged<T>`.
854/// let mut query = <(Write<Position>, Read<Velocity>, Tagged<Model>)>::query();
855/// ```
856///
857/// By default, a query will filter its results to include only entities with the data
858/// types accessed by the view. However, additional filters can be specified if needed:
859///
860/// ```rust
861/// # use legion_core::prelude::*;
862/// # #[derive(Copy, Clone, Debug, PartialEq)]
863/// # struct Position;
864/// # #[derive(Copy, Clone, Debug, PartialEq)]
865/// # struct Velocity;
866/// # #[derive(Copy, Clone, Debug, PartialEq)]
867/// # struct Model;
868/// #[derive(Copy, Clone, Debug, PartialEq)]
869/// struct Static;
870///
871/// // A query which also requires that entities have the `Static` tag
872/// let mut query = <(Read<Position>, Tagged<Model>)>::query().filter(tag::<Static>());
873/// ```
874///
875/// Filters can be combined with bitwise operators:
876///
877/// ```rust
878/// # use legion_core::prelude::*;
879/// # #[derive(Copy, Clone, Debug, PartialEq)]
880/// # struct Position;
881/// # #[derive(Copy, Clone, Debug, PartialEq)]
882/// # struct Velocity;
883/// # #[derive(Copy, Clone, Debug, PartialEq)]
884/// # struct Model;
885/// #[derive(Copy, Clone, Debug, PartialEq)]
886/// struct Static;
887///
888/// // This query matches entities with positions and a model
889/// // But it also requires that the entity is not static, or has moved (even if static)
890/// let mut query = <(Read<Position>, Tagged<Model>)>::query()
891///     .filter(!tag::<Static>() | changed::<Position>());
892/// ```
893///
894/// Filters can be iterated through to pull data out of a `World`:
895///
896/// ```rust
897/// # use legion_core::prelude::*;
898/// # #[derive(Copy, Clone, Debug, PartialEq)]
899/// # struct Position;
900/// # #[derive(Copy, Clone, Debug, PartialEq)]
901/// # struct Velocity;
902/// # #[derive(Copy, Clone, Debug, PartialEq)]
903/// # struct Model;
904/// # let universe = Universe::new();
905/// # let mut world = universe.create_world();
906/// // A query which writes `Position`, reads `Velocity` and reads `Model`
907/// // Tags are read-only, and is distinguished from entity data reads with `Tagged<T>`.
908/// let mut query = <(Write<Position>, Read<Velocity>, Tagged<Model>)>::query();
909///
910/// for (mut pos, vel, model) in query.iter_mut(&mut world) {
911///     // `.iter` yields tuples of references to a single entity's data:
912///     // pos: &mut Position
913///     // vel: &Velocity
914///     // model: &Model
915/// }
916/// ```
917///
918/// The lower level `iter_chunks_mut` function allows access to each underlying chunk of entity data.
919/// This allows you to run code for each tag value, or to retrieve a contiguous data slice.
920///
921/// ```rust
922/// # use legion_core::prelude::*;
923/// # #[derive(Copy, Clone, Debug, PartialEq)]
924/// # struct Position;
925/// # #[derive(Copy, Clone, Debug, PartialEq)]
926/// # struct Velocity;
927/// # #[derive(Copy, Clone, Debug, PartialEq)]
928/// # struct Model;
929/// # let universe = Universe::new();
930/// # let mut world = universe.create_world();
931/// let mut query = <(Write<Position>, Read<Velocity>, Tagged<Model>)>::query();
932///
933/// for chunk in query.iter_chunks_mut(&mut world) {
934///     let model = chunk.tag::<Model>();
935///     let positions = chunk.components_mut::<Position>();
936///     let velocities = chunk.components::<Velocity>();
937/// }
938/// ```
939///
940/// The `ChunkView` yielded from `iter_chunks_mut` allows access to all shared data in the chunk (queried for or not),
941/// but entity data slices can only be accessed if they were requested in the query's view. Attempting to access
942/// other data types, or attempting to write to components that were only requested via a `Read` will panic.
943#[derive(Derivative)]
944#[derivative(Clone(bound = "F: Clone"))]
945pub struct Query<V: for<'a> View<'a>, F: EntityFilter> {
946    view: PhantomData<V>,
947    pub filter: F,
948}
949
950impl<V, F> Query<V, F>
951where
952    V: for<'a> View<'a>,
953    F: EntityFilter,
954{
955    /// Adds an additional filter to the query.
956    pub fn filter<T: EntityFilter>(self, filter: T) -> Query<V, <F as std::ops::BitAnd<T>>::Output>
957    where
958        F: std::ops::BitAnd<T>,
959        <F as std::ops::BitAnd<T>>::Output: EntityFilter,
960    {
961        Query {
962            view: self.view,
963            filter: self.filter & filter,
964        }
965    }
966
967    /// Gets an iterator which iterates through all chunks that match the query.
968    /// Does not perform static borrow checking.
969    ///
970    /// # Safety
971    ///
972    /// The normal borrowing restrictions apply for the duration of the iteration:
973    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
974    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
975    ///
976    /// # Panics
977    ///
978    /// This function may panic if other code is concurrently accessing the same components.
979    pub unsafe fn iter_chunks_unchecked<'a, 'data, T: EntityStore>(
980        &'a self,
981        world: &'data T,
982    ) -> ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter> {
983        self.filter.init();
984        let (arch_filter, chunkset_filter, chunk_filter) = self.filter.filters();
985        let storage = world.get_component_storage::<V>().unwrap();
986        let archetypes = arch_filter
987            .collect(ArchetypeFilterData {
988                component_types: storage.inner().component_types(),
989                tag_types: storage.inner().tag_types(),
990            })
991            .enumerate();
992        ChunkViewIter {
993            storage,
994            arch_filter,
995            chunkset_filter,
996            chunk_filter,
997            archetypes,
998            set_frontier: None,
999            chunk_frontier: None,
1000            _view: PhantomData,
1001        }
1002    }
1003
1004    /// Gets an iterator which iterates through all chunks that match the query.
1005    pub fn iter_chunks<'a, 'data, T: EntityStore>(
1006        &'a self,
1007        world: &'data T,
1008    ) -> ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>
1009    where
1010        V: ReadOnly,
1011    {
1012        // safe because the view can only read data immutably
1013        unsafe { self.iter_chunks_unchecked(world) }
1014    }
1015
1016    /// Gets an iterator which iterates through all chunks that match the query.
1017    pub fn iter_chunks_mut<'a, 'data, T: EntityStore>(
1018        &'a self,
1019        world: &'data mut T,
1020    ) -> ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter> {
1021        // safe because the &mut World ensures exclusivity
1022        unsafe { self.iter_chunks_unchecked(world) }
1023    }
1024
1025    /// Gets an iterator which iterates through all entity data that matches the query, and also yields the the `Entity` IDs.
1026    /// Does not perform static borrow checking.
1027    ///
1028    /// # Safety
1029    ///
1030    /// The normal borrowing restrictions apply for the duration of the iteration:
1031    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1032    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1033    ///
1034    /// # Panics
1035    ///
1036    /// This function may panic if other code is concurrently accessing the same components.
1037    pub unsafe fn iter_entities_unchecked<'a, 'data, T: EntityStore>(
1038        &'a self,
1039        world: &'data T,
1040    ) -> ChunkEntityIter<
1041        'data,
1042        V,
1043        ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>,
1044    > {
1045        ChunkEntityIter {
1046            iter: self.iter_chunks_unchecked(world),
1047            frontier: None,
1048            _view: PhantomData,
1049        }
1050    }
1051
1052    /// Gets an iterator which iterates through all entity data that matches the query, and also yields the the `Entity` IDs.
1053    pub fn iter_entities<'a, 'data, T: EntityStore>(
1054        &'a self,
1055        world: &'data T,
1056    ) -> ChunkEntityIter<
1057        'data,
1058        V,
1059        ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>,
1060    >
1061    where
1062        V: ReadOnly,
1063    {
1064        // safe because the view can only read data immutably
1065        unsafe { self.iter_entities_unchecked(world) }
1066    }
1067
1068    /// Gets an iterator which iterates through all entity data that matches the query, and also yields the the `Entity` IDs.
1069    pub fn iter_entities_mut<'a, 'data, T: EntityStore>(
1070        &'a self,
1071        world: &'data mut T,
1072    ) -> ChunkEntityIter<
1073        'data,
1074        V,
1075        ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>,
1076    > {
1077        // safe because the &mut World ensures exclusivity
1078        unsafe { self.iter_entities_unchecked(world) }
1079    }
1080
1081    /// Gets an iterator which iterates through all entity data that matches the query.
1082    /// Does not perform static borrow checking.
1083    ///
1084    /// # Safety
1085    ///
1086    /// The normal borrowing restrictions apply for the duration of the iteration:
1087    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1088    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1089    ///
1090    /// # Panics
1091    ///
1092    /// This function may panic if other code is concurrently accessing the same components.
1093    pub unsafe fn iter_unchecked<'a, 'data, T: EntityStore>(
1094        &'a self,
1095        world: &'data T,
1096    ) -> ChunkDataIter<
1097        'data,
1098        V,
1099        ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>,
1100    > {
1101        ChunkDataIter {
1102            iter: self.iter_chunks_unchecked(world),
1103            frontier: None,
1104            _view: PhantomData,
1105        }
1106    }
1107
1108    /// Gets an iterator which iterates through all entity data that matches the query.
1109    pub fn iter<'a, 'data, T: EntityStore>(
1110        &'a self,
1111        world: &'data T,
1112    ) -> ChunkDataIter<
1113        'data,
1114        V,
1115        ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>,
1116    >
1117    where
1118        V: ReadOnly,
1119    {
1120        // safe because the view can only read data immutably
1121        unsafe { self.iter_unchecked(world) }
1122    }
1123
1124    /// Gets an iterator which iterates through all entity data that matches the query.
1125    pub fn iter_mut<'a, 'data, T: EntityStore>(
1126        &'a self,
1127        world: &'data mut T,
1128    ) -> ChunkDataIter<
1129        'data,
1130        V,
1131        ChunkViewIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>,
1132    > {
1133        // safe because the &mut World ensures exclusivity
1134        unsafe { self.iter_unchecked(world) }
1135    }
1136
1137    /// Iterates through all entity data that matches the query.
1138    /// Does not perform static borrow checking.
1139    ///
1140    /// # Safety
1141    ///
1142    /// The normal borrowing restrictions apply for the duration of the iteration:
1143    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1144    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1145    ///
1146    /// # Panics
1147    ///
1148    /// This function may panic if other code is concurrently accessing the same components.
1149    pub unsafe fn for_each_entities_unchecked<'a, 'data, T, W>(&'a self, world: &'data W, mut f: T)
1150    where
1151        T: Fn((Entity, <<V as View<'data>>::Iter as Iterator>::Item)),
1152        W: EntityStore,
1153    {
1154        for mut chunk in self.iter_chunks_unchecked(world) {
1155            chunk.iter_entities_mut().for_each(&mut f)
1156        }
1157    }
1158
1159    /// Iterates through all entity data that matches the query.
1160    pub fn for_each_entities<'a, 'data, T, W>(&'a self, world: &'data W, f: T)
1161    where
1162        T: Fn((Entity, <<V as View<'data>>::Iter as Iterator>::Item)),
1163        V: ReadOnly,
1164        W: EntityStore,
1165    {
1166        // safe because the view can only read data immutably
1167        unsafe { self.for_each_entities_unchecked(world, f) };
1168    }
1169
1170    /// Iterates through all entity data that matches the query.
1171    pub fn for_each_entities_mut<'a, 'data, T, W>(&'a self, world: &'data mut W, f: T)
1172    where
1173        T: Fn((Entity, <<V as View<'data>>::Iter as Iterator>::Item)),
1174        W: EntityStore,
1175    {
1176        // safe because the &mut World ensures exclusivity
1177        unsafe { self.for_each_entities_unchecked(world, f) };
1178    }
1179
1180    /// Iterates through all entity data that matches the query.
1181    /// Does not perform static borrow checking.
1182    ///
1183    /// # Safety
1184    ///
1185    /// The normal borrowing restrictions apply for the duration of the iteration:
1186    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1187    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1188    ///
1189    /// # Panics
1190    ///
1191    /// This function may panic if other code is concurrently accessing the same components.
1192    pub unsafe fn for_each_unchecked<'a, 'data, T, W>(&'a self, world: &'data W, mut f: T)
1193    where
1194        T: Fn(<<V as View<'data>>::Iter as Iterator>::Item),
1195        W: EntityStore,
1196    {
1197        for mut chunk in self.iter_chunks_unchecked(world) {
1198            chunk.iter_mut().for_each(&mut f)
1199        }
1200    }
1201
1202    /// Iterates through all entity data that matches the query.
1203    pub fn for_each<'a, 'data, T, W>(&'a self, world: &'data W, f: T)
1204    where
1205        T: Fn(<<V as View<'data>>::Iter as Iterator>::Item),
1206        V: ReadOnly,
1207        W: EntityStore,
1208    {
1209        // safe because the view can only read data immutably
1210        unsafe { self.for_each_unchecked(world, f) };
1211    }
1212
1213    /// Iterates through all entity data that matches the query.
1214    pub fn for_each_mut<'a, 'data, T, W>(&'a self, world: &'data mut W, f: T)
1215    where
1216        T: Fn(<<V as View<'data>>::Iter as Iterator>::Item),
1217        W: EntityStore,
1218    {
1219        // safe because the &mut World ensures exclusivity
1220        unsafe { self.for_each_unchecked(world, f) };
1221    }
1222
1223    /// Returns a RefMapSet of all components of a given type. This simplifies getting a slice of
1224    /// references to all components of type T that match the filter. This can be useful for passing
1225    /// to other libraries or FFI.
1226    pub fn components<'a, T: Component, W: EntityStore>(
1227        &self,
1228        world: &'a W,
1229    ) -> RefMapSet<'a, Vec<&'a T>> {
1230        if !V::reads::<T>() {
1231            panic!("data type not readable via this query");
1232        }
1233
1234        let mut borrows = vec![];
1235        let mut refs = vec![];
1236        let storage = world.get_component_storage::<Read<T>>().unwrap().inner();
1237
1238        unsafe {
1239            self.filter
1240                .iter_archetype_indexes(storage)
1241                .flat_map(|archetype_index| {
1242                    storage
1243                        .archetypes()
1244                        .get_unchecked(archetype_index.0)
1245                        .iter_data_slice::<T>()
1246                })
1247                .map(|x| x.deconstruct())
1248                .for_each(|(borrow, slice)| {
1249                    borrows.push(borrow);
1250                    refs.extend(slice);
1251                });
1252        }
1253
1254        RefMapSet::new(borrows, refs)
1255    }
1256
1257    /// Returns a RefMapMutSet of all components of a given type. This simplifies getting a slice of
1258    /// mutable refs to all components of type T that match the filter.
1259    pub fn components_mut<'a, T: Component, W: EntityStore>(
1260        &self,
1261        world: &'a mut W,
1262    ) -> RefMapMutSet<'a, Vec<&'a mut T>> {
1263        if !V::writes::<T>() {
1264            panic!("data type not writable via this query");
1265        }
1266
1267        let mut borrows = vec![];
1268        let mut refs = vec![];
1269        let storage = world.get_component_storage::<Read<T>>().unwrap().inner();
1270
1271        unsafe {
1272            self.filter
1273                .iter_archetype_indexes(storage)
1274                .flat_map(|archetype_index| {
1275                    storage
1276                        .archetypes()
1277                        .get_unchecked(archetype_index.0)
1278                        .iter_data_slice_unchecked_mut::<T>()
1279                })
1280                .map(|x| x.deconstruct())
1281                .for_each(|(borrow, slice)| {
1282                    borrows.push(borrow);
1283                    refs.extend(slice);
1284                });
1285        }
1286
1287        RefMapMutSet::new(borrows, refs)
1288    }
1289
1290    #[cfg(feature = "par-iter")]
1291    /// Gets an iterator which iterates through all chunks that match the query in parallel.
1292    /// Does not perform static borrow checking.
1293    ///
1294    /// # Safety
1295    ///
1296    /// The normal borrowing restrictions apply for the duration of the iteration:
1297    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1298    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1299    ///
1300    /// # Panics
1301    ///
1302    /// This function may panic if other code is concurrently accessing the same components.
1303    pub unsafe fn par_iter_chunks_unchecked<'a, 'data, W>(
1304        &'a self,
1305        world: &'data W,
1306    ) -> ChunkViewParIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>
1307    where
1308        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'data>>>::Iter: FissileIterator,
1309        <F::ChunksetFilter as Filter<ChunksetFilterData<'data>>>::Iter: FissileIterator,
1310        <F::ChunkFilter as Filter<ChunkFilterData<'data>>>::Iter: FissileIterator,
1311        W: EntityStore,
1312    {
1313        self.filter.init();
1314        let (arch_filter, chunkset_filter, chunk_filter) = self.filter.filters();
1315        let storage = world.get_component_storage::<V>().unwrap();
1316        let archetypes = FissileEnumerate::new(arch_filter.collect(ArchetypeFilterData {
1317            component_types: storage.inner().component_types(),
1318            tag_types: storage.inner().tag_types(),
1319        }));
1320        ChunkViewParIter {
1321            storage,
1322            arch_filter,
1323            chunkset_filter,
1324            chunk_filter,
1325            archetypes,
1326            set_frontier: None,
1327            chunk_frontier: None,
1328            _view: PhantomData,
1329        }
1330    }
1331
1332    #[cfg(feature = "par-iter")]
1333    /// Gets an iterator which iterates through all chunks that match the query in parallel.
1334    pub fn par_iter_chunks<'a, 'data, W>(
1335        &'a self,
1336        world: &'data W,
1337    ) -> ChunkViewParIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>
1338    where
1339        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'data>>>::Iter: FissileIterator,
1340        <F::ChunksetFilter as Filter<ChunksetFilterData<'data>>>::Iter: FissileIterator,
1341        <F::ChunkFilter as Filter<ChunkFilterData<'data>>>::Iter: FissileIterator,
1342        V: ReadOnly,
1343        W: EntityStore,
1344    {
1345        // safe because the view can only read data immutably
1346        unsafe { self.par_iter_chunks_unchecked(world) }
1347    }
1348
1349    #[cfg(feature = "par-iter")]
1350    /// Gets an iterator which iterates through all chunks that match the query in parallel.
1351    pub fn par_iter_chunks_mut<'a, 'data, W>(
1352        &'a self,
1353        world: &'data mut W,
1354    ) -> ChunkViewParIter<'data, 'a, V, F::ArchetypeFilter, F::ChunksetFilter, F::ChunkFilter>
1355    where
1356        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'data>>>::Iter: FissileIterator,
1357        <F::ChunksetFilter as Filter<ChunksetFilterData<'data>>>::Iter: FissileIterator,
1358        <F::ChunkFilter as Filter<ChunkFilterData<'data>>>::Iter: FissileIterator,
1359        W: EntityStore,
1360    {
1361        // safe because the &mut World ensures exclusivity
1362        unsafe { self.par_iter_chunks_unchecked(world) }
1363    }
1364
1365    /// Iterates through all entity data that matches the query in parallel.
1366    /// Does not perform static borrow checking.
1367    ///
1368    /// # Safety
1369    ///
1370    /// The normal borrowing restrictions apply for the duration of the iteration:
1371    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1372    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1373    ///
1374    /// # Panics
1375    ///
1376    /// This function may panic if other code is concurrently accessing the same components.
1377    #[cfg(feature = "par-iter")]
1378    pub unsafe fn par_entities_for_each_unchecked<'a, T, W>(&'a self, world: &'a W, f: T)
1379    where
1380        T: Fn((Entity, <<V as View<'a>>::Iter as Iterator>::Item)) + Send + Sync,
1381        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1382        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1383        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1384        W: EntityStore,
1385    {
1386        self.par_for_each_chunk_unchecked(world, |mut chunk| {
1387            for data in chunk.iter_entities_mut() {
1388                f(data);
1389            }
1390        });
1391    }
1392
1393    /// Iterates through all entity data that matches the query in parallel.
1394    #[cfg(feature = "par-iter")]
1395    pub fn par_entities_for_each<'a, T, W>(&'a self, world: &'a W, f: T)
1396    where
1397        T: Fn((Entity, <<V as View<'a>>::Iter as Iterator>::Item)) + Send + Sync,
1398        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1399        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1400        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1401        V: ReadOnly,
1402        W: EntityStore,
1403    {
1404        // safe because the view can only read data immutably
1405        unsafe { self.par_entities_for_each_unchecked(world, f) };
1406    }
1407
1408    /// Iterates through all entity data that matches the query in parallel.
1409    #[cfg(feature = "par-iter")]
1410    pub fn par_entities_for_each_mut<'a, T, W>(&'a self, world: &'a mut W, f: T)
1411    where
1412        T: Fn((Entity, <<V as View<'a>>::Iter as Iterator>::Item)) + Send + Sync,
1413        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1414        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1415        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1416        W: EntityStore,
1417    {
1418        // safe because the &mut World ensures exclusivity
1419        unsafe { self.par_entities_for_each_unchecked(world, f) };
1420    }
1421
1422    /// Iterates through all entity data that matches the query in parallel.
1423    /// Does not perform static borrow checking.
1424    ///
1425    /// # Safety
1426    ///
1427    /// The normal borrowing restrictions apply for the duration of the iteration:
1428    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1429    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1430    ///
1431    /// # Panics
1432    ///
1433    /// This function may panic if other code is concurrently accessing the same components.
1434    #[cfg(feature = "par-iter")]
1435    pub unsafe fn par_for_each_unchecked<'a, T, W>(&'a self, world: &'a W, f: T)
1436    where
1437        T: Fn(<<V as View<'a>>::Iter as Iterator>::Item) + Send + Sync,
1438        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1439        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1440        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1441        W: EntityStore,
1442    {
1443        self.par_for_each_chunk_unchecked(world, |mut chunk| {
1444            for data in chunk.iter_mut() {
1445                f(data);
1446            }
1447        });
1448    }
1449
1450    /// Iterates through all entity data that matches the query in parallel.
1451    #[cfg(feature = "par-iter")]
1452    pub fn par_for_each<'a, T, W>(&'a self, world: &'a W, f: T)
1453    where
1454        T: Fn(<<V as View<'a>>::Iter as Iterator>::Item) + Send + Sync,
1455        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1456        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1457        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1458        V: ReadOnly,
1459        W: EntityStore,
1460    {
1461        // safe because the view can only read data immutably
1462        unsafe { self.par_for_each_unchecked(world, f) };
1463    }
1464
1465    /// Iterates through all entity data that matches the query in parallel.
1466    #[cfg(feature = "par-iter")]
1467    pub fn par_for_each_mut<'a, T, W>(&'a self, world: &'a mut W, f: T)
1468    where
1469        T: Fn(<<V as View<'a>>::Iter as Iterator>::Item) + Send + Sync,
1470        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1471        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1472        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1473        W: EntityStore,
1474    {
1475        // safe because the &mut World ensures exclusivity
1476        unsafe { self.par_for_each_unchecked(world, f) };
1477    }
1478
1479    /// Iterates through all chunks that match the query in parallel.
1480    /// Does not perform static borrow checking.
1481    ///
1482    /// # Safety
1483    ///
1484    /// The normal borrowing restrictions apply for the duration of the iteration:
1485    /// * Components borrowed with `Read` access must not be borrowed mutably elsewhere.
1486    /// * Components borrowed with `Write` access must not be borrowed elsewhere at all.
1487    ///
1488    /// # Panics
1489    ///
1490    /// This function may panic if other code is concurrently accessing the same components.
1491    #[cfg(feature = "par-iter")]
1492    pub unsafe fn par_for_each_chunk_unchecked<'a, T, W>(&'a self, world: &'a W, f: T)
1493    where
1494        T: Fn(Chunk<'a, V>) + Send + Sync,
1495        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1496        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1497        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1498        W: EntityStore,
1499    {
1500        let par_iter = self.par_iter_chunks_unchecked(world);
1501        ParallelIterator::for_each(par_iter, |chunk| {
1502            f(chunk);
1503        });
1504    }
1505
1506    /// Iterates through all chunks that match the query in parallel.
1507    #[cfg(feature = "par-iter")]
1508    pub fn par_for_each_chunk<'a, T, W>(&'a self, world: &'a W, f: T)
1509    where
1510        T: Fn(Chunk<'a, V>) + Send + Sync,
1511        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1512        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1513        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1514        V: ReadOnly,
1515        W: EntityStore,
1516    {
1517        // safe because the view can only read data immutably
1518        unsafe { self.par_for_each_chunk_unchecked(world, f) };
1519    }
1520
1521    /// Iterates through all chunks that match the query in parallel.
1522    #[cfg(feature = "par-iter")]
1523    pub fn par_for_each_chunk_mut<'a, T, W>(&'a self, world: &'a mut W, f: T)
1524    where
1525        T: Fn(Chunk<'a, V>) + Send + Sync,
1526        <F::ArchetypeFilter as Filter<ArchetypeFilterData<'a>>>::Iter: FissileIterator,
1527        <F::ChunksetFilter as Filter<ChunksetFilterData<'a>>>::Iter: FissileIterator,
1528        <F::ChunkFilter as Filter<ChunkFilterData<'a>>>::Iter: FissileIterator,
1529        W: EntityStore,
1530    {
1531        // safe because the &mut World ensures exclusivity
1532        unsafe { self.par_for_each_chunk_unchecked(world, f) };
1533    }
1534}
1535
1536/// An iterator over all chunks that match a given query.
1537#[cfg(feature = "par-iter")]
1538pub struct ChunkViewParIter<'data, 'filter, V, FArch, FChunkset, FChunk>
1539where
1540    V: for<'a> View<'a>,
1541    FArch: Filter<ArchetypeFilterData<'data>>,
1542    FChunkset: Filter<ChunksetFilterData<'data>>,
1543    FChunk: Filter<ChunkFilterData<'data>>,
1544    FArch::Iter: FissileIterator,
1545    FChunkset::Iter: FissileIterator,
1546    FChunk::Iter: FissileIterator,
1547{
1548    _view: PhantomData<V>,
1549    storage: StorageAccessor<'data>,
1550    arch_filter: &'filter FArch,
1551    chunkset_filter: &'filter FChunkset,
1552    chunk_filter: &'filter FChunk,
1553    archetypes: FissileEnumerate<FArch::Iter>,
1554    set_frontier: Option<(
1555        &'data ArchetypeData,
1556        FissileEnumerate<FChunkset::Iter>,
1557        usize,
1558    )>,
1559    chunk_frontier: Option<(
1560        &'data ArchetypeData,
1561        SetIndex,
1562        FissileEnumerate<FChunk::Iter>,
1563        usize,
1564    )>,
1565}
1566
1567#[cfg(feature = "par-iter")]
1568impl<'data, 'filter, V, FArch, FChunkset, FChunk>
1569    ChunkViewParIter<'data, 'filter, V, FArch, FChunkset, FChunk>
1570where
1571    V: for<'a> View<'a>,
1572    FArch: Filter<ArchetypeFilterData<'data>>,
1573    FChunkset: Filter<ChunksetFilterData<'data>>,
1574    FChunk: Filter<ChunkFilterData<'data>>,
1575    FArch::Iter: FissileIterator,
1576    FChunkset::Iter: FissileIterator,
1577    FChunk::Iter: FissileIterator,
1578{
1579    fn next_set(&mut self) -> Option<(&'data ArchetypeData, SetIndex)> {
1580        loop {
1581            // if we are looping through an archetype, find the next set
1582            if let Some((ref arch, ref mut chunks, index_bound)) = self.set_frontier {
1583                for (set_index, filter_data) in chunks {
1584                    if set_index < index_bound
1585                        && self.chunkset_filter.is_match(&filter_data).is_pass()
1586                    {
1587                        return Some((arch, SetIndex(set_index)));
1588                    }
1589                }
1590            }
1591
1592            // we have completed the current set, find the next one
1593            loop {
1594                match self.archetypes.next() {
1595                    Some((arch_index, arch_data)) => {
1596                        if self.arch_filter.is_match(&arch_data).is_pass() {
1597                            // validate that we are allowed to access this archetype
1598                            if !self
1599                                .storage
1600                                .can_access_archetype(ArchetypeIndex(arch_index))
1601                            {
1602                                panic!(
1603                                    "query attempted to access archetype unavailable via sub world"
1604                                );
1605                            }
1606                            // we have found another set
1607                            self.set_frontier = {
1608                                let arch = unsafe {
1609                                    self.storage.inner().archetypes().get_unchecked(arch_index)
1610                                };
1611                                let data = ChunksetFilterData {
1612                                    archetype_data: arch,
1613                                };
1614
1615                                Some((
1616                                    arch,
1617                                    FissileEnumerate::new(self.chunkset_filter.collect(data)),
1618                                    arch.len(),
1619                                ))
1620                            };
1621                            break;
1622                        }
1623                    }
1624                    // there are no more sets
1625                    None => return None,
1626                }
1627            }
1628        }
1629    }
1630}
1631
1632#[cfg(feature = "par-iter")]
1633impl<'data, 'filter, V, FArch, FChunkset, FChunk> Iterator
1634    for ChunkViewParIter<'data, 'filter, V, FArch, FChunkset, FChunk>
1635where
1636    V: for<'a> View<'a>,
1637    FArch: Filter<ArchetypeFilterData<'data>>,
1638    FChunkset: Filter<ChunksetFilterData<'data>>,
1639    FChunk: Filter<ChunkFilterData<'data>>,
1640    FArch::Iter: FissileIterator,
1641    FChunkset::Iter: FissileIterator,
1642    FChunk::Iter: FissileIterator,
1643{
1644    type Item = Chunk<'data, V>;
1645
1646    fn next(&mut self) -> Option<Self::Item> {
1647        loop {
1648            // if we are looping through a set, then yield the next chunk
1649            if let Some((ref arch, set_index, ref mut set, index_bound)) = self.chunk_frontier {
1650                for (chunk_index, filter_data) in set {
1651                    if chunk_index < index_bound
1652                        && self.chunk_filter.is_match(&filter_data).is_pass()
1653                    {
1654                        return Some(Chunk::new(arch, set_index, ChunkIndex(chunk_index)));
1655                    }
1656                }
1657            }
1658
1659            // we have completed the set, find the next
1660            if let Some((ref arch, set_index)) = self.next_set() {
1661                let chunks = unsafe { arch.chunkset_unchecked(set_index) }.occupied();
1662                self.chunk_frontier = Some((
1663                    arch,
1664                    set_index,
1665                    FissileEnumerate::new(self.chunk_filter.collect(ChunkFilterData { chunks })),
1666                    chunks.len(),
1667                ))
1668            } else {
1669                return None;
1670            }
1671        }
1672    }
1673}
1674
1675#[cfg(feature = "par-iter")]
1676impl<'data, 'filter, V, FArch, FChunkset, FChunk> ParallelIterator
1677    for ChunkViewParIter<'data, 'filter, V, FArch, FChunkset, FChunk>
1678where
1679    V: for<'a> View<'a>,
1680    FArch: Filter<ArchetypeFilterData<'data>>,
1681    FChunkset: Filter<ChunksetFilterData<'data>>,
1682    FChunk: Filter<ChunkFilterData<'data>>,
1683    FArch::Iter: FissileIterator,
1684    FChunkset::Iter: FissileIterator,
1685    FChunk::Iter: FissileIterator,
1686{
1687    type Item = Chunk<'data, V>;
1688
1689    fn drive_unindexed<C>(self, consumer: C) -> C::Result
1690    where
1691        C: UnindexedConsumer<Self::Item>,
1692    {
1693        bridge_unindexed(self, consumer)
1694    }
1695}
1696
1697#[cfg(feature = "par-iter")]
1698impl<'data, 'filter, V, FArch, FChunkset, FChunk> UnindexedProducer
1699    for ChunkViewParIter<'data, 'filter, V, FArch, FChunkset, FChunk>
1700where
1701    V: for<'a> View<'a>,
1702    FArch: Filter<ArchetypeFilterData<'data>>,
1703    FChunkset: Filter<ChunksetFilterData<'data>>,
1704    FChunk: Filter<ChunkFilterData<'data>>,
1705    FArch::Iter: FissileIterator,
1706    FChunkset::Iter: FissileIterator,
1707    FChunk::Iter: FissileIterator,
1708{
1709    type Item = Chunk<'data, V>;
1710
1711    fn split(self) -> (Self, Option<Self>) {
1712        let Self {
1713            _view,
1714            storage,
1715            arch_filter,
1716            chunkset_filter,
1717            chunk_filter,
1718            archetypes,
1719            set_frontier,
1720            chunk_frontier,
1721        } = self;
1722
1723        let (left_archetypes, right_archetypes, arch_size) = archetypes.split();
1724
1725        let (left_set, right_set, set_size) = if let Some((data, iter, bound)) = set_frontier {
1726            let (left_iter, right_iter, iter_size) = iter.split();
1727            (
1728                Some((data, left_iter, bound)),
1729                Some((data, right_iter, bound)),
1730                iter_size,
1731            )
1732        } else {
1733            (None, None, 0)
1734        };
1735
1736        let (left_chunk, right_chunk, chunk_size) =
1737            if let Some((data, idx, iter, bound)) = chunk_frontier {
1738                let (left_iter, right_iter, iter_size) = iter.split();
1739                (
1740                    Some((data, idx, left_iter, bound)),
1741                    Some((data, idx, right_iter, bound)),
1742                    iter_size,
1743                )
1744            } else {
1745                (None, None, 0)
1746            };
1747
1748        let right_split = Self {
1749            _view,
1750            storage: storage.clone(),
1751            arch_filter,
1752            chunkset_filter,
1753            chunk_filter,
1754            archetypes: right_archetypes,
1755            set_frontier: right_set,
1756            chunk_frontier: right_chunk,
1757        };
1758
1759        if arch_size + set_size + chunk_size == 0 {
1760            (right_split, None)
1761        } else {
1762            (
1763                Self {
1764                    _view,
1765                    storage,
1766                    arch_filter,
1767                    chunkset_filter,
1768                    chunk_filter,
1769                    archetypes: left_archetypes,
1770                    set_frontier: left_set,
1771                    chunk_frontier: left_chunk,
1772                },
1773                Some(right_split),
1774            )
1775        }
1776    }
1777    fn fold_with<F>(self, folder: F) -> F
1778    where
1779        F: Folder<Self::Item>,
1780    {
1781        folder.consume_iter(self)
1782    }
1783}