Skip to main content

gloss_hecs/
query.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8// use core::any::StableTypeId;
9use crate::stabletypeid::StableTypeId;
10use core::{
11    marker::PhantomData,
12    mem,
13    ops::{Deref, DerefMut},
14    ptr::NonNull,
15    slice::Iter as SliceIter,
16};
17
18use crate::{
19    alloc::{boxed::Box, vec::Vec},
20    archetype::Archetype,
21    entities::EntityMeta,
22    Component, Entity, World,
23};
24
25/// A collection of component types to fetch from a [`World`](crate::World)
26///
27/// The interface of this trait is a private implementation detail.
28pub trait Query {
29    #[doc(hidden)]
30    type Fetch: for<'a> Fetch<'a>;
31}
32
33/// Marker trait indicating whether a given [`Query`] will not produce unique
34/// references
35#[allow(clippy::missing_safety_doc)]
36pub unsafe trait QueryShared {}
37
38/// Type of values yielded by a query
39///
40/// Once rust offers generic associated types, this will be moved into
41/// [`Query`].
42pub type QueryItem<'a, Q> = <<Q as Query>::Fetch as Fetch<'a>>::Item;
43
44/// Streaming iterators over contiguous homogeneous ranges of components
45#[allow(clippy::missing_safety_doc)]
46pub unsafe trait Fetch<'a>: Sized {
47    /// Type of value to be fetched
48    type Item;
49
50    /// The type of the data which can be cached to speed up retrieving
51    /// the relevant type states from a matching [`Archetype`]
52    type State: Copy;
53
54    /// A value on which `get` may never be called
55    fn dangling() -> Self;
56
57    /// How this query will access `archetype`, if at all
58    fn access(archetype: &Archetype) -> Option<Access>;
59
60    /// Acquire dynamic borrows from `archetype`
61    fn borrow(archetype: &Archetype, state: Self::State);
62    /// Look up state for `archetype` if it should be traversed
63    fn prepare(archetype: &Archetype) -> Option<Self::State>;
64    /// Construct a `Fetch` for `archetype` based on the associated state
65    fn execute(archetype: &'a Archetype, state: Self::State) -> Self;
66    /// Release dynamic borrows acquired by `borrow`
67    fn release(archetype: &Archetype, state: Self::State);
68
69    /// Invoke `f` for every component type that may be borrowed and whether the
70    /// borrow is unique
71    fn for_each_borrow(f: impl FnMut(StableTypeId, bool));
72
73    /// Access the `n`th item in this archetype without bounds checking
74    ///
75    /// # Safety
76    /// - Must only be called after `borrow`
77    /// - `release` must not be called while `'a` is still live
78    /// - Bounds-checking must be performed externally
79    /// - Any resulting borrows must be legal (e.g. no &mut to something another
80    ///   iterator might access)
81    unsafe fn get(&self, n: usize) -> Self::Item;
82}
83
84/// Type of access a [`Query`] may have to an [`Archetype`]
85#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
86pub enum Access {
87    /// Read entity IDs only, no components
88    Iterate,
89    /// Read components
90    Read,
91    /// Read and write components
92    Write,
93}
94
95impl<T: Component> Query for &T {
96    type Fetch = FetchRead<T>;
97}
98
99unsafe impl<T> QueryShared for &T {}
100
101#[doc(hidden)]
102pub struct FetchRead<T>(NonNull<T>);
103
104unsafe impl<'a, T: Component> Fetch<'a> for FetchRead<T> {
105    type Item = &'a T;
106
107    type State = usize;
108
109    fn dangling() -> Self {
110        Self(NonNull::dangling())
111    }
112
113    fn access(archetype: &Archetype) -> Option<Access> {
114        if archetype.has::<T>() {
115            Some(Access::Read)
116        } else {
117            None
118        }
119    }
120
121    fn borrow(archetype: &Archetype, state: Self::State) {
122        archetype.borrow::<T>(state);
123    }
124    fn prepare(archetype: &Archetype) -> Option<Self::State> {
125        archetype.get_state::<T>()
126    }
127    fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
128        Self(archetype.get_base(state))
129    }
130    fn release(archetype: &Archetype, state: Self::State) {
131        archetype.release::<T>(state);
132    }
133
134    fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
135        f(StableTypeId::of::<T>(), false);
136    }
137
138    unsafe fn get(&self, n: usize) -> Self::Item {
139        &*self.0.as_ptr().add(n)
140    }
141}
142
143/// Unique borrow of an entity's component
144pub struct Mut<'a, T: Component> {
145    pub(crate) value: &'a mut T,
146    pub(crate) mutated: &'a mut bool,
147}
148
149impl<'a, T: Component> Mut<'a, T> {
150    /// Creates a new mutable reference to a component. This is unsafe because
151    /// the index bounds are not checked.
152    ///
153    /// # Safety
154    /// This doesn't check the bounds of index in archetype
155    pub unsafe fn new(value: &'a mut T, mutated: &'a mut bool) -> Self {
156        Mut { value, mutated }
157    }
158}
159
160unsafe impl<T: Component> Send for Mut<'_, T> {}
161unsafe impl<T: Component> Sync for Mut<'_, T> {}
162
163impl<T: Component> Deref for Mut<'_, T> {
164    type Target = T;
165
166    #[inline]
167    fn deref(&self) -> &T {
168        self.value
169    }
170}
171
172impl<T: Component> DerefMut for Mut<'_, T> {
173    #[inline]
174    fn deref_mut(&mut self) -> &mut T {
175        *self.mutated = true;
176        self.value
177    }
178}
179
180impl<T: Component + core::fmt::Debug> core::fmt::Debug for Mut<'_, T> {
181    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
182        self.value.fmt(f)
183    }
184}
185
186impl<T: Component> Query for &mut T {
187    type Fetch = FetchWrite<T>;
188}
189
190#[doc(hidden)]
191pub struct FetchWrite<T>(NonNull<T>, NonNull<bool>);
192
193unsafe impl<'a, T: Component> Fetch<'a> for FetchWrite<T> {
194    type Item = Mut<'a, T>;
195
196    type State = usize;
197
198    fn dangling() -> Self {
199        Self(NonNull::dangling(), NonNull::dangling())
200    }
201
202    fn access(archetype: &Archetype) -> Option<Access> {
203        if archetype.has::<T>() {
204            Some(Access::Write)
205        } else {
206            None
207        }
208    }
209
210    fn borrow(archetype: &Archetype, state: Self::State) {
211        archetype.borrow_mut::<T>(state);
212    }
213    #[allow(clippy::needless_question_mark)]
214    fn prepare(archetype: &Archetype) -> Option<Self::State> {
215        Some(archetype.get_state::<T>()?)
216    }
217    fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
218        Self(archetype.get_base::<T>(state), archetype.get_mutated(state))
219    }
220    fn release(archetype: &Archetype, state: Self::State) {
221        archetype.release_mut::<T>(state);
222    }
223
224    fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
225        f(StableTypeId::of::<T>(), true);
226    }
227
228    unsafe fn get(&self, n: usize) -> Self::Item {
229        Mut::new(&mut *self.0.as_ptr().add(n), &mut *self.1.as_ptr().add(n))
230    }
231}
232
233impl<T: Query> Query for Option<T> {
234    type Fetch = TryFetch<T::Fetch>;
235}
236
237unsafe impl<T: QueryShared> QueryShared for Option<T> {}
238
239#[doc(hidden)]
240pub struct TryFetch<T>(Option<T>);
241
242unsafe impl<'a, T: Fetch<'a>> Fetch<'a> for TryFetch<T> {
243    type Item = Option<T::Item>;
244
245    type State = Option<T::State>;
246
247    fn dangling() -> Self {
248        Self(None)
249    }
250
251    fn access(archetype: &Archetype) -> Option<Access> {
252        Some(T::access(archetype).unwrap_or(Access::Iterate))
253    }
254
255    fn borrow(archetype: &Archetype, state: Self::State) {
256        if let Some(state) = state {
257            T::borrow(archetype, state);
258        }
259    }
260    fn prepare(archetype: &Archetype) -> Option<Self::State> {
261        Some(T::prepare(archetype))
262    }
263    fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
264        Self(state.map(|state| T::execute(archetype, state)))
265    }
266    fn release(archetype: &Archetype, state: Self::State) {
267        if let Some(state) = state {
268            T::release(archetype, state);
269        }
270    }
271
272    fn for_each_borrow(f: impl FnMut(StableTypeId, bool)) {
273        T::for_each_borrow(f);
274    }
275
276    unsafe fn get(&self, n: usize) -> Option<T::Item> {
277        Some(self.0.as_ref()?.get(n))
278    }
279}
280
281/// Holds an `L`, or an `R`, or both
282#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
283pub enum Or<L, R> {
284    /// Just an `L`
285    Left(L),
286    /// Just an `R`
287    Right(R),
288    /// Both an `L` and an `R`
289    Both(L, R),
290}
291
292impl<L, R> Or<L, R> {
293    /// Construct an `Or<L, R>` if at least one argument is `Some`
294    pub fn new(l: Option<L>, r: Option<R>) -> Option<Self> {
295        match (l, r) {
296            (None, None) => None,
297            (Some(l), None) => Some(Or::Left(l)),
298            (None, Some(r)) => Some(Or::Right(r)),
299            (Some(l), Some(r)) => Some(Or::Both(l, r)),
300        }
301    }
302
303    /// Destructure into two `Option`s, where either or both are `Some`
304    pub fn split(self) -> (Option<L>, Option<R>) {
305        match self {
306            Or::Left(l) => (Some(l), None),
307            Or::Right(r) => (None, Some(r)),
308            Or::Both(l, r) => (Some(l), Some(r)),
309        }
310    }
311
312    /// Extract `L` regardless of whether `R` is present
313    #[allow(clippy::match_wildcard_for_single_variants)]
314    pub fn left(self) -> Option<L> {
315        match self {
316            // Or::Left(l) => Some(l),
317            Or::Both(l, _) | Or::Left(l) => Some(l),
318            _ => None,
319        }
320    }
321
322    /// Extract `R` regardless of whether `L` is present
323    #[allow(clippy::match_wildcard_for_single_variants)]
324    pub fn right(self) -> Option<R> {
325        match self {
326            // Or::Right(r) => Some(r),
327            Or::Both(_, r) | Or::Right(r) => Some(r),
328            _ => None,
329        }
330    }
331
332    /// Transform `L` with `f` and `R` with `g`
333    pub fn map<L1, R1, F, G>(self, f: F, g: G) -> Or<L1, R1>
334    where
335        F: FnOnce(L) -> L1,
336        G: FnOnce(R) -> R1,
337    {
338        match self {
339            Or::Left(l) => Or::Left(f(l)),
340            Or::Right(r) => Or::Right(g(r)),
341            Or::Both(l, r) => Or::Both(f(l), g(r)),
342        }
343    }
344
345    /// Convert from `&Or<L, R>` to `Or<&L, &R>`
346    pub fn as_ref(&self) -> Or<&L, &R> {
347        match *self {
348            Or::Left(ref l) => Or::Left(l),
349            Or::Right(ref r) => Or::Right(r),
350            Or::Both(ref l, ref r) => Or::Both(l, r),
351        }
352    }
353
354    /// Convert from `&mut Or<L, R>` to `Or<&mut L, &mut R>`
355    pub fn as_mut(&mut self) -> Or<&mut L, &mut R> {
356        match *self {
357            Or::Left(ref mut l) => Or::Left(l),
358            Or::Right(ref mut r) => Or::Right(r),
359            Or::Both(ref mut l, ref mut r) => Or::Both(l, r),
360        }
361    }
362}
363
364impl<L, R> Or<&'_ L, &'_ R>
365where
366    L: Clone,
367    R: Clone,
368{
369    /// Maps an `Or<&L, &R>` to an `Or<L, R>` by cloning its contents
370    pub fn cloned(self) -> Or<L, R> {
371        self.map(Clone::clone, Clone::clone)
372    }
373}
374
375impl<L: Query, R: Query> Query for Or<L, R> {
376    type Fetch = FetchOr<L::Fetch, R::Fetch>;
377}
378
379unsafe impl<L: QueryShared, R: QueryShared> QueryShared for Or<L, R> {}
380
381#[doc(hidden)]
382pub struct FetchOr<L, R>(Or<L, R>);
383
384unsafe impl<'a, L: Fetch<'a>, R: Fetch<'a>> Fetch<'a> for FetchOr<L, R> {
385    type Item = Or<L::Item, R::Item>;
386
387    type State = Or<L::State, R::State>;
388
389    fn dangling() -> Self {
390        Self(Or::Left(L::dangling()))
391    }
392
393    fn access(archetype: &Archetype) -> Option<Access> {
394        L::access(archetype).max(R::access(archetype))
395    }
396
397    fn borrow(archetype: &Archetype, state: Self::State) {
398        state.map(|l| L::borrow(archetype, l), |r| R::borrow(archetype, r));
399    }
400
401    fn prepare(archetype: &Archetype) -> Option<Self::State> {
402        Or::new(L::prepare(archetype), R::prepare(archetype))
403    }
404
405    fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
406        Self(state.map(|l| L::execute(archetype, l), |r| R::execute(archetype, r)))
407    }
408
409    fn release(archetype: &Archetype, state: Self::State) {
410        state.map(|l| L::release(archetype, l), |r| R::release(archetype, r));
411    }
412
413    fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
414        L::for_each_borrow(&mut f);
415        R::for_each_borrow(&mut f);
416    }
417
418    unsafe fn get(&self, n: usize) -> Self::Item {
419        self.0.as_ref().map(|l| l.get(n), |r| r.get(n))
420    }
421}
422
423/// Transforms query `Q` by skipping entities satisfying query `R`
424///
425/// See also `QueryBorrow::without`.
426///
427/// # Example
428/// ```
429/// # use gloss_hecs::*;
430/// let mut world = World::new();
431/// let a = world.spawn((123, true, "abc"));
432/// let b = world.spawn((456, false));
433/// let c = world.spawn((42, "def"));
434/// let entities = world
435///     .query::<Without<&i32, &bool>>()
436///     .iter()
437///     .map(|(e, &i)| (e, i))
438///     .collect::<Vec<_>>();
439/// assert_eq!(entities, &[(c, 42)]);
440/// ```
441pub struct Without<Q, R>(PhantomData<(Q, fn(R))>);
442
443impl<Q: Query, R: Query> Query for Without<Q, R> {
444    type Fetch = FetchWithout<Q::Fetch, R::Fetch>;
445}
446
447unsafe impl<Q: QueryShared, R> QueryShared for Without<Q, R> {}
448
449#[doc(hidden)]
450pub struct FetchWithout<F, G>(F, PhantomData<fn(G)>);
451
452unsafe impl<'a, F: Fetch<'a>, G: Fetch<'a>> Fetch<'a> for FetchWithout<F, G> {
453    type Item = F::Item;
454
455    type State = F::State;
456
457    fn dangling() -> Self {
458        Self(F::dangling(), PhantomData)
459    }
460
461    fn access(archetype: &Archetype) -> Option<Access> {
462        if G::access(archetype).is_some() {
463            None
464        } else {
465            F::access(archetype)
466        }
467    }
468
469    fn borrow(archetype: &Archetype, state: Self::State) {
470        F::borrow(archetype, state);
471    }
472    fn prepare(archetype: &Archetype) -> Option<Self::State> {
473        if G::access(archetype).is_some() {
474            return None;
475        }
476        F::prepare(archetype)
477    }
478    fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
479        Self(F::execute(archetype, state), PhantomData)
480    }
481    fn release(archetype: &Archetype, state: Self::State) {
482        F::release(archetype, state);
483    }
484
485    fn for_each_borrow(f: impl FnMut(StableTypeId, bool)) {
486        F::for_each_borrow(f);
487    }
488
489    unsafe fn get(&self, n: usize) -> F::Item {
490        self.0.get(n)
491    }
492}
493
494/// Transforms query `Q` by skipping entities not satisfying query `R`
495///
496/// See also `QueryBorrow::with`.
497///
498/// # Example
499/// ```
500/// # use gloss_hecs::*;
501/// let mut world = World::new();
502/// let a = world.spawn((123, true, "abc"));
503/// let b = world.spawn((456, false));
504/// let c = world.spawn((42, "def"));
505/// let entities = world
506///     .query::<With<&i32, &bool>>()
507///     .iter()
508///     .map(|(e, &i)| (e, i))
509///     .collect::<Vec<_>>();
510/// assert_eq!(entities.len(), 2);
511/// assert!(entities.contains(&(a, 123)));
512/// assert!(entities.contains(&(b, 456)));
513/// ```
514pub struct With<Q, R>(PhantomData<(Q, fn(R))>);
515
516impl<Q: Query, R: Query> Query for With<Q, R> {
517    type Fetch = FetchWith<Q::Fetch, R::Fetch>;
518}
519
520unsafe impl<Q: QueryShared, R> QueryShared for With<Q, R> {}
521
522#[doc(hidden)]
523pub struct FetchWith<F, G>(F, PhantomData<fn(G)>);
524
525unsafe impl<'a, F: Fetch<'a>, G: Fetch<'a>> Fetch<'a> for FetchWith<F, G> {
526    type Item = F::Item;
527
528    type State = F::State;
529
530    fn dangling() -> Self {
531        Self(F::dangling(), PhantomData)
532    }
533
534    fn access(archetype: &Archetype) -> Option<Access> {
535        if G::access(archetype).is_some() {
536            F::access(archetype)
537        } else {
538            None
539        }
540    }
541
542    fn borrow(archetype: &Archetype, state: Self::State) {
543        F::borrow(archetype, state);
544    }
545    fn prepare(archetype: &Archetype) -> Option<Self::State> {
546        G::access(archetype)?;
547        F::prepare(archetype)
548    }
549    fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
550        Self(F::execute(archetype, state), PhantomData)
551    }
552    fn release(archetype: &Archetype, state: Self::State) {
553        F::release(archetype, state);
554    }
555
556    fn for_each_borrow(f: impl FnMut(StableTypeId, bool)) {
557        F::for_each_borrow(f);
558    }
559
560    unsafe fn get(&self, n: usize) -> F::Item {
561        self.0.get(n)
562    }
563}
564
565/// A query that matches all entities, yielding `bool`s indicating whether each
566/// satisfies query `Q`
567///
568/// Does not borrow any components, making it faster and more
569/// concurrency-friendly than `Option<Q>`.
570///
571/// # Example
572/// ```
573/// # use gloss_hecs::*;
574/// let mut world = World::new();
575/// let a = world.spawn((123, true, "abc"));
576/// let b = world.spawn((456, false));
577/// let c = world.spawn((42, "def"));
578/// let entities = world
579///     .query::<Satisfies<&bool>>()
580///     .iter()
581///     .map(|(e, x)| (e, x))
582///     .collect::<Vec<_>>();
583/// assert_eq!(entities.len(), 3);
584/// assert!(entities.contains(&(a, true)));
585/// assert!(entities.contains(&(b, true)));
586/// assert!(entities.contains(&(c, false)));
587/// ```
588pub struct Satisfies<Q>(PhantomData<Q>);
589
590impl<Q: Query> Query for Satisfies<Q> {
591    type Fetch = FetchSatisfies<Q::Fetch>;
592}
593
594unsafe impl<Q> QueryShared for Satisfies<Q> {}
595
596#[doc(hidden)]
597pub struct FetchSatisfies<F>(bool, PhantomData<F>);
598
599unsafe impl<'a, F: Fetch<'a>> Fetch<'a> for FetchSatisfies<F> {
600    type Item = bool;
601
602    type State = bool;
603
604    fn dangling() -> Self {
605        Self(false, PhantomData)
606    }
607
608    fn access(_archetype: &Archetype) -> Option<Access> {
609        Some(Access::Iterate)
610    }
611
612    fn borrow(_archetype: &Archetype, _state: Self::State) {}
613    fn prepare(archetype: &Archetype) -> Option<Self::State> {
614        Some(F::prepare(archetype).is_some())
615    }
616    fn execute(_archetype: &'a Archetype, state: Self::State) -> Self {
617        Self(state, PhantomData)
618    }
619    fn release(_archetype: &Archetype, _state: Self::State) {}
620
621    fn for_each_borrow(_: impl FnMut(StableTypeId, bool)) {}
622
623    unsafe fn get(&self, _: usize) -> bool {
624        self.0
625    }
626}
627
628/// A borrow of a [`World`](crate::World) sufficient to execute the query `Q`
629///
630/// Note that borrows are not released until this object is dropped.
631pub struct QueryBorrow<'w, Q: Query> {
632    meta: &'w [EntityMeta],
633    archetypes: &'w [Archetype],
634    borrowed: bool,
635    _marker: PhantomData<Q>,
636}
637
638impl<'w, Q: Query> QueryBorrow<'w, Q> {
639    pub(crate) fn new(meta: &'w [EntityMeta], archetypes: &'w [Archetype]) -> Self {
640        Self {
641            meta,
642            archetypes,
643            borrowed: false,
644            _marker: PhantomData,
645        }
646    }
647
648    /// Execute the query
649    // The lifetime narrowing here is required for soundness.
650    pub fn iter(&mut self) -> QueryIter<'_, Q> {
651        self.borrow();
652        unsafe { QueryIter::new(self.meta, self.archetypes.iter()) }
653    }
654
655    /// Provide random access to the query results
656    pub fn view(&mut self) -> View<'_, Q> {
657        self.borrow();
658        unsafe { View::new(self.meta, self.archetypes) }
659    }
660
661    /// Like `iter`, but returns child iterators of at most `batch_size`
662    /// elements
663    ///
664    /// Useful for distributing work over a threadpool.
665    // The lifetime narrowing here is required for soundness.
666    pub fn iter_batched(&mut self, batch_size: u32) -> BatchedIter<'_, Q> {
667        self.borrow();
668        unsafe { BatchedIter::new(self.meta, self.archetypes.iter(), batch_size) }
669    }
670
671    fn borrow(&mut self) {
672        if self.borrowed {
673            return;
674        }
675        for x in self.archetypes {
676            if x.is_empty() {
677                continue;
678            }
679            // TODO: Release prior borrows on failure?
680            if let Some(state) = Q::Fetch::prepare(x) {
681                Q::Fetch::borrow(x, state);
682            }
683        }
684        self.borrowed = true;
685    }
686
687    /// Transform the query into one that requires another query be satisfied
688    ///
689    /// Convenient when the values of the components in the other query are not
690    /// of interest.
691    ///
692    /// Equivalent to using a query type wrapped in `With`.
693    ///
694    /// # Example
695    /// ```
696    /// # use gloss_hecs::*;
697    /// let mut world = World::new();
698    /// let a = world.spawn((123, true, "abc"));
699    /// let b = world.spawn((456, false));
700    /// let c = world.spawn((42, "def"));
701    /// let entities = world
702    ///     .query::<&i32>()
703    ///     .with::<&bool>()
704    ///     .iter()
705    ///     .map(|(e, &i)| (e, i)) // Copy out of the world
706    ///     .collect::<Vec<_>>();
707    /// assert_eq!(entities.len(), 2);
708    /// assert!(entities.contains(&(a, 123)));
709    /// assert!(entities.contains(&(b, 456)));
710    /// ```
711    pub fn with<R: Query>(self) -> QueryBorrow<'w, With<Q, R>> {
712        self.transform()
713    }
714
715    /// Transform the query into one that skips entities satisfying another
716    ///
717    /// Equivalent to using a query type wrapped in `Without`.
718    ///
719    /// # Example
720    /// ```
721    /// # use gloss_hecs::*;
722    /// let mut world = World::new();
723    /// let a = world.spawn((123, true, "abc"));
724    /// let b = world.spawn((456, false));
725    /// let c = world.spawn((42, "def"));
726    /// let entities = world
727    ///     .query::<&i32>()
728    ///     .without::<&bool>()
729    ///     .iter()
730    ///     .map(|(e, &i)| (e, i)) // Copy out of the world
731    ///     .collect::<Vec<_>>();
732    /// assert_eq!(entities, &[(c, 42)]);
733    /// ```
734    pub fn without<R: Query>(self) -> QueryBorrow<'w, Without<Q, R>> {
735        self.transform()
736    }
737
738    /// Helper to change the type of the query
739    fn transform<R: Query>(mut self) -> QueryBorrow<'w, R> {
740        let x = QueryBorrow {
741            meta: self.meta,
742            archetypes: self.archetypes,
743            borrowed: self.borrowed,
744            _marker: PhantomData,
745        };
746        // Ensure `Drop` won't fire redundantly
747        self.borrowed = false;
748        x
749    }
750}
751
752unsafe impl<'w, Q: Query> Send for QueryBorrow<'w, Q> where <Q::Fetch as Fetch<'w>>::Item: Send {}
753unsafe impl<'w, Q: Query> Sync for QueryBorrow<'w, Q> where <Q::Fetch as Fetch<'w>>::Item: Send {}
754
755impl<Q: Query> Drop for QueryBorrow<'_, Q> {
756    fn drop(&mut self) {
757        if self.borrowed {
758            for x in self.archetypes {
759                if x.is_empty() {
760                    continue;
761                }
762                if let Some(state) = Q::Fetch::prepare(x) {
763                    Q::Fetch::release(x, state);
764                }
765            }
766        }
767    }
768}
769
770#[allow(clippy::into_iter_without_iter)]
771impl<'q, Q: Query> IntoIterator for &'q mut QueryBorrow<'_, Q> {
772    type Item = (Entity, QueryItem<'q, Q>);
773    type IntoIter = QueryIter<'q, Q>;
774
775    fn into_iter(self) -> Self::IntoIter {
776        self.iter()
777    }
778}
779
780/// Iterator over the set of entities with the components in `Q`
781pub struct QueryIter<'q, Q: Query> {
782    meta: &'q [EntityMeta],
783    archetypes: SliceIter<'q, Archetype>,
784    iter: ChunkIter<Q>,
785}
786
787impl<'q, Q: Query> QueryIter<'q, Q> {
788    /// # Safety
789    ///
790    /// `'q` must be sufficient to guarantee that `Q` cannot violate borrow
791    /// safety, either with dynamic borrow checks or by representing
792    /// exclusive access to the `World`.
793    unsafe fn new(meta: &'q [EntityMeta], archetypes: SliceIter<'q, Archetype>) -> Self {
794        Self {
795            meta,
796            archetypes,
797            iter: ChunkIter::empty(),
798        }
799    }
800}
801
802unsafe impl<'q, Q: Query> Send for QueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
803unsafe impl<'q, Q: Query> Sync for QueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
804
805#[allow(clippy::inline_always)]
806impl<'q, Q: Query> Iterator for QueryIter<'q, Q> {
807    type Item = (Entity, QueryItem<'q, Q>);
808
809    #[inline(always)]
810    fn next(&mut self) -> Option<Self::Item> {
811        loop {
812            match unsafe { self.iter.next() } {
813                None => {
814                    let archetype = self.archetypes.next()?;
815                    let state = Q::Fetch::prepare(archetype);
816                    let fetch = state.map(|state| Q::Fetch::execute(archetype, state));
817                    self.iter = fetch.map_or(ChunkIter::empty(), |fetch| ChunkIter {
818                        entities: archetype.entities(),
819                        fetch,
820                        position: 0,
821                        len: archetype.len() as usize,
822                    });
823                    continue;
824                }
825                Some((id, components)) => {
826                    return Some((
827                        Entity {
828                            id,
829                            generation: unsafe { self.meta.get_unchecked(id as usize).generation },
830                        },
831                        components,
832                    ));
833                }
834            }
835        }
836    }
837
838    fn size_hint(&self) -> (usize, Option<usize>) {
839        let n = self.len();
840        (n, Some(n))
841    }
842}
843
844impl<Q: Query> ExactSizeIterator for QueryIter<'_, Q> {
845    fn len(&self) -> usize {
846        self.archetypes
847            .clone()
848            .filter(|&x| Q::Fetch::access(x).is_some())
849            .map(|x| x.len() as usize)
850            .sum::<usize>()
851            + self.iter.remaining()
852    }
853}
854
855/// A query builder that's convertible directly into an iterator
856pub struct QueryMut<'q, Q: Query> {
857    iter: QueryIter<'q, Q>,
858}
859
860impl<'q, Q: Query> QueryMut<'q, Q> {
861    pub(crate) fn new(meta: &'q [EntityMeta], archetypes: &'q mut [Archetype]) -> Self {
862        assert_borrow::<Q>();
863
864        Self {
865            iter: unsafe { QueryIter::new(meta, archetypes.iter()) },
866        }
867    }
868
869    /// Provide random access to the query results
870    pub fn view(&mut self) -> View<'_, Q> {
871        unsafe { View::new(self.iter.meta, self.iter.archetypes.as_slice()) }
872    }
873
874    /// Transform the query into one that requires another query be satisfied
875    ///
876    /// See `QueryBorrow::with`
877    pub fn with<R: Query>(self) -> QueryMut<'q, With<Q, R>> {
878        self.transform()
879    }
880
881    /// Transform the query into one that skips entities satisfying another
882    ///
883    /// See `QueryBorrow::without`
884    pub fn without<R: Query>(self) -> QueryMut<'q, Without<Q, R>> {
885        self.transform()
886    }
887
888    /// Helper to change the type of the query
889    fn transform<R: Query>(self) -> QueryMut<'q, R> {
890        QueryMut {
891            iter: unsafe { QueryIter::new(self.iter.meta, self.iter.archetypes) },
892        }
893    }
894
895    /// Like `into_iter`, but returns child iterators of at most `batch_size`
896    /// elements
897    ///
898    /// Useful for distributing work over a threadpool.
899    pub fn into_iter_batched(self, batch_size: u32) -> BatchedIter<'q, Q> {
900        unsafe { BatchedIter::new(self.iter.meta, self.iter.archetypes, batch_size) }
901    }
902}
903
904impl<'q, Q: Query> IntoIterator for QueryMut<'q, Q> {
905    type Item = <QueryIter<'q, Q> as Iterator>::Item;
906    type IntoIter = QueryIter<'q, Q>;
907
908    #[inline]
909    fn into_iter(self) -> Self::IntoIter {
910        self.iter
911    }
912}
913
914pub(crate) fn assert_borrow<Q: Query>() {
915    // This looks like an ugly O(n^2) loop, but everything's constant after
916    // inlining, so in practice LLVM optimizes it out entirely.
917    let mut i = 0;
918    Q::Fetch::for_each_borrow(|a, unique| {
919        if unique {
920            let mut j = 0;
921            Q::Fetch::for_each_borrow(|b, _| {
922                if i != j {
923                    core::assert!(a != b, "query violates a unique borrow");
924                }
925                j += 1;
926            });
927        }
928        i += 1;
929    });
930}
931
932struct ChunkIter<Q: Query> {
933    entities: NonNull<u32>,
934    fetch: Q::Fetch,
935    position: usize,
936    len: usize,
937}
938
939impl<Q: Query> ChunkIter<Q> {
940    fn empty() -> Self {
941        Self {
942            entities: NonNull::dangling(),
943            fetch: Q::Fetch::dangling(),
944            position: 0,
945            len: 0,
946        }
947    }
948
949    #[inline]
950    unsafe fn next<'a>(&mut self) -> Option<(u32, <Q::Fetch as Fetch<'a>>::Item)> {
951        if self.position == self.len {
952            return None;
953        }
954        let entity = self.entities.as_ptr().add(self.position);
955        let item = self.fetch.get(self.position);
956        self.position += 1;
957        Some((*entity, item))
958    }
959
960    fn remaining(&self) -> usize {
961        self.len - self.position
962    }
963}
964
965/// Batched version of [`QueryIter`]
966pub struct BatchedIter<'q, Q: Query> {
967    _marker: PhantomData<&'q Q>,
968    meta: &'q [EntityMeta],
969    archetypes: SliceIter<'q, Archetype>,
970    batch_size: u32,
971    batch: u32,
972}
973
974impl<'q, Q: Query> BatchedIter<'q, Q> {
975    /// # Safety
976    ///
977    /// `'q` must be sufficient to guarantee that `Q` cannot violate borrow
978    /// safety, either with dynamic borrow checks or by representing
979    /// exclusive access to the `World`.
980    unsafe fn new(meta: &'q [EntityMeta], archetypes: SliceIter<'q, Archetype>, batch_size: u32) -> Self {
981        Self {
982            _marker: PhantomData,
983            meta,
984            archetypes,
985            batch_size,
986            batch: 0,
987        }
988    }
989}
990
991unsafe impl<'q, Q: Query> Send for BatchedIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
992unsafe impl<'q, Q: Query> Sync for BatchedIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
993
994impl<'q, Q: Query> Iterator for BatchedIter<'q, Q> {
995    type Item = Batch<'q, Q>;
996
997    fn next(&mut self) -> Option<Self::Item> {
998        loop {
999            let mut archetypes = self.archetypes.clone();
1000            let archetype = archetypes.next()?;
1001            let offset = self.batch_size * self.batch;
1002            if offset >= archetype.len() {
1003                self.archetypes = archetypes;
1004                self.batch = 0;
1005                continue;
1006            }
1007            let state = Q::Fetch::prepare(archetype);
1008            let fetch = state.map(|state| Q::Fetch::execute(archetype, state));
1009            if let Some(fetch) = fetch {
1010                self.batch += 1;
1011                return Some(Batch {
1012                    meta: self.meta,
1013                    state: ChunkIter {
1014                        entities: archetype.entities(),
1015                        fetch,
1016                        len: (offset + self.batch_size.min(archetype.len() - offset)) as usize,
1017                        position: offset as usize,
1018                    },
1019                });
1020            }
1021            self.archetypes = archetypes;
1022            debug_assert_eq!(self.batch, 0, "query fetch should always reject at the first batch or not at all");
1023            // continue;
1024        }
1025    }
1026}
1027
1028/// A sequence of entities yielded by [`BatchedIter`]
1029pub struct Batch<'q, Q: Query> {
1030    meta: &'q [EntityMeta],
1031    state: ChunkIter<Q>,
1032}
1033
1034impl<'q, Q: Query> Iterator for Batch<'q, Q> {
1035    type Item = (Entity, QueryItem<'q, Q>);
1036
1037    fn next(&mut self) -> Option<Self::Item> {
1038        let (id, components) = unsafe { self.state.next()? };
1039        Some((
1040            Entity {
1041                id,
1042                generation: self.meta[id as usize].generation,
1043            },
1044            components,
1045        ))
1046    }
1047}
1048
1049unsafe impl<'q, Q: Query> Send for Batch<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1050unsafe impl<'q, Q: Query> Sync for Batch<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1051
1052macro_rules! tuple_impl {
1053    ($($name: ident),*) => {
1054        unsafe impl<'a, $($name: Fetch<'a>),*> Fetch<'a> for ($($name,)*) {
1055            type Item = ($($name::Item,)*);
1056
1057            type State = ($($name::State,)*);
1058
1059            #[allow(clippy::unused_unit)]
1060            fn dangling() -> Self {
1061                ($($name::dangling(),)*)
1062            }
1063
1064            #[allow(unused_variables, unused_mut)]
1065            fn access(archetype: &Archetype) -> Option<Access> {
1066                let mut access = Access::Iterate;
1067                $(
1068                    access = access.max($name::access(archetype)?);
1069                )*
1070                Some(access)
1071            }
1072
1073            #[allow(unused_variables, non_snake_case, clippy::unused_unit)]
1074            fn borrow(archetype: &Archetype, state: Self::State) {
1075                let ($($name,)*) = state;
1076                $($name::borrow(archetype, $name);)*
1077            }
1078            #[allow(unused_variables)]
1079            fn prepare(archetype: &Archetype) -> Option<Self::State> {
1080                Some(($($name::prepare(archetype)?,)*))
1081            }
1082            #[allow(unused_variables, non_snake_case, clippy::unused_unit)]
1083            fn execute(archetype: &'a Archetype, state: Self::State) -> Self {
1084                let ($($name,)*) = state;
1085                ($($name::execute(archetype, $name),)*)
1086            }
1087            #[allow(unused_variables, non_snake_case, clippy::unused_unit)]
1088            fn release(archetype: &Archetype, state: Self::State) {
1089                let ($($name,)*) = state;
1090                $($name::release(archetype, $name);)*
1091            }
1092
1093            #[allow(unused_variables, unused_mut, clippy::unused_unit)]
1094            fn for_each_borrow(mut f: impl FnMut(StableTypeId, bool)) {
1095                $($name::for_each_borrow(&mut f);)*
1096            }
1097
1098            #[allow(unused_variables, clippy::unused_unit)]
1099            unsafe fn get(&self, n: usize) -> Self::Item {
1100                #[allow(non_snake_case)]
1101                let ($($name,)*) = self;
1102                ($($name.get(n),)*)
1103            }
1104        }
1105
1106        impl<$($name: Query),*> Query for ($($name,)*) {
1107            type Fetch = ($($name::Fetch,)*);
1108        }
1109
1110        unsafe impl<$($name: QueryShared),*> QueryShared for ($($name,)*) {}
1111    };
1112}
1113
1114//smaller_tuples_too!(tuple_impl, B, A);
1115smaller_tuples_too!(tuple_impl, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A);
1116
1117/// A prepared query can be stored independently of the [`World`] to amortize
1118/// query set-up costs.
1119pub struct PreparedQuery<Q: Query> {
1120    memo: (u64, u32),
1121    state: Box<[(usize, <Q::Fetch as Fetch<'static>>::State)]>,
1122    fetch: Box<[Option<Q::Fetch>]>,
1123}
1124
1125impl<Q: Query> Default for PreparedQuery<Q> {
1126    fn default() -> Self {
1127        Self::new()
1128    }
1129}
1130
1131impl<Q: Query> PreparedQuery<Q> {
1132    /// Create a prepared query which is not yet attached to any world
1133    pub fn new() -> Self {
1134        Self {
1135            // This memo will not match any world as the first ID will be 1.
1136            memo: (0, 0),
1137            state: Box::default(),
1138            fetch: Box::default(),
1139        }
1140    }
1141
1142    #[cold]
1143    fn prepare(world: &World) -> Self {
1144        let memo = world.memo();
1145
1146        let state = world
1147            .archetypes()
1148            .enumerate()
1149            .filter_map(|(idx, x)| Q::Fetch::prepare(x).map(|state| (idx, state)))
1150            .collect();
1151
1152        let fetch = world.archetypes().map(|_| None).collect();
1153
1154        Self { memo, state, fetch }
1155    }
1156
1157    /// Query `world`, using dynamic borrow checking
1158    ///
1159    /// This will panic if it would violate an existing unique reference
1160    /// or construct an invalid unique reference.
1161    pub fn query<'q>(&'q mut self, world: &'q World) -> PreparedQueryBorrow<'q, Q> {
1162        if self.memo != world.memo() {
1163            *self = Self::prepare(world);
1164        }
1165
1166        let meta = world.entities_meta();
1167        let archetypes = world.archetypes_inner();
1168
1169        PreparedQueryBorrow::new(meta, archetypes, &self.state, &mut self.fetch)
1170    }
1171
1172    /// Query a uniquely borrowed world
1173    ///
1174    /// Avoids the cost of the dynamic borrow checking performed by
1175    /// [`query`][Self::query].
1176    pub fn query_mut<'q>(&'q mut self, world: &'q mut World) -> PreparedQueryIter<'q, Q> {
1177        assert_borrow::<Q>();
1178
1179        if self.memo != world.memo() {
1180            *self = Self::prepare(world);
1181        }
1182
1183        let meta = world.entities_meta();
1184        let archetypes = world.archetypes_inner();
1185
1186        let state: &'q [(usize, <Q::Fetch as Fetch<'q>>::State)] = unsafe { mem::transmute(&*self.state) };
1187
1188        unsafe { PreparedQueryIter::new(meta, archetypes, state.iter()) }
1189    }
1190
1191    /// Provide random access to query results for a uniquely borrow world
1192    pub fn view_mut<'q>(&'q mut self, world: &'q mut World) -> PreparedView<'q, Q> {
1193        assert_borrow::<Q>();
1194
1195        if self.memo != world.memo() {
1196            *self = Self::prepare(world);
1197        }
1198
1199        let meta = world.entities_meta();
1200        let archetypes = world.archetypes_inner();
1201
1202        let state: &'q [(usize, <Q::Fetch as Fetch<'q>>::State)] = unsafe { mem::transmute(&*self.state) };
1203
1204        unsafe { PreparedView::new(meta, archetypes, state.iter(), &mut self.fetch) }
1205    }
1206}
1207
1208/// Combined borrow of a [`PreparedQuery`] and a [`World`]
1209pub struct PreparedQueryBorrow<'q, Q: Query> {
1210    meta: &'q [EntityMeta],
1211    archetypes: &'q [Archetype],
1212    state: &'q [(usize, <Q::Fetch as Fetch<'static>>::State)],
1213    fetch: &'q mut [Option<Q::Fetch>],
1214}
1215
1216impl<'q, Q: Query> PreparedQueryBorrow<'q, Q> {
1217    fn new(
1218        meta: &'q [EntityMeta],
1219        archetypes: &'q [Archetype],
1220        state: &'q [(usize, <Q::Fetch as Fetch<'static>>::State)],
1221        fetch: &'q mut [Option<Q::Fetch>],
1222    ) -> Self {
1223        for (idx, state) in state {
1224            if archetypes[*idx].is_empty() {
1225                continue;
1226            }
1227            Q::Fetch::borrow(&archetypes[*idx], *state);
1228        }
1229
1230        Self {
1231            meta,
1232            archetypes,
1233            state,
1234            fetch,
1235        }
1236    }
1237
1238    /// Execute the prepared query
1239    // The lifetime narrowing here is required for soundness.
1240    pub fn iter<'i>(&'i mut self) -> PreparedQueryIter<'i, Q> {
1241        let state: &'i [(usize, <Q::Fetch as Fetch<'i>>::State)] = unsafe { mem::transmute(self.state) };
1242
1243        unsafe { PreparedQueryIter::new(self.meta, self.archetypes, state.iter()) }
1244    }
1245
1246    /// Provides random access to the results of the prepared query
1247    pub fn view<'i>(&'i mut self) -> PreparedView<'i, Q> {
1248        let state: &'i [(usize, <Q::Fetch as Fetch<'i>>::State)] = unsafe { mem::transmute(self.state) };
1249
1250        unsafe { PreparedView::new(self.meta, self.archetypes, state.iter(), self.fetch) }
1251    }
1252}
1253
1254impl<Q: Query> Drop for PreparedQueryBorrow<'_, Q> {
1255    fn drop(&mut self) {
1256        for (idx, state) in self.state {
1257            if self.archetypes[*idx].is_empty() {
1258                continue;
1259            }
1260            Q::Fetch::release(&self.archetypes[*idx], *state);
1261        }
1262    }
1263}
1264
1265/// Iterates over all entities matching a [`PreparedQuery`]
1266pub struct PreparedQueryIter<'q, Q: Query> {
1267    meta: &'q [EntityMeta],
1268    archetypes: &'q [Archetype],
1269    state: SliceIter<'q, (usize, <Q::Fetch as Fetch<'q>>::State)>,
1270    iter: ChunkIter<Q>,
1271}
1272
1273impl<'q, Q: Query> PreparedQueryIter<'q, Q> {
1274    /// # Safety
1275    ///
1276    /// `'q` must be sufficient to guarantee that `Q` cannot violate borrow
1277    /// safety, either with dynamic borrow checks or by representing
1278    /// exclusive access to the `World`.
1279    unsafe fn new(meta: &'q [EntityMeta], archetypes: &'q [Archetype], state: SliceIter<'q, (usize, <Q::Fetch as Fetch<'q>>::State)>) -> Self {
1280        Self {
1281            meta,
1282            archetypes,
1283            state,
1284            iter: ChunkIter::empty(),
1285        }
1286    }
1287}
1288
1289unsafe impl<'q, Q: Query> Send for PreparedQueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1290unsafe impl<'q, Q: Query> Sync for PreparedQueryIter<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1291
1292#[allow(clippy::inline_always)]
1293impl<'q, Q: Query> Iterator for PreparedQueryIter<'q, Q> {
1294    type Item = (Entity, QueryItem<'q, Q>);
1295
1296    #[inline(always)]
1297    fn next(&mut self) -> Option<Self::Item> {
1298        loop {
1299            match unsafe { self.iter.next() } {
1300                None => {
1301                    let (idx, state) = self.state.next()?;
1302                    let archetype = &self.archetypes[*idx];
1303                    self.iter = ChunkIter {
1304                        entities: archetype.entities(),
1305                        fetch: Q::Fetch::execute(archetype, *state),
1306                        position: 0,
1307                        len: archetype.len() as usize,
1308                    };
1309                    continue;
1310                }
1311                Some((id, components)) => {
1312                    return Some((
1313                        Entity {
1314                            id,
1315                            generation: unsafe { self.meta.get_unchecked(id as usize).generation },
1316                        },
1317                        components,
1318                    ));
1319                }
1320            }
1321        }
1322    }
1323
1324    fn size_hint(&self) -> (usize, Option<usize>) {
1325        let n = self.len();
1326        (n, Some(n))
1327    }
1328}
1329
1330impl<Q: Query> ExactSizeIterator for PreparedQueryIter<'_, Q> {
1331    fn len(&self) -> usize {
1332        self.state.clone().map(|(idx, _)| self.archetypes[*idx].len() as usize).sum::<usize>() + self.iter.remaining()
1333    }
1334}
1335
1336/// Provides random access to the results of a query
1337pub struct View<'q, Q: Query> {
1338    meta: &'q [EntityMeta],
1339    fetch: Vec<Option<Q::Fetch>>,
1340}
1341
1342unsafe impl<'q, Q: Query> Send for View<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1343unsafe impl<'q, Q: Query> Sync for View<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1344
1345impl<'q, Q: Query> View<'q, Q> {
1346    /// # Safety
1347    ///
1348    /// `'q` must be sufficient to guarantee that `Q` cannot violate borrow
1349    /// safety, either with dynamic borrow checks or by representing
1350    /// exclusive access to the `World`.
1351    unsafe fn new(meta: &'q [EntityMeta], archetypes: &'q [Archetype]) -> Self {
1352        let fetch = archetypes
1353            .iter()
1354            .map(|archetype| Q::Fetch::prepare(archetype).map(|state| Q::Fetch::execute(archetype, state)))
1355            .collect();
1356
1357        Self { meta, fetch }
1358    }
1359
1360    /// Retrieve the query results corresponding to `entity`
1361    ///
1362    /// Will yield `None` if the entity does not exist or does not match the
1363    /// query.
1364    ///
1365    /// Does not require exclusive access to the map, but is defined only for
1366    /// queries yielding only shared references.
1367    pub fn get(&self, entity: Entity) -> Option<QueryItem<'_, Q>>
1368    where
1369        Q: QueryShared,
1370    {
1371        let meta = self.meta.get(entity.id as usize)?;
1372        if meta.generation != entity.generation {
1373            return None;
1374        }
1375
1376        self.fetch[meta.location.archetype as usize]
1377            .as_ref()
1378            .map(|fetch| unsafe { fetch.get(meta.location.index as usize) })
1379    }
1380
1381    /// Retrieve the query results corresponding to `entity`
1382    ///
1383    /// Will yield `None` if the entity does not exist or does not match the
1384    /// query.
1385    pub fn get_mut(&mut self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1386        unsafe { self.get_unchecked(entity) }
1387    }
1388
1389    /// Like `get_mut`, but allows simultaneous access to multiple entities
1390    ///
1391    /// # Safety
1392    ///
1393    /// Must not be invoked while any unique borrow of the fetched components of
1394    /// `entity` is live.
1395    pub unsafe fn get_unchecked(&self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1396        let meta = self.meta.get(entity.id as usize)?;
1397        if meta.generation != entity.generation {
1398            return None;
1399        }
1400
1401        self.fetch[meta.location.archetype as usize]
1402            .as_ref()
1403            .map(|fetch| fetch.get(meta.location.index as usize))
1404    }
1405
1406    /// Like `get_mut`, but allows checked simultaneous access to multiple
1407    /// entities
1408    ///
1409    /// For N > 3, the check for distinct entities will clone the array and take
1410    /// O(N log N) time.
1411    ///
1412    /// # Examples
1413    ///
1414    /// ```
1415    /// # use gloss_hecs::World;
1416    /// let mut world = World::new();
1417    ///
1418    /// let a = world.spawn((1, 1.0));
1419    /// let b = world.spawn((2, 4.0));
1420    /// let c = world.spawn((3, 9.0));
1421    ///
1422    /// let mut query = world.query_mut::<&mut i32>();
1423    /// let mut view = query.view();
1424    /// let [a, b, c] = view.get_mut_n([a, b, c]);
1425    ///
1426    /// assert_eq!(*a.unwrap(), 1);
1427    /// assert_eq!(*b.unwrap(), 2);
1428    /// assert_eq!(*c.unwrap(), 3);
1429    /// ```
1430    pub fn get_mut_n<const N: usize>(&mut self, entities: [Entity; N]) -> [Option<QueryItem<'_, Q>>; N] {
1431        assert_distinct(&entities);
1432
1433        let mut items = [(); N].map(|()| None);
1434
1435        for (item, entity) in items.iter_mut().zip(entities) {
1436            unsafe {
1437                *item = self.get_unchecked(entity);
1438            }
1439        }
1440
1441        items
1442    }
1443}
1444
1445/// Provides random access to the results of a prepared query
1446pub struct PreparedView<'q, Q: Query> {
1447    meta: &'q [EntityMeta],
1448    fetch: &'q mut [Option<Q::Fetch>],
1449}
1450
1451unsafe impl<'q, Q: Query> Send for PreparedView<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1452unsafe impl<'q, Q: Query> Sync for PreparedView<'q, Q> where <Q::Fetch as Fetch<'q>>::Item: Send {}
1453
1454impl<'q, Q: Query> PreparedView<'q, Q> {
1455    /// # Safety
1456    ///
1457    /// `'q` must be sufficient to guarantee that `Q` cannot violate borrow
1458    /// safety, either with dynamic borrow checks or by representing
1459    /// exclusive access to the `World`.
1460    unsafe fn new(
1461        meta: &'q [EntityMeta],
1462        archetypes: &'q [Archetype],
1463        state: SliceIter<'q, (usize, <Q::Fetch as Fetch<'q>>::State)>,
1464        fetch: &'q mut [Option<Q::Fetch>],
1465    ) -> Self {
1466        fetch.iter_mut().for_each(|fetch| *fetch = None);
1467
1468        for (idx, state) in state {
1469            let archetype = &archetypes[*idx];
1470            fetch[*idx] = Some(Q::Fetch::execute(archetype, *state));
1471        }
1472
1473        Self { meta, fetch }
1474    }
1475
1476    /// Retrieve the query results corresponding to `entity`
1477    ///
1478    /// Will yield `None` if the entity does not exist or does not match the
1479    /// query.
1480    ///
1481    /// Does not require exclusive access to the map, but is defined only for
1482    /// queries yielding only shared references.
1483    pub fn get(&self, entity: Entity) -> Option<QueryItem<'_, Q>>
1484    where
1485        Q: QueryShared,
1486    {
1487        let meta = self.meta.get(entity.id as usize)?;
1488        if meta.generation != entity.generation {
1489            return None;
1490        }
1491
1492        self.fetch[meta.location.archetype as usize]
1493            .as_ref()
1494            .map(|fetch| unsafe { fetch.get(meta.location.index as usize) })
1495    }
1496
1497    /// Retrieve the query results corresponding to `entity`
1498    ///
1499    /// Will yield `None` if the entity does not exist or does not match the
1500    /// query.
1501    pub fn get_mut(&mut self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1502        unsafe { self.get_unchecked(entity) }
1503    }
1504
1505    /// Like `get_mut`, but allows simultaneous access to multiple entities
1506    ///
1507    /// # Safety
1508    ///
1509    /// Must not be invoked while any unique borrow of the fetched components of
1510    /// `entity` is live.
1511    pub unsafe fn get_unchecked(&self, entity: Entity) -> Option<QueryItem<'_, Q>> {
1512        let meta = self.meta.get(entity.id as usize)?;
1513        if meta.generation != entity.generation {
1514            return None;
1515        }
1516
1517        self.fetch[meta.location.archetype as usize]
1518            .as_ref()
1519            .map(|fetch| fetch.get(meta.location.index as usize))
1520    }
1521
1522    /// Like `get_mut`, but allows checked simultaneous access to multiple
1523    /// entities
1524    ///
1525    /// See [`View::get_mut_n`] for details.
1526    pub fn get_mut_n<const N: usize>(&mut self, entities: [Entity; N]) -> [Option<QueryItem<'_, Q>>; N] {
1527        assert_distinct(&entities);
1528
1529        let mut items = [(); N].map(|()| None);
1530
1531        for (item, entity) in items.iter_mut().zip(entities) {
1532            unsafe {
1533                *item = self.get_unchecked(entity);
1534            }
1535        }
1536
1537        items
1538    }
1539}
1540
1541fn assert_distinct<const N: usize>(entities: &[Entity; N]) {
1542    match N {
1543        1 => (),
1544        2 => assert_ne!(entities[0], entities[1]),
1545        3 => {
1546            assert_ne!(entities[0], entities[1]);
1547            assert_ne!(entities[1], entities[2]);
1548            assert_ne!(entities[2], entities[0]);
1549        }
1550        _ => {
1551            let mut entities = *entities;
1552            entities.sort_unstable();
1553            for index in 0..N - 1 {
1554                assert_ne!(entities[index], entities[index + 1]);
1555            }
1556        }
1557    }
1558}
1559#[cfg(test)]
1560mod tests {
1561    use super::*;
1562
1563    #[test]
1564    fn access_order() {
1565        assert!(Access::Write > Access::Read);
1566        assert!(Access::Read > Access::Iterate);
1567        assert!(Some(Access::Iterate) > None);
1568    }
1569}