apecs/storage/archetype/
query.rs

1//! Component queries.
2use std::ops::Deref;
3use std::{any::TypeId, marker::PhantomData};
4
5use any_vec::{traits::*, AnyVec};
6use moongraph::{Edges, GraphError, TypeKey, TypeMap, View};
7use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
8use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
9
10use crate as apecs;
11use crate::storage::{
12    archetype::{Archetype, Components},
13    Entry,
14};
15
16use super::IsBundle;
17
18/// A placeholder type for borrowing an entire column of components from
19/// the world.
20pub struct ComponentColumn<T>(PhantomData<T>);
21
22/// Denotes the shape of a query that can be used to iterate over bundles of
23/// components.
24pub trait IsQuery {
25    /// Data that is read or write locked by performing this query.
26    type LockedColumns<'a>;
27    /// Data that can be used to append to columns. Typically vectors of
28    /// component entries or bundles of vectors of component entries.
29    type ExtensionColumns: 'static;
30    /// The iterator that is produced by performing a query on _one_ archetype.
31    type QueryResult<'a>: Iterator<Item = Self::QueryRow<'a>>;
32    /// The parallel iterator that is produced by performing a query on _one_
33    /// archetype.
34    type ParQueryResult<'a>: ParallelIterator<Item = Self::QueryRow<'a>> + IndexedParallelIterator;
35    /// The iterator item.
36    type QueryRow<'a>: Send + Sync;
37
38    fn reads() -> Vec<TypeKey>;
39
40    fn writes() -> Vec<TypeKey>;
41
42    /// Find and acquire a "lock" on the columns for reading or writing.
43    fn lock_columns<'a>(arch: &'a Archetype) -> Self::LockedColumns<'a>;
44
45    /// Extend entries in the locked columns.
46    ///
47    /// This is for internal use only.
48    fn extend_locked_columns<'a, 'b>(
49        lock: &'b mut Self::LockedColumns<'a>,
50        extension_columns: Self::ExtensionColumns,
51        output_ids: Option<(&mut Vec<usize>, &mut usize)>,
52    );
53
54    /// Create an iterator over the rows of the given columns.
55    fn iter_mut<'a, 'b>(lock: &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b>;
56
57    /// Create an iterator over one row with the given index.
58    fn iter_one<'a, 'b>(
59        lock: &'b mut Self::LockedColumns<'a>,
60        index: usize,
61    ) -> Self::QueryResult<'b>;
62
63    /// Create an iterator over the rows of the given columns.
64    fn par_iter_mut<'a, 'b>(
65        len: usize,
66        lock: &'b mut Self::LockedColumns<'a>,
67    ) -> Self::ParQueryResult<'b>;
68}
69
70impl<'s, T: Send + Sync + 'static> IsQuery for &'s T {
71    type LockedColumns<'a> = Option<RwLockReadGuard<'a, AnyVec<dyn Send + Sync + 'static>>>;
72    type ExtensionColumns = ();
73    type QueryResult<'a> = std::slice::Iter<'a, Entry<T>>;
74    type ParQueryResult<'a> = rayon::slice::Iter<'a, Entry<T>>;
75    type QueryRow<'a> = &'a Entry<T>;
76
77    fn reads() -> Vec<TypeKey> {
78        vec![TypeKey::new::<ComponentColumn<T>>()]
79    }
80
81    fn writes() -> Vec<TypeKey> {
82        vec![]
83    }
84
85    #[inline]
86    fn lock_columns<'t>(arch: &'t Archetype) -> Self::LockedColumns<'t> {
87        let ty = TypeId::of::<Entry<T>>();
88        let i = arch.index_of(&ty)?;
89        let data = arch.data[i].read();
90        Some(data)
91    }
92
93    fn extend_locked_columns<'a, 'b>(
94        _: &'b mut Self::LockedColumns<'a>,
95        (): Self::ExtensionColumns,
96        _: Option<(&mut Vec<usize>, &mut usize)>,
97    ) {
98        panic!("cannot mutate a read-only lock");
99    }
100
101    #[inline]
102    fn iter_mut<'a, 'b>(locked: &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b> {
103        locked.as_ref().map_or_else(
104            || (&[]).into_iter(),
105            |data| data.downcast_ref::<Entry<T>>().unwrap().into_iter(),
106        )
107    }
108
109    #[inline]
110    fn iter_one<'a, 'b>(
111        lock: &'b mut Self::LockedColumns<'a>,
112        index: usize,
113    ) -> Self::QueryResult<'b> {
114        lock.as_ref().map_or_else(
115            || (&[]).into_iter(),
116            |data| {
117                data.downcast_ref::<Entry<T>>()
118                    .expect("can't downcast")
119                    .as_slice()[index..=index]
120                    .into_iter()
121            },
122        )
123    }
124
125    /// Create an iterator over the rows of the given columns.
126    fn par_iter_mut<'a, 'b>(
127        _: usize,
128        lock: &'b mut Self::LockedColumns<'a>,
129    ) -> Self::ParQueryResult<'b> {
130        lock.as_ref().map_or_else(
131            || (&[]).into_par_iter(),
132            |data| {
133                data.downcast_ref::<Entry<T>>()
134                    .expect("can't downcast")
135                    .as_slice()
136                    .into_par_iter()
137            },
138        )
139    }
140}
141
142impl<'s, T: Send + Sync + 'static> IsQuery for &'s mut T {
143    type LockedColumns<'a> = Option<RwLockWriteGuard<'a, AnyVec<dyn Send + Sync + 'static>>>;
144    type ExtensionColumns = Box<dyn Iterator<Item = Entry<T>>>;
145    type QueryResult<'a> = std::slice::IterMut<'a, Entry<T>>;
146    type ParQueryResult<'a> = rayon::slice::IterMut<'a, Entry<T>>;
147    type QueryRow<'a> = &'a mut Entry<T>;
148
149    fn reads() -> Vec<TypeKey> {
150        vec![]
151    }
152
153    fn writes() -> Vec<TypeKey> {
154        vec![TypeKey::new::<ComponentColumn<T>>()]
155    }
156
157    #[inline]
158    fn lock_columns<'t>(arch: &'t Archetype) -> Self::LockedColumns<'t> {
159        let ty = TypeId::of::<Entry<T>>();
160        let i = arch.index_of(&ty)?;
161        let data = arch.data[i].write();
162        Some(data)
163    }
164
165    fn extend_locked_columns<'a, 'b>(
166        lock: &'b mut Self::LockedColumns<'a>,
167        extension_columns: Self::ExtensionColumns,
168        output_ids: Option<(&mut Vec<usize>, &mut usize)>,
169    ) {
170        lock.as_mut().map(|guard| {
171            let mut vs = guard.downcast_mut::<Entry<T>>().expect("can't downcast");
172            let (lower, may_upper) = extension_columns.size_hint();
173            let additional = may_upper.unwrap_or(lower);
174            vs.reserve(additional);
175            if let Some((output_ids, max_id)) = output_ids {
176                for entry in extension_columns {
177                    let id = entry.id();
178                    *max_id = id.max(*max_id);
179                    output_ids.push(id);
180                    vs.push(entry);
181                }
182            } else {
183                for entry in extension_columns {
184                    vs.push(entry);
185                }
186            }
187        });
188    }
189
190    #[inline]
191    fn iter_mut<'a, 'b>(locked: &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b> {
192        locked.as_mut().map_or_else(
193            || (&mut []).into_iter(),
194            |data| {
195                data.downcast_mut::<Entry<T>>()
196                    .expect("can't downcast")
197                    .into_iter()
198            },
199        )
200    }
201
202    #[inline]
203    fn iter_one<'a, 'b>(
204        lock: &'b mut Self::LockedColumns<'a>,
205        index: usize,
206    ) -> Self::QueryResult<'b> {
207        lock.as_mut().map_or_else(
208            || (&mut []).into_iter(),
209            |data| {
210                (&mut data
211                    .downcast_mut::<Entry<T>>()
212                    .expect("can't downcast")
213                    .as_mut_slice()[index..=index])
214                    .into_iter()
215            },
216        )
217    }
218
219    /// Create an iterator over the rows of the given columns.
220    fn par_iter_mut<'a, 'b>(
221        _: usize,
222        lock: &'b mut Self::LockedColumns<'a>,
223    ) -> Self::ParQueryResult<'b> {
224        lock.as_mut().map_or_else(
225            || (&mut []).into_par_iter(),
226            |data| {
227                data.downcast_mut::<Entry<T>>()
228                    .expect("can't downcast")
229                    .as_mut_slice()
230                    .into_par_iter()
231            },
232        )
233    }
234}
235
236/// Query type used to denote an optional column.
237///
238/// Use `Maybe` in queries to return bundles of components that may or may not
239/// contain a component of the wrapped type `T`.
240pub struct Maybe<T>(PhantomData<T>);
241
242impl<'s, T: Send + Sync + 'static> IsQuery for Maybe<&'s T> {
243    type LockedColumns<'a> = Option<RwLockReadGuard<'a, AnyVec<dyn Send + Sync + 'static>>>;
244    type ExtensionColumns = ();
245    type QueryResult<'a> = itertools::Either<
246        std::iter::RepeatWith<fn() -> Option<&'a Entry<T>>>,
247        std::iter::Map<
248            std::slice::Iter<'a, Entry<T>>,
249            for<'r> fn(&'r Entry<T>) -> Option<&'r Entry<T>>,
250        >,
251    >;
252    type ParQueryResult<'a> = rayon::iter::Either<
253        rayon::iter::Map<rayon::iter::RepeatN<()>, fn(()) -> Option<&'a Entry<T>>>,
254        rayon::iter::Map<
255            rayon::slice::Iter<'a, Entry<T>>,
256            for<'r> fn(&'r Entry<T>) -> Option<&'r Entry<T>>,
257        >,
258    >;
259    type QueryRow<'a> = Option<&'a Entry<T>>;
260
261    fn reads() -> Vec<TypeKey> {
262        <&T as IsQuery>::reads()
263    }
264
265    fn writes() -> Vec<TypeKey> {
266        <&T as IsQuery>::writes()
267    }
268
269    fn lock_columns<'a>(arch: &'a Archetype) -> Self::LockedColumns<'a> {
270        <&T as IsQuery>::lock_columns(arch)
271    }
272
273    fn extend_locked_columns<'a, 'b>(
274        _: &'b mut Self::LockedColumns<'a>,
275        _: Self::ExtensionColumns,
276        _: Option<(&mut Vec<usize>, &mut usize)>,
277    ) {
278        panic!("cannot extend Maybe columns");
279    }
280
281    fn iter_mut<'a, 'b>(lock: &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b> {
282        lock.as_mut().map_or_else(
283            || {
284                itertools::Either::Left(std::iter::repeat_with(
285                    (|| None) as fn() -> Option<&'a Entry<T>>,
286                ))
287            },
288            |data| {
289                itertools::Either::Right(
290                    data.downcast_ref::<Entry<T>>()
291                        .expect("can't downcast")
292                        .into_iter()
293                        .map((|e| Some(e)) as fn(&Entry<T>) -> Option<&Entry<T>>),
294                )
295            },
296        )
297    }
298
299    fn iter_one<'a, 'b>(
300        lock: &'b mut Self::LockedColumns<'a>,
301        index: usize,
302    ) -> Self::QueryResult<'b> {
303        lock.as_mut().map_or_else(
304            || {
305                itertools::Either::Left(std::iter::repeat_with(
306                    (|| None) as fn() -> Option<&'b Entry<T>>,
307                ))
308            },
309            |data| {
310                itertools::Either::Right(
311                    (&data
312                        .downcast_ref::<Entry<T>>()
313                        .expect("can't downcast")
314                        .as_slice()[index..=index])
315                        .into_iter()
316                        .map((|e| Some(e)) as fn(&Entry<T>) -> Option<&Entry<T>>),
317                )
318            },
319        )
320    }
321
322    fn par_iter_mut<'a, 'b>(
323        len: usize,
324        lock: &'b mut Self::LockedColumns<'a>,
325    ) -> Self::ParQueryResult<'b> {
326        lock.as_mut().map_or_else(
327            || {
328                rayon::iter::Either::Left(
329                    rayon::iter::repeatn((), len)
330                        .map((|()| None) as fn(()) -> Option<&'a Entry<T>>),
331                )
332            },
333            |data| {
334                rayon::iter::Either::Right(
335                    data.downcast_ref::<Entry<T>>()
336                        .expect("can't downcast")
337                        .as_slice()
338                        .into_par_iter()
339                        .map((|e| Some(e)) as fn(&Entry<T>) -> Option<&Entry<T>>),
340                )
341            },
342        )
343    }
344}
345
346impl<'s, T: Send + Sync + 'static> IsQuery for Maybe<&'s mut T> {
347    type LockedColumns<'a> = Option<RwLockWriteGuard<'a, AnyVec<dyn Send + Sync + 'static>>>;
348    type ExtensionColumns = ();
349    type QueryResult<'a> = itertools::Either<
350        std::iter::RepeatWith<fn() -> Option<&'a mut Entry<T>>>,
351        std::iter::Map<
352            std::slice::IterMut<'a, Entry<T>>,
353            for<'r> fn(&'r mut Entry<T>) -> Option<&'r mut Entry<T>>,
354        >,
355    >;
356    type ParQueryResult<'a> = rayon::iter::Either<
357        rayon::iter::Map<rayon::iter::RepeatN<()>, fn(()) -> Option<&'a mut Entry<T>>>,
358        rayon::iter::Map<
359            rayon::slice::IterMut<'a, Entry<T>>,
360            for<'r> fn(&'r mut Entry<T>) -> Option<&'r mut Entry<T>>,
361        >,
362    >;
363    type QueryRow<'a> = Option<&'a mut Entry<T>>;
364
365    fn reads() -> Vec<TypeKey> {
366        <&mut T as IsQuery>::reads()
367    }
368
369    fn writes() -> Vec<TypeKey> {
370        <&mut T as IsQuery>::writes()
371    }
372
373    fn lock_columns<'a>(arch: &'a Archetype) -> Self::LockedColumns<'a> {
374        <&mut T as IsQuery>::lock_columns(arch)
375    }
376
377    fn extend_locked_columns<'a, 'b>(
378        _: &'b mut Self::LockedColumns<'a>,
379        _: Self::ExtensionColumns,
380        _: Option<(&mut Vec<usize>, &mut usize)>,
381    ) {
382        panic!("cannot extend Maybe columns");
383    }
384
385    fn iter_mut<'a, 'b>(lock: &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b> {
386        lock.as_mut().map_or_else(
387            || {
388                itertools::Either::Left(std::iter::repeat_with(
389                    (|| None) as fn() -> Option<&'a mut Entry<T>>,
390                ))
391            },
392            |data| {
393                itertools::Either::Right(
394                    data.downcast_mut::<Entry<T>>()
395                        .expect("can't downcast")
396                        .into_iter()
397                        .map((|e| Some(e)) as fn(&mut Entry<T>) -> Option<&mut Entry<T>>),
398                )
399            },
400        )
401    }
402
403    fn iter_one<'a, 'b>(
404        lock: &'b mut Self::LockedColumns<'a>,
405        index: usize,
406    ) -> Self::QueryResult<'b> {
407        lock.as_mut().map_or_else(
408            || {
409                itertools::Either::Left(std::iter::repeat_with(
410                    (|| None) as fn() -> Option<&'b mut Entry<T>>,
411                ))
412            },
413            |data| {
414                itertools::Either::Right(
415                    (&mut data
416                        .downcast_mut::<Entry<T>>()
417                        .expect("can't downcast")
418                        .as_mut_slice()[index..=index])
419                        .into_iter()
420                        .map((|e| Some(e)) as fn(&mut Entry<T>) -> Option<&mut Entry<T>>),
421                )
422            },
423        )
424    }
425
426    fn par_iter_mut<'a, 'b>(
427        len: usize,
428        lock: &'b mut Self::LockedColumns<'a>,
429    ) -> Self::ParQueryResult<'b> {
430        lock.as_mut().map_or_else(
431            || {
432                rayon::iter::Either::Left(
433                    rayon::iter::repeatn((), len)
434                        .map((|()| None) as fn(()) -> Option<&'a mut Entry<T>>),
435                )
436            },
437            |data| {
438                rayon::iter::Either::Right(
439                    data.downcast_mut::<Entry<T>>()
440                        .expect("can't downcast")
441                        .as_mut_slice()
442                        .into_par_iter()
443                        .map((|e| Some(e)) as fn(&mut Entry<T>) -> Option<&mut Entry<T>>),
444                )
445            },
446        )
447    }
448}
449
450/// Query type used to denote the absence of the wrapped type.
451pub struct Without<T>(PhantomData<T>);
452
453impl<T: Send + Sync + 'static> IsQuery for Without<T> {
454    type LockedColumns<'a> = bool;
455    type ExtensionColumns = ();
456    type QueryResult<'a> = itertools::Either<std::iter::Repeat<()>, std::vec::IntoIter<()>>;
457    type ParQueryResult<'a> = rayon::iter::RepeatN<()>;
458    type QueryRow<'a> = ();
459
460    fn reads() -> Vec<TypeKey> {
461        <&T as IsQuery>::reads()
462    }
463
464    fn writes() -> Vec<TypeKey> {
465        <&T as IsQuery>::writes()
466    }
467
468    fn lock_columns<'a>(arch: &'a Archetype) -> Self::LockedColumns<'a> {
469        arch.has_component::<T>()
470    }
471
472    fn extend_locked_columns<'a, 'b>(
473        _: &'b mut Self::LockedColumns<'a>,
474        _: Self::ExtensionColumns,
475        _: Option<(&mut Vec<usize>, &mut usize)>,
476    ) {
477        panic!("cannot extend Without columns");
478    }
479
480    fn iter_mut<'a, 'b>(lock: &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b> {
481        if *lock {
482            itertools::Either::Right(vec![].into_iter())
483        } else {
484            itertools::Either::Left(std::iter::repeat(()))
485        }
486    }
487
488    fn iter_one<'a, 'b>(lock: &'b mut Self::LockedColumns<'a>, _: usize) -> Self::QueryResult<'b> {
489        if *lock {
490            itertools::Either::Right(vec![].into_iter())
491        } else {
492            itertools::Either::Left(std::iter::repeat(()))
493        }
494    }
495
496    fn par_iter_mut<'a, 'b>(
497        len: usize,
498        lock: &'b mut Self::LockedColumns<'a>,
499    ) -> Self::ParQueryResult<'b> {
500        if *lock {
501            rayon::iter::repeatn((), 0)
502        } else {
503            rayon::iter::repeatn((), len)
504        }
505    }
506}
507
508impl<A> IsQuery for (A,)
509where
510    A: IsQuery,
511{
512    type LockedColumns<'a> = A::LockedColumns<'a>;
513    type ExtensionColumns = A::ExtensionColumns;
514    type QueryResult<'a> = A::QueryResult<'a>;
515    type ParQueryResult<'a> = A::ParQueryResult<'a>;
516    type QueryRow<'a> = A::QueryRow<'a>;
517
518    fn reads() -> Vec<TypeKey> {
519        A::reads()
520    }
521
522    fn writes() -> Vec<TypeKey> {
523        A::writes()
524    }
525
526    #[inline]
527    fn lock_columns<'t>(arch: &'t Archetype) -> Self::LockedColumns<'t> {
528        A::lock_columns(arch)
529    }
530
531    fn extend_locked_columns<'a, 'b>(
532        lock: &'b mut Self::LockedColumns<'a>,
533        ext: Self::ExtensionColumns,
534        output_ids: Option<(&mut Vec<usize>, &mut usize)>,
535    ) {
536        A::extend_locked_columns(lock, ext, output_ids);
537    }
538
539    #[inline]
540    fn iter_mut<'a, 'b>(lock: &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b> {
541        A::iter_mut(lock)
542    }
543
544    fn iter_one<'a, 'b>(
545        lock: &'b mut Self::LockedColumns<'a>,
546        index: usize,
547    ) -> Self::QueryResult<'b> {
548        A::iter_one(lock, index)
549    }
550
551    fn par_iter_mut<'a, 'b>(
552        len: usize,
553        lock: &'b mut Self::LockedColumns<'a>,
554    ) -> Self::ParQueryResult<'b> {
555        A::par_iter_mut(len, lock)
556    }
557}
558
559impl<A, B> IsQuery for (A, B)
560where
561    A: IsQuery,
562    B: IsQuery,
563{
564    type LockedColumns<'a> = (A::LockedColumns<'a>, B::LockedColumns<'a>);
565    type ExtensionColumns = (A::ExtensionColumns, B::ExtensionColumns);
566    type QueryResult<'a> = std::iter::Zip<A::QueryResult<'a>, B::QueryResult<'a>>;
567    type ParQueryResult<'a> = rayon::iter::Zip<A::ParQueryResult<'a>, B::ParQueryResult<'a>>;
568    type QueryRow<'a> = (A::QueryRow<'a>, B::QueryRow<'a>);
569
570    fn reads() -> Vec<TypeKey> {
571        let mut bs = A::reads();
572        bs.extend(B::reads());
573        bs
574    }
575
576    fn writes() -> Vec<TypeKey> {
577        let mut bs = A::writes();
578        bs.extend(B::writes());
579        bs
580    }
581
582    #[inline]
583    fn lock_columns<'t>(arch: &'t Archetype) -> Self::LockedColumns<'t> {
584        let a = A::lock_columns(arch);
585        let b = B::lock_columns(arch);
586        (a, b)
587    }
588
589    fn extend_locked_columns<'a, 'b>(
590        (a, b): &'b mut Self::LockedColumns<'a>,
591        (ea, eb): Self::ExtensionColumns,
592        output_ids: Option<(&mut Vec<usize>, &mut usize)>,
593    ) {
594        A::extend_locked_columns(a, ea, output_ids);
595        B::extend_locked_columns(b, eb, None);
596    }
597
598    #[inline]
599    fn iter_mut<'a, 'b>((col_a, col_b): &'b mut Self::LockedColumns<'a>) -> Self::QueryResult<'b> {
600        A::iter_mut(col_a).zip(B::iter_mut(col_b))
601    }
602
603    fn iter_one<'a, 'b>(
604        (col_a, col_b): &'b mut Self::LockedColumns<'a>,
605        index: usize,
606    ) -> Self::QueryResult<'b> {
607        A::iter_one(col_a, index).zip(B::iter_one(col_b, index))
608    }
609
610    fn par_iter_mut<'a, 'b>(
611        len: usize,
612        (col_a, col_b): &'b mut Self::LockedColumns<'a>,
613    ) -> Self::ParQueryResult<'b> {
614        A::par_iter_mut(len, col_a).zip(B::par_iter_mut(len, col_b))
615    }
616}
617
618apecs_derive::impl_isquery_tuple!((A, B, C));
619apecs_derive::impl_isquery_tuple!((A, B, C, D));
620apecs_derive::impl_isquery_tuple!((A, B, C, D, E));
621apecs_derive::impl_isquery_tuple!((A, B, C, D, E, F));
622apecs_derive::impl_isquery_tuple!((A, B, C, D, E, F, G));
623apecs_derive::impl_isquery_tuple!((A, B, C, D, E, F, G, H));
624apecs_derive::impl_isquery_tuple!((A, B, C, D, E, F, G, H, I));
625apecs_derive::impl_isquery_tuple!((A, B, C, D, E, F, G, H, I, J));
626apecs_derive::impl_isquery_tuple!((A, B, C, D, E, F, G, H, I, J, K));
627apecs_derive::impl_isquery_tuple!((A, B, C, D, E, F, G, H, I, J, K, L));
628
629impl Components {
630    /// Append to the existing set of archetypes in bulk.
631    ///
632    /// This assumes the entries being inserted have unique ids and don't
633    /// already exist in the set.
634    ///
635    /// ```rust
636    /// use apecs::*;
637    /// let mut components = Components::default();
638    /// let a = Box::new((0..10_000).map(|id| Entry::new(id, id as u32)));
639    /// let b = Box::new((0..10_000).map(|id| Entry::new(id, id as f32)));
640    /// let c = Box::new((0..10_000).map(|id| Entry::new(id, format!("string{}", id))));
641    /// let d = Box::new((0..10_000).map(|id| Entry::new(id, id % 2 == 0)));
642    /// components.extend::<(u32, f32, String, bool)>((a, b, c, d));
643    /// assert_eq!(10_000, components.len());
644    /// ```
645    pub fn extend<B: IsBundle>(&mut self, extension: <B::MutBundle as IsQuery>::ExtensionColumns)
646    where
647        B::MutBundle: IsQuery,
648    {
649        let types = B::EntryBundle::ordered_types().unwrap();
650        let archetype_index;
651        let arch;
652        if let Some((i, a)) = self.get_archetype_mut(&types) {
653            archetype_index = i;
654            arch = a;
655        } else {
656            let new_arch = Archetype::new::<B>().unwrap();
657            archetype_index = self.archetypes.len();
658            self.archetypes.push(new_arch);
659            arch = &mut self.archetypes[archetype_index];
660        }
661        let mut index_lookup: Vec<usize> = vec![];
662        let mut max_id: usize = 0;
663        {
664            let mut lock = <B::MutBundle as IsQuery>::lock_columns(arch);
665            <B::MutBundle as IsQuery>::extend_locked_columns(
666                &mut lock,
667                extension,
668                Some((&mut index_lookup, &mut max_id)),
669            );
670        }
671        arch.index_lookup = index_lookup.clone();
672
673        if max_id >= self.entity_lookup.len() {
674            self.entity_lookup.resize_with(max_id + 1, Default::default);
675        }
676        index_lookup.iter().enumerate().for_each(|(i, id)| {
677            self.entity_lookup[*id] = Some((archetype_index, i));
678        });
679    }
680
681    /// Prepare a query.
682    /// ```rust
683    /// use apecs::*;
684    ///
685    /// let mut components = Components::default();
686    /// components.insert_bundle(0, ("zero", 0.0f32, 0u32));
687    /// components.insert_bundle(1, ("zero", 0.0f32, 0u32));
688    /// components.insert_bundle(2, ("zero", 0.0f32, 0u32));
689    ///
690    /// for (f, u) in components.query::<(&f32, &u32)>().iter_mut() {
691    ///     assert_eq!(**f, **u as f32);
692    /// }
693    /// ```
694    pub fn query<Q: IsQuery + 'static>(&mut self) -> QueryGuard<'_, Q> {
695        QueryGuard(
696            self.archetypes.iter().map(|a| Q::lock_columns(a)).collect(),
697            self,
698        )
699    }
700}
701
702/// Iterator returned by [`QueryGuard::iter_mut`].
703pub type QueryIter<'a, 'b, Q> = std::iter::FlatMap<
704    std::slice::IterMut<'b, <Q as IsQuery>::LockedColumns<'a>>,
705    <Q as IsQuery>::QueryResult<'b>,
706    for<'r> fn(&'r mut <Q as IsQuery>::LockedColumns<'a>) -> <Q as IsQuery>::QueryResult<'r>,
707>;
708
709/// A prepared and active query.
710///
711/// Iterate over queried items using [`QueryGuard::iter_mut`].
712pub struct QueryGuard<'a, Q: IsQuery + ?Sized>(Vec<Q::LockedColumns<'a>>, &'a Components);
713
714impl<'a, Q> QueryGuard<'a, Q>
715where
716    Q: IsQuery + ?Sized,
717{
718    /// Iterate over matched component bundles.
719    ///
720    /// Each component is wrapped with [`Entry`], which provides access
721    /// to the entity id and modification data.
722    pub fn iter_mut(&mut self) -> QueryIter<'a, '_, Q> {
723        self.0.iter_mut().flat_map(|cols| Q::iter_mut(cols))
724    }
725
726    /// Find the component bundle with the given entity id.
727    ///
728    /// This does not iterate. It locates the item by index.
729    pub fn find_one(&mut self, entity_id: usize) -> Option<Q::QueryRow<'_>> {
730        self.1
731            .entity_lookup
732            .get(entity_id)
733            .copied()
734            .and_then(|may_indices| {
735                let (archetype_index, component_index) = may_indices?;
736                let mut vs =
737                    Q::iter_one(&mut self.0[archetype_index], component_index).collect::<Vec<_>>();
738                vs.pop()
739            })
740    }
741
742    /// Iterate over matched component bundles, in parallel.
743    ///
744    /// Each component is wrapped with [`Entry`], which provides access
745    /// to the entity id and modification data.
746    pub fn par_iter_mut(
747        &mut self,
748    ) -> rayon::iter::Flatten<rayon::vec::IntoIter<<Q as IsQuery>::ParQueryResult<'_>>> {
749        let size_hints = self.1.archetypes.iter().map(|arch| arch.index_lookup.len());
750        size_hints
751            .zip(self.0.iter_mut())
752            .map(|(len, cols)| Q::par_iter_mut(len, cols))
753            .collect::<Vec<_>>()
754            .into_par_iter()
755            .flatten()
756    }
757}
758
759/// Queries are used to iterate over matching bundles of components.
760///
761/// `Query`s are written as a tuple of component column types, where each
762/// position in the tuple denotes a column value in each item of the resulting
763/// query iterator. Each item column type will be wrapped in [`Entry`] in the
764/// resulting query iterator.
765///
766/// For example: `Query<(&mut f32, &String)>` will result in an iterator of
767/// items with the type `(&mut Entry<f32>, &Entry<String>)`.
768///
769/// ## Creating queries
770/// Some functions query immidiately and return [`QueryGuard`]:
771/// * [`Components::query`]
772/// * [`Entity::visit`](crate::Entity::visit)
773///
774/// With these functions you pass component column types as a type parameter:
775/// ```
776/// # use apecs::*;
777/// # let mut world = World::default();
778/// let mut query = world
779///     .get_components_mut()
780///     .query::<(&f32, &String)>();
781/// for (f32, string) in query.iter_mut() {
782///     //...
783/// }
784/// ```
785///
786/// ### System data queries
787/// `Query` implements [`Edges`], which allows you to use queries
788/// as fields inside system data structs:
789///
790/// ```
791/// # use apecs::*;
792/// #[derive(Edges)]
793/// struct MySystemData {
794///     counter: ViewMut<u32>,
795///     // we use &'static to avoid introducing a lifetime
796///     q_f32_and_string: Query<(&'static f32, &'static String)>,
797/// }
798/// ```
799///
800/// Which means queries may be [`visit`](crate::World::visit)ed from outside the world,
801/// or used as the input to a system:
802/// ```
803/// use apecs::*;
804///
805/// #[derive(Edges)]
806/// struct MySystemData {
807///     tracker: ViewMut<u64>,
808///     // We can use Mut and Ref which are aliases for &'static mut and &'static.
809///     q_f32_and_string: Query<(Mut<f32>, Ref<String>)>,
810/// }
811///
812/// fn my_system(mut data: MySystemData) -> Result<(), GraphError> {
813///     for (f32, string) in data.q_f32_and_string.query().iter_mut() {
814///         if f32.was_modified_since(*data.tracker) {
815///             **f32 += 1.0;
816///             println!("set entity {} = {}", f32.id(), **f32);
817///         }
818///     }
819///     *data.tracker = apecs::current_iteration();
820///     ok()
821/// }
822///
823/// let mut world = World::default();
824/// world.add_subgraph(graph!(my_system));
825/// world.tick().unwrap();
826/// ```
827///
828/// ## Iterating queries
829/// Below we use mutable and immutable reference types in our query to include
830/// either a mutable or immutable reference to those components:
831/// ```
832/// use apecs::*;
833///
834/// struct Position(pub f32);
835/// struct Velocity(pub f32);
836/// struct Acceleration(pub f32);
837///
838/// fn create(mut entities: ViewMut<Entities>) -> Result<(), GraphError> {
839///     for i in 0..100 {
840///         entities.create().insert_bundle((
841///             Position(0.0),
842///             Velocity(0.0),
843///             Acceleration(i as f32),
844///         ));
845///     }
846///     
847///     /// This system ends after one tick
848///     end()
849/// }
850///
851/// fn accelerate(q_accelerate: Query<(&mut Velocity, &Acceleration)>) -> Result<(), GraphError> {
852///     for (v, a) in q_accelerate.query().iter_mut() {
853///         v.0 += a.0;
854///     }
855///     ok()
856/// }
857///
858/// fn position(q_move: Query<(&mut Position, &Velocity)>) -> Result<(), GraphError> {
859///     for (p, v) in q_move.query().iter_mut() {
860///         p.0 += v.0;
861///     }
862///     ok()
863/// }
864///
865/// let mut world = World::default();
866/// world.add_subgraph(graph!(create, accelerate, position));
867/// world.tick().unwrap();
868/// ```
869pub struct Query<T>(
870    Box<dyn Deref<Target = Components> + Send + Sync + 'static>,
871    PhantomData<T>,
872)
873where
874    T: IsQuery + ?Sized;
875
876impl<T> Edges for Query<T>
877where
878    T: IsQuery + Send + Sync + ?Sized,
879{
880    fn reads() -> Vec<TypeKey> {
881        let mut bs = <T as IsQuery>::reads();
882        bs.extend(View::<Components>::reads());
883        bs
884    }
885
886    fn writes() -> Vec<TypeKey> {
887        let mut bs = <T as IsQuery>::writes();
888        bs.extend(View::<Components>::writes());
889        bs
890    }
891
892    fn moves() -> Vec<TypeKey> {
893        vec![]
894    }
895
896    fn construct(loan_mngr: &mut TypeMap) -> Result<Self, GraphError> {
897        let all: View<Components> = View::construct(loan_mngr)?;
898        Ok(Query(Box::new(all), PhantomData))
899    }
900}
901
902impl<Q> Query<Q>
903where
904    Q: IsQuery + ?Sized,
905{
906    /// Prepare the query, locking the columns needed to iterate over matching
907    /// components.
908    pub fn query(&self) -> QueryGuard<'_, Q> {
909        QueryGuard(
910            self.0
911                .archetypes
912                .iter()
913                .map(|a| Q::lock_columns(a))
914                .collect(),
915            &self.0,
916        )
917    }
918}
919
920/// Alias for `&'static T` for folks with wrist pain.
921pub type Ref<T> = &'static T;
922/// Alias for `&'static mut T` for folks with wrist pain.
923pub type Mut<T> = &'static mut T;
924/// Alias for `Maybe<&'static T>` for folks with wrist pain.
925pub type MaybeRef<T> = Maybe<&'static T>;
926/// Alias for `Maybe<&'static mut T>` for folks with wrist pain.
927pub type MaybeMut<T> = Maybe<&'static mut T>;
928
929#[cfg(test)]
930mod test {
931    use std::ops::DerefMut;
932
933    use super::*;
934
935    #[test]
936    fn can_query_all() {
937        let _ = env_logger::builder()
938            .is_test(true)
939            .filter_level(log::LevelFilter::Trace)
940            .try_init();
941
942        let mut all = Components::default();
943        all.insert_bundle(0, (0.0f32, true));
944        all.insert_bundle(1, (1.0f32, false, "hello"));
945        all.insert_bundle(2, (2.0f32, true, ()));
946        all.insert_bundle(3, (3.0f32, false));
947
948        let mut q = all.query::<&f32>();
949        let sum = q.iter_mut().fold(0.0f32, |sum, f| sum + **f);
950        assert_eq!(6.0, sum);
951    }
952
953    #[test]
954    fn iter_types() {
955        let _ = env_logger::builder()
956            .is_test(true)
957            .filter_level(log::LevelFilter::Trace)
958            .try_init();
959
960        println!("insert");
961        let mut store = Components::default();
962        store.insert_bundle(0, (0.0f32, "zero".to_string(), false));
963        store.insert_bundle(1, (1.0f32, "one".to_string(), false));
964        store.insert_bundle(2, (2.0f32, "two".to_string(), false));
965
966        {
967            println!("query 1");
968            let mut q = store.query::<&f32>();
969            let f32s = q.iter_mut().map(|f| **f).collect::<Vec<_>>();
970            let f32s_again = q.iter_mut().map(|f| **f).collect::<Vec<_>>();
971            assert_eq!(vec![0.0f32, 1.0, 2.0f32], f32s);
972            assert_eq!(vec![0.0f32, 1.0, 2.0f32], f32s_again);
973        }
974
975        {
976            println!("query 2");
977            let mut q = store.query::<(&mut bool, &f32)>();
978            let units: Vec<()> = q
979                .iter_mut()
980                .enumerate()
981                .map(|(i, (is_on, f))| {
982                    **is_on = !**is_on;
983                    assert!(**is_on);
984                    assert!(**f as usize == i);
985                })
986                .collect::<Vec<_>>();
987            assert_eq!(3, units.len());
988        }
989
990        {
991            println!("query 3");
992            let mut q = store.query::<(&String, &mut bool, &mut f32)>();
993            println!("query 3 iteration");
994            q.iter_mut().for_each(|(s, is_on, f)| {
995                **is_on = true;
996                **f = s.len() as f32;
997            });
998        }
999
1000        println!("query 4");
1001        let mut q = store.query::<(&bool, &f32, &String)>();
1002        q.iter_mut().for_each(|(is_on, f, s)| {
1003            assert!(**is_on);
1004            assert_eq!(**f, s.len() as f32, "{}.len() != {}", **s, **f);
1005        });
1006    }
1007
1008    #[test]
1009    fn query_one() {
1010        let mut store = Components::default();
1011        store.insert_bundle(0, (0.0f32, "zero".to_string(), false));
1012        store.insert_bundle(1, (1.0f32, "one".to_string(), false));
1013        store.insert_bundle(2, (2.0f32, "two".to_string(), false));
1014
1015        {
1016            let mut q = store.query::<(&mut f32, &mut String, &bool)>();
1017            let (f, s, b) = q.find_one(1).unwrap();
1018            *f.deref_mut() = 666.0;
1019            **s = format!("blah {:?} {:?}", f.value(), b.value());
1020        }
1021
1022        let mut q = store.query::<(&f32, &String, &bool)>();
1023        let vs = q
1024            .iter_mut()
1025            .map(|(f, s, b)| (f.id(), **f, s.to_string(), **b))
1026            .collect::<Vec<_>>();
1027        assert_eq!(
1028            vec![
1029                (0usize, 0.0f32, "zero".to_string(), false,),
1030                (1, 666.0, "blah 666.0 false".to_string(), false,),
1031                (2, 2.0, "two".to_string(), false,),
1032            ],
1033            vs
1034        );
1035    }
1036
1037    #[test]
1038    fn sanity_query_iter() {
1039        let mut store = Components::default();
1040        store.insert_bundle(0, (0.0f32, "zero".to_string(), false));
1041        store.insert_bundle(1, (1.0f32, "one".to_string(), false));
1042        store.insert_bundle(2, (2.0f32, "two".to_string(), false));
1043
1044        type MyQuery<'a> = (&'a f32, &'a String, &'a bool);
1045        let mut locked = store
1046            .archetypes
1047            .iter()
1048            .map(|a| MyQuery::lock_columns(a))
1049            .collect::<Vec<_>>();
1050        let mut count = 0;
1051        let iter = locked.iter_mut().flat_map(|cols| MyQuery::iter_mut(cols));
1052        for (f, s, b) in iter {
1053            assert!(!**b, "{} {} {}", f.value(), s.value(), b.value());
1054            count += 1;
1055        }
1056        assert_eq!(3, count);
1057    }
1058
1059    #[test]
1060    fn can_query_maybe() {
1061        let mut components = Components::default();
1062        components.insert_bundle(0, (0.0f32, "zero".to_string()));
1063        components.insert_bundle(1, (1.0f32, "one".to_string(), false));
1064        components.insert_bundle(2, (2.0f32, "two".to_string()));
1065
1066        let cols = components
1067            .query::<(&f32, Maybe<&bool>, &String)>()
1068            .iter_mut()
1069            .map(|(f, mb, s)| (**f, mb.map(|b| **b), s.value().clone()))
1070            .collect::<Vec<_>>();
1071        // these appear in order of archetypes added
1072        assert_eq!(
1073            vec![
1074                (0.0, None, "zero".to_string()),
1075                (2.0, None, "two".to_string()),
1076                (1.0, Some(false), "one".to_string()),
1077            ],
1078            cols
1079        );
1080
1081        let par_cols = components
1082            .query::<(&f32, Maybe<&bool>, &String)>()
1083            .par_iter_mut()
1084            .map(|(f, mb, s)| (**f, mb.map(|b| **b), s.value().clone()))
1085            .collect::<Vec<_>>();
1086        assert_eq!(cols, par_cols);
1087    }
1088
1089    #[test]
1090    fn can_query_without() {
1091        let mut components = Components::default();
1092        components.insert_bundle(0, (0.0f32, "zero".to_string()));
1093        components.insert_bundle(1, (1.0f32, "one".to_string(), false));
1094        components.insert_bundle(2, (2.0f32, "two".to_string()));
1095
1096        let cols = components
1097            .query::<(&f32, Without<bool>, &String)>()
1098            .iter_mut()
1099            .map(|(f, (), s)| (**f, (), s.value().clone()))
1100            .collect::<Vec<_>>();
1101        assert_eq!(
1102            vec![(0.0, (), "zero".to_string()), (2.0, (), "two".to_string()),],
1103            cols
1104        );
1105
1106        let par_cols = components
1107            .query::<(&f32, Without<bool>, &String)>()
1108            .par_iter_mut()
1109            .map(|(f, (), s)| (**f, (), s.value().clone()))
1110            .collect::<Vec<_>>();
1111        assert_eq!(cols, par_cols);
1112    }
1113}