cecs/
query.rs

1// FIXME: yeet the bloody Box<dyn Iterator> iterators please
2//
3pub mod filters;
4pub mod resource_query;
5
6#[cfg(test)]
7mod query_tests;
8
9use crate::{
10    Component, RowIndex, World,
11    entity_id::EntityId,
12    systems::SystemDescriptor,
13    table::{ArchetypeHash, EntityTable},
14};
15use filters::Filter;
16use std::{any::TypeId, collections::HashSet, marker::PhantomData, ops::RangeBounds, slice};
17
18/// # SAFETY
19///
20/// Implementors must ensure that the appropriate methods are implemented!
21pub unsafe trait WorldQuery<'a> {
22    fn new(db: &'a World, system_idx: usize) -> Self;
23
24    /// List of component types this query needs exclusive access to
25    fn components_mut(_set: &mut HashSet<TypeId>) {}
26    /// List of component types this query needs
27    fn components_const(_set: &mut HashSet<TypeId>) {}
28    /// List of resource types this query needs exclusive access to
29    fn resources_mut(_set: &mut HashSet<TypeId>) {}
30    /// List of resource types this query needs
31    fn resources_const(_set: &mut HashSet<TypeId>) {}
32    /// Return wether this system should run in isolation
33    fn exclusive() -> bool {
34        false
35    }
36
37    fn read_only() -> bool {
38        false
39    }
40}
41
42unsafe impl<'a> WorldQuery<'a> for () {
43    fn new(_db: &'a World, _system_idx: usize) -> Self {}
44    fn read_only() -> bool {
45        true
46    }
47}
48
49#[derive(Default)]
50pub struct QueryProperties {
51    pub exclusive: bool,
52    pub comp_mut: HashSet<TypeId>,
53    pub comp_const: HashSet<TypeId>,
54    pub res_mut: HashSet<TypeId>,
55    pub res_const: HashSet<TypeId>,
56}
57
58impl QueryProperties {
59    pub fn is_disjoint(&self, other: &QueryProperties) -> bool {
60        !self.exclusive
61            && !other.exclusive
62            && self.comp_mut.is_disjoint(&other.comp_const)
63            && self.res_mut.is_disjoint(&other.res_const)
64            && self.comp_mut.is_disjoint(&other.comp_mut)
65            && self.res_mut.is_disjoint(&other.res_mut)
66            && self.comp_const.is_disjoint(&other.comp_mut)
67            && self.res_const.is_disjoint(&other.res_mut)
68    }
69
70    pub fn extend(&mut self, props: QueryProperties) {
71        self.exclusive = self.exclusive || props.exclusive;
72        self.comp_mut.extend(props.comp_mut.into_iter());
73        self.res_mut.extend(props.res_mut.into_iter());
74        self.comp_const.extend(props.comp_const.into_iter());
75        self.res_const.extend(props.res_const.into_iter());
76    }
77
78    pub fn is_empty(&self) -> bool {
79        !self.exclusive
80            && self.comp_mut.is_empty()
81            && self.res_mut.is_empty()
82            && self.res_const.is_empty()
83            && self.comp_const.is_empty()
84    }
85
86    pub fn from_system<T>(desc: &SystemDescriptor<T>) -> Self {
87        Self {
88            exclusive: (desc.exclusive)(),
89            comp_mut: (desc.components_mut)(),
90            res_mut: (desc.resources_mut)(),
91            comp_const: (desc.components_const)(),
92            res_const: (desc.resources_const)(),
93        }
94    }
95}
96
97/// Test if this query is valid and return its properties
98#[inline]
99#[allow(unused)]
100pub(crate) fn ensure_query_valid<'a, T: WorldQuery<'a>>() -> QueryProperties {
101    let mut comp_mut = HashSet::new();
102    let mut comp_const = HashSet::new();
103
104    T::components_mut(&mut comp_mut);
105    T::components_const(&mut comp_const);
106
107    assert!(
108        comp_mut.is_disjoint(&comp_const),
109        "A query may not borrow the same type as both mutable and immutable,
110{}",
111        std::any::type_name::<T>()
112    );
113
114    // resources do not need asserts here
115    let mut res_mut = HashSet::new();
116    let mut res_const = HashSet::new();
117    T::resources_mut(&mut res_mut);
118    T::resources_const(&mut res_const);
119    QueryProperties {
120        comp_mut,
121        comp_const,
122        res_mut,
123        res_const,
124        exclusive: T::exclusive(),
125    }
126}
127
128pub struct Query<'a, T, F = ()> {
129    world: std::ptr::NonNull<crate::World>,
130    _m: PhantomData<(T, F)>,
131    _l: PhantomData<&'a ()>,
132}
133
134unsafe impl<T, F> Send for Query<'_, T, F> {}
135unsafe impl<T, F> Sync for Query<'_, T, F> {}
136
137unsafe impl<'a, T, F> WorldQuery<'a> for Query<'a, T, F>
138where
139    T: QueryFragment,
140    F: Filter,
141{
142    fn new(db: &'a World, _system_idx: usize) -> Self {
143        Self::new(db)
144    }
145
146    fn components_mut(set: &mut HashSet<TypeId>) {
147        <T as QueryFragment>::types_mut(set);
148    }
149
150    fn components_const(set: &mut HashSet<TypeId>) {
151        <T as QueryFragment>::types_const(set);
152    }
153
154    fn read_only() -> bool {
155        <T as QueryFragment>::read_only()
156    }
157}
158
159impl<'a, T, F> Query<'a, T, F>
160where
161    T: QueryFragment,
162    F: Filter,
163{
164    pub fn new(world: &'a crate::World) -> Self {
165        Query {
166            world: std::ptr::NonNull::from(world),
167            _m: PhantomData,
168            _l: PhantomData,
169        }
170    }
171
172    /// Return a query that is a subset of this query
173    ///
174    /// Subset means that the child query may not have more components than the original query.
175    ///
176    /// Mutable references may be demoted to const references, but const references may not be
177    /// promoted to mutable references.
178    ///
179    /// The query has to be uniquely borrowed, because the subquery _may_ mutably borrow the same data as the parent query
180    ///
181    /// # Panics
182    ///
183    /// Panics if an invariant no longer holds.
184    ///
185    /// TODO: Can we avoid the unique borrow of the parent Query?
186    ///
187    ///
188    /// ```
189    /// use cecs::prelude::*;
190    /// # #[derive(Clone, Copy)]
191    /// # struct A;
192    /// # #[derive(Clone, Copy)]
193    /// # struct B;
194    /// # #[derive(Clone, Copy)]
195    /// # struct C;
196    ///
197    /// let mut world = World::new(4);
198    ///
199    /// let e = world.insert_entity();
200    /// world.run_system(move |mut cmd: Commands| {
201    ///     cmd.entity(e).insert_bundle((A, B, C));
202    /// });
203    ///
204    /// let mut q = Query::<(EntityId, &mut A, &mut B, &C)>::new(&world);
205    ///
206    /// let sub: Query<(&A, &C, EntityId)> = q.subset();
207    ///
208    /// let mut count = 0;
209    /// for (_a, _c, id) in sub.iter() {
210    ///     assert_eq!(id, e);
211    ///     count += 1;
212    /// }
213    /// assert_eq!(count, 1);
214    /// ```
215    pub fn subset<'b, T1>(&'b mut self) -> Query<'b, T1, F>
216    where
217        T1: QueryFragment,
218        'a: 'b,
219    {
220        #[cfg(debug_assertions)]
221        {
222            let p = ensure_query_valid::<Query<T1, F>>();
223
224            let mut rhs = HashSet::new();
225            Self::components_mut(&mut rhs);
226            let lhs = p.comp_mut;
227
228            assert!(lhs.is_subset(&rhs));
229
230            // T1 const components must be a subset of rhs const+mut
231            Self::components_const(&mut rhs);
232
233            let lhs = p.comp_const;
234            assert!(lhs.is_subset(&rhs));
235        }
236        unsafe { Query::<'b, T1, F>::new(self.world.as_ref()) }
237    }
238
239    /// Restrict this Query with an additional filter
240    /// ```
241    /// use cecs::prelude::*;
242    /// # #[derive(Clone, Copy)]
243    /// # struct A;
244    /// # #[derive(Clone, Copy)]
245    /// # struct B;
246    ///
247    /// let mut world = World::new(4);
248    ///
249    /// let e = world.insert_entity();
250    /// world.run_system(move |mut cmd: Commands| {
251    ///     cmd.entity(e).insert_bundle((A, B));
252    /// });
253    ///
254    /// let mut q = Query::<(EntityId, &mut A)>::new(&world);
255    ///
256    /// let sub = q.with_filter::<WithOut<B>>();
257    ///
258    /// let mut count = 0;
259    /// for _ in sub.iter() {
260    ///     count += 1;
261    /// }
262    /// assert_eq!(count, 0);
263    /// ```
264    pub fn with_filter<'b, F1>(&'b mut self) -> Query<'b, T, (F, F1)>
265    where
266        F1: Filter,
267        'a: 'b,
268    {
269        unsafe { Query::<'b, T, (F, F1)>::new(self.world.as_ref()) }
270    }
271
272    /// Count the number of entities this query spans
273    pub fn count(&self) -> usize {
274        unsafe {
275            self.world
276                .as_ref()
277                .archetypes
278                .iter()
279                .filter(|(_, arch)| F::filter(arch) && T::contains(arch))
280                .map(|(_, arch)| arch.len())
281                .sum::<usize>()
282        }
283    }
284
285    pub fn is_empty(&self) -> bool {
286        unsafe {
287            self.world
288                .as_ref()
289                .archetypes
290                .iter()
291                .filter(|(_, arch)| F::filter(arch) && T::contains(arch))
292                .all(|(_, arch)| arch.is_empty())
293        }
294    }
295
296    pub fn any(&self) -> bool {
297        unsafe {
298            self.world
299                .as_ref()
300                .archetypes
301                .iter()
302                .filter(|(_, arch)| F::filter(arch) && T::contains(arch))
303                .any(|(_, arch)| !arch.is_empty())
304        }
305    }
306
307    pub fn single<'b>(&'b self) -> Option<<T as QueryFragment>::Item<'a>>
308    where
309        'a: 'b,
310    {
311        self.iter().next()
312    }
313
314    pub fn single_mut<'b>(&'b mut self) -> Option<<T as QueryFragment>::ItemMut<'a>>
315    where
316        'a: 'b,
317    {
318        self.iter_mut().next()
319    }
320
321    pub fn iter<'b>(&'b self) -> impl Iterator<Item = <T as QueryFragment>::Item<'a>> + 'b {
322        unsafe {
323            self.world
324                .as_ref()
325                .archetypes
326                .iter()
327                .filter(|(_, arch)| F::filter(arch))
328                .flat_map(|(_, arch)| T::iter(arch))
329        }
330    }
331
332    pub fn iter_mut<'b>(
333        &'b mut self,
334    ) -> impl Iterator<Item = <T as QueryFragment>::ItemMut<'a>> + 'b {
335        unsafe {
336            self.world
337                .as_ref()
338                .archetypes
339                .iter()
340                .filter(|(_, arch)| F::filter(arch))
341                .flat_map(|(_, arch)| T::iter_mut(arch))
342        }
343    }
344
345    /// Unsafe functions let you pass the same query to sub-systems recursively splitting workload
346    /// on multiple threads.
347    ///
348    /// The top-level system still needs &mut access to the components.
349    pub unsafe fn iter_unsafe(
350        &'a self,
351    ) -> impl Iterator<Item = <T as QueryFragment>::ItemUnsafe<'a>> {
352        unsafe {
353            self.world
354                .as_ref()
355                .archetypes
356                .iter()
357                .filter(|(_, arch)| F::filter(arch))
358                .flat_map(|(_, arch)| T::iter_unsafe(arch))
359        }
360    }
361
362    pub fn fetch<'b>(&'b self, id: EntityId) -> Option<<T as QueryFragment>::Item<'b>>
363    where
364        'a: 'b,
365    {
366        unsafe {
367            let (arch, index) = self.world.as_ref().entity_ids().read(id).ok()?;
368            if !F::filter(arch.as_ref()) {
369                return None;
370            }
371
372            T::fetch(arch.as_ref(), index)
373        }
374    }
375
376    pub fn fetch_mut<'b>(&'b mut self, id: EntityId) -> Option<<T as QueryFragment>::ItemMut<'b>>
377    where
378        'a: 'b,
379    {
380        unsafe {
381            let (arch, index) = self.world.as_ref().entity_ids().read(id).ok()?;
382            if !F::filter(arch.as_ref()) {
383                return None;
384            }
385
386            T::fetch_mut(arch.as_ref(), index)
387        }
388    }
389
390    pub unsafe fn fetch_unsafe(
391        &'a self,
392        id: EntityId,
393    ) -> Option<<T as QueryFragment>::ItemUnsafe<'a>> {
394        unsafe {
395            let (arch, index) = self.world.as_ref().entity_ids().read(id).ok()?;
396            if !F::filter(arch.as_ref()) {
397                return None;
398            }
399
400            T::fetch_unsafe(arch.as_ref(), index)
401        }
402    }
403
404    pub fn contains(&self, id: EntityId) -> bool {
405        unsafe {
406            let (arch, _index) = match self.world.as_ref().entity_ids().read(id).ok() {
407                None => return false,
408                Some(x) => x,
409            };
410            if !F::filter(arch.as_ref()) {
411                return false;
412            }
413
414            T::contains(arch.as_ref())
415        }
416    }
417
418    /// fetch the first row of the query
419    /// panic if no row was found
420    pub fn one(&'a self) -> <T as QueryFragment>::Item<'a> {
421        self.iter().next().unwrap()
422    }
423
424    #[cfg(feature = "parallel")]
425    pub fn par_for_each<'b>(&'b self, f: impl Fn(<T as QueryFragment>::Item<'a>) + Sync + 'b)
426    where
427        T: Send + Sync,
428    {
429        unsafe {
430            let world = self.world.as_ref();
431            let pool = &world.job_system;
432            pool.scope(|s| {
433                let f = &f;
434                world
435                    .archetypes
436                    .iter()
437                    // TODO: should filters run inside the jobs instead?
438                    // currently I anticipate that filters are inexpensive, so it seems cheaper to
439                    // filter ahead of job creation
440                    .filter(|(_, arch)| !arch.is_empty() && F::filter(arch))
441                    .for_each(|(_, arch)| {
442                        let batch_size = arch.len() / pool.parallelism() + 1;
443                        // TODO: the job allocator could probably help greatly with these jobs
444                        for range in batches(arch.len(), batch_size) {
445                            s.spawn(move |_s| {
446                                for t in T::iter_range(arch, range) {
447                                    f(t);
448                                }
449                            })
450                        }
451                    });
452            });
453        }
454    }
455
456    #[cfg(feature = "parallel")]
457    pub fn par_for_each_mut<'b>(
458        &'b mut self,
459        f: impl Fn(<T as QueryFragment>::ItemMut<'a>) + Sync + 'b,
460    ) where
461        T: Send + Sync,
462    {
463        unsafe {
464            let world = self.world.as_ref();
465            let pool = &world.job_system;
466            pool.scope(|s| {
467                let f = &f;
468                world
469                    .archetypes
470                    .iter()
471                    // TODO: should filters run inside the jobs instead?
472                    // currently I anticipate that filters are inexpensive, so it seems cheaper to
473                    // filter ahead of job creation
474                    .filter(|(_, arch)| !arch.is_empty() && F::filter(arch))
475                    .for_each(|(_, arch)| {
476                        // TODO: should take size of queried types into account?
477                        let batch_size = arch.len() / pool.parallelism() + 1;
478
479                        // TODO: the job allocator could probably help greatly with these jobs
480                        for range in batches(arch.len(), batch_size) {
481                            s.spawn(move |_s| {
482                                for t in T::iter_range_mut(arch, range) {
483                                    f(t);
484                                }
485                            })
486                        }
487                    });
488            });
489        }
490    }
491
492    #[cfg(not(feature = "parallel"))]
493    pub fn par_for_each<'b>(&'b self, f: impl Fn(<T as QueryFragment>::Item<'a>) + 'b) {
494        self.iter().for_each(f);
495    }
496
497    #[cfg(not(feature = "parallel"))]
498    pub fn par_for_each_mut<'b>(&'b mut self, f: impl Fn(<T as QueryFragment>::ItemMut<'a>) + 'b) {
499        self.iter_mut().for_each(f);
500    }
501}
502
503#[allow(unused)]
504fn batches(len: usize, batch_size: usize) -> impl Iterator<Item = impl RangeBounds<usize> + Clone> {
505    (0..len / batch_size)
506        .map(move |i| {
507            let s = i * batch_size;
508            s..s + batch_size
509        })
510        // last batch if len is not divisible by batch_size
511        // otherwise it's an empty range
512        .chain(std::iter::once((len - (len % batch_size))..len))
513}
514
515pub trait QueryFragment {
516    type ItemUnsafe<'a>;
517    type ItUnsafe<'a>: Iterator<Item = Self::ItemUnsafe<'a>>;
518    type Item<'a>;
519    type It<'a>: Iterator<Item = Self::Item<'a>>;
520    type ItemMut<'a>;
521    type ItMut<'a>: Iterator<Item = Self::ItemMut<'a>>;
522
523    unsafe fn iter_unsafe(archetype: &EntityTable) -> Self::ItUnsafe<'_>;
524    unsafe fn fetch_unsafe(
525        archetype: &EntityTable,
526        index: RowIndex,
527    ) -> Option<Self::ItemUnsafe<'_>>;
528    fn iter(archetype: &EntityTable) -> Self::It<'_>;
529    fn iter_mut(archetype: &EntityTable) -> Self::ItMut<'_>;
530    fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>>;
531    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>>;
532    fn types_mut(set: &mut HashSet<TypeId>);
533    fn types_const(set: &mut HashSet<TypeId>);
534    fn contains(archetype: &EntityTable) -> bool;
535    fn read_only() -> bool;
536    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize> + Clone) -> Self::It<'_>;
537    fn iter_range_mut(
538        archetype: &EntityTable,
539        range: impl RangeBounds<usize> + Clone,
540    ) -> Self::ItMut<'_>;
541}
542
543/// Query wether an entity has a component
544///
545/// Shortcut for `Option<&T>::is_some()`
546///
547/// In general one should prefer the use of [[With]] and [[WithOut]] filters. But sometimes it can
548/// be convenient to use the Has query.
549/// ```
550/// # use cecs::prelude::*;
551/// # let mut world = World::new(4);
552/// # #[derive(Debug, Clone, Copy)]
553/// # struct Foo;
554/// #
555/// # world.run_system(|mut cmd: Commands| {
556/// #   for i in 0..4 {
557/// #     cmd.spawn().insert(Foo);
558/// #   }
559/// # });
560///
561/// fn system(q: Query<(Option<&Foo>, Has<Foo>)>) {
562/// #   assert_eq!(q.count(), 4);
563///     for (opt, has) in q.iter() {
564///         assert_eq!(opt.is_some(), has);
565///     }
566/// }
567///
568/// # world.run_system(system).unwrap();
569/// ```
570pub struct Has<T>(PhantomData<T>);
571
572impl<T: Component> QueryFragment for Has<T> {
573    type ItemUnsafe<'a> = bool;
574    type ItUnsafe<'a> = Self::It<'a>;
575    type Item<'a> = bool;
576    type It<'a> = std::iter::Take<std::iter::Repeat<bool>>;
577    type ItemMut<'a> = bool;
578    type ItMut<'a> = Self::It<'a>;
579
580    unsafe fn iter_unsafe<'a>(archetype: &'a EntityTable) -> Self::ItUnsafe<'a> {
581        Self::iter(archetype)
582    }
583
584    unsafe fn fetch_unsafe(
585        archetype: &EntityTable,
586        index: RowIndex,
587    ) -> Option<Self::ItemUnsafe<'_>> {
588        Self::fetch(archetype, index)
589    }
590
591    fn iter<'a>(archetype: &'a EntityTable) -> Self::It<'a> {
592        std::iter::repeat(archetype.contains_column::<T>()).take(archetype.len())
593    }
594
595    fn iter_mut<'a>(archetype: &'a EntityTable) -> Self::ItMut<'a> {
596        Self::iter(archetype)
597    }
598
599    fn fetch(archetype: &EntityTable, _index: RowIndex) -> Option<Self::Item<'_>> {
600        Some(archetype.contains_column::<T>())
601    }
602
603    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
604        Self::fetch(archetype, index)
605    }
606
607    fn contains(_archetype: &EntityTable) -> bool {
608        true
609    }
610
611    fn types_mut(_set: &mut HashSet<TypeId>) {
612        // noop
613    }
614
615    fn types_const(_set: &mut HashSet<TypeId>) {
616        // noop
617        // Do not care about mutations to component T, only wether it is present in the archetype
618    }
619
620    fn read_only() -> bool {
621        true
622    }
623
624    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize>) -> Self::It<'_> {
625        let len = archetype.entities.len();
626        let range = slice::range(range, ..len);
627        let len = range.len();
628        std::iter::repeat(archetype.contains_column::<T>()).take(len)
629    }
630
631    fn iter_range_mut(
632        archetype: &EntityTable,
633        range: impl RangeBounds<usize> + Clone,
634    ) -> Self::ItMut<'_> {
635        Self::iter_range(archetype, range)
636    }
637}
638
639impl QueryFragment for EntityId {
640    type ItemUnsafe<'a> = EntityId;
641    type ItUnsafe<'a> = std::iter::Copied<std::slice::Iter<'a, EntityId>>;
642    type Item<'a> = EntityId;
643    type It<'a> = std::iter::Copied<std::slice::Iter<'a, EntityId>>;
644    type ItemMut<'a> = EntityId;
645    type ItMut<'a> = std::iter::Copied<std::slice::Iter<'a, EntityId>>;
646
647    unsafe fn iter_unsafe<'a>(archetype: &'a EntityTable) -> Self::ItUnsafe<'a> {
648        archetype.entities.iter().copied()
649    }
650
651    unsafe fn fetch_unsafe(
652        archetype: &EntityTable,
653        index: RowIndex,
654    ) -> Option<Self::ItemUnsafe<'_>> {
655        archetype.entities.get(index as usize).copied()
656    }
657
658    fn iter<'a>(archetype: &'a EntityTable) -> Self::It<'a> {
659        archetype.entities.iter().copied()
660    }
661
662    fn iter_mut<'a>(archetype: &'a EntityTable) -> Self::ItMut<'a> {
663        Self::iter(archetype)
664    }
665
666    fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>> {
667        archetype.entities.get(index as usize).copied()
668    }
669
670    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
671        Self::fetch(archetype, index)
672    }
673
674    fn contains(_archetype: &EntityTable) -> bool {
675        true
676    }
677
678    fn types_mut(_set: &mut HashSet<TypeId>) {
679        // noop
680    }
681
682    fn types_const(_set: &mut HashSet<TypeId>) {
683        // noop
684        // entity_id is not considered while scheduling
685    }
686
687    fn read_only() -> bool {
688        true
689    }
690
691    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize>) -> Self::It<'_> {
692        let len = archetype.entities.len();
693        let range = slice::range(range, ..len);
694        archetype.entities[range].iter().copied()
695    }
696
697    fn iter_range_mut(
698        archetype: &EntityTable,
699        range: impl RangeBounds<usize> + Clone,
700    ) -> Self::ItMut<'_> {
701        Self::iter_range(archetype, range)
702    }
703}
704
705impl QueryFragment for ArchetypeHash {
706    type ItemUnsafe<'a> = ArchetypeHash;
707    type Item<'a> = ArchetypeHash;
708    type ItemMut<'a> = ArchetypeHash;
709    type It<'a> = Box<dyn Iterator<Item = Self::Item<'a>> + 'a>;
710    type ItUnsafe<'a> = Self::It<'a>;
711    type ItMut<'a> = Self::It<'a>;
712
713    unsafe fn iter_unsafe<'a>(archetype: &'a EntityTable) -> Self::ItUnsafe<'a> {
714        Self::iter(archetype)
715    }
716
717    unsafe fn fetch_unsafe(
718        archetype: &EntityTable,
719        index: RowIndex,
720    ) -> Option<Self::ItemUnsafe<'_>> {
721        Self::fetch(archetype, index)
722    }
723
724    fn iter<'a>(archetype: &'a EntityTable) -> Self::It<'a> {
725        let hash = archetype.ty;
726        Box::new((0..archetype.rows).map(move |_| ArchetypeHash(hash)))
727    }
728
729    fn iter_mut<'a>(archetype: &'a EntityTable) -> Self::ItMut<'a> {
730        Self::iter(archetype)
731    }
732
733    fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>> {
734        archetype
735            .entities
736            .get(index as usize)
737            .map(|_| ArchetypeHash(archetype.ty))
738    }
739
740    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
741        Self::fetch(archetype, index)
742    }
743
744    fn contains(_archetype: &EntityTable) -> bool {
745        true
746    }
747
748    fn types_mut(_set: &mut HashSet<TypeId>) {
749        // noop
750    }
751
752    fn types_const(_set: &mut HashSet<TypeId>) {
753        // noop
754    }
755
756    fn read_only() -> bool {
757        true
758    }
759
760    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize>) -> Self::It<'_> {
761        let len = archetype.entities.len();
762        let range = slice::range(range, ..len);
763        let hash = archetype.ty;
764        Box::new(
765            archetype.entities[range]
766                .iter()
767                .map(move |_| ArchetypeHash(hash)),
768        )
769    }
770
771    fn iter_range_mut(
772        archetype: &EntityTable,
773        range: impl RangeBounds<usize> + Clone,
774    ) -> Self::ItMut<'_> {
775        Self::iter_range(archetype, range)
776    }
777}
778
779// Optional query fetch functions return Option<Option<T>> where the outer optional is always Some.
780// This awkward interface is there because of combined queries
781//
782impl<'a, T: Component> QueryFragment for Option<&'a T> {
783    type ItemUnsafe<'b> = Option<*mut T>;
784    type ItUnsafe<'b> = Box<dyn Iterator<Item = Self::ItemUnsafe<'b>> + 'b>;
785    type Item<'b> = Option<&'b T>;
786    type It<'b> = Box<dyn Iterator<Item = Self::Item<'b>> + 'b>;
787    type ItemMut<'b> = Option<&'b T>;
788    type ItMut<'b> = Box<dyn Iterator<Item = Self::ItemMut<'b>> + 'b>;
789
790    fn iter(archetype: &EntityTable) -> Self::It<'_> {
791        match archetype.components.get(&TypeId::of::<T>()) {
792            Some(columns) => {
793                Box::new(unsafe { (&*columns.get()).as_slice::<T>().iter() }.map(Some))
794            }
795            None => Box::new((0..archetype.rows).map(|_| None)),
796        }
797    }
798
799    fn iter_mut(archetype: &EntityTable) -> Self::ItMut<'_> {
800        <Self as QueryFragment>::iter(archetype)
801    }
802
803    unsafe fn iter_unsafe(archetype: &EntityTable) -> Self::ItUnsafe<'_> {
804        match archetype.components.get(&TypeId::of::<T>()) {
805            Some(columns) => Box::new(
806                unsafe { (&mut *columns.get()).as_slice_mut::<T>().iter_mut() }
807                    .map(|x| x as *mut _)
808                    .map(Some),
809            ),
810            None => Box::new((0..archetype.rows).map(|_| None)),
811        }
812    }
813
814    fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>> {
815        Some(archetype.get_component::<T>(index))
816    }
817
818    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
819        Self::fetch(archetype, index)
820    }
821
822    unsafe fn fetch_unsafe(
823        archetype: &EntityTable,
824        index: RowIndex,
825    ) -> Option<Self::ItemUnsafe<'_>> {
826        unsafe { Some(archetype.get_component_mut::<T>(index).map(|x| x as *mut _)) }
827    }
828
829    fn types_mut(_set: &mut HashSet<TypeId>) {
830        // noop
831    }
832
833    fn types_const(set: &mut HashSet<TypeId>) {
834        set.insert(TypeId::of::<T>());
835    }
836
837    fn contains(_archetype: &EntityTable) -> bool {
838        true
839    }
840
841    fn read_only() -> bool {
842        true
843    }
844
845    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize>) -> Self::It<'_> {
846        let len = archetype.len();
847        let range = slice::range(range, ..len);
848        match archetype.components.get(&TypeId::of::<T>()) {
849            Some(columns) => unsafe {
850                let col = (&*columns.get()).as_slice::<T>();
851                Box::new(col[range].iter().map(Some))
852            },
853            None => Box::new(range.into_iter().map(|_| None)),
854        }
855    }
856
857    fn iter_range_mut(
858        archetype: &EntityTable,
859        range: impl RangeBounds<usize> + Clone,
860    ) -> Self::ItMut<'_> {
861        Self::iter_range(archetype, range)
862    }
863}
864
865impl<'a, T: Component> QueryFragment for Option<&'a mut T> {
866    type ItemUnsafe<'b> = Option<*mut T>;
867    type ItUnsafe<'b> = Box<dyn Iterator<Item = Self::ItemUnsafe<'b>> + 'b>;
868    type Item<'b> = Option<&'b T>;
869    type It<'b> = Box<dyn Iterator<Item = Self::Item<'b>> + 'b>;
870    type ItemMut<'b> = Option<&'b mut T>;
871    type ItMut<'b> = Box<dyn Iterator<Item = Self::ItemMut<'b>> + 'b>;
872
873    fn iter(archetype: &EntityTable) -> Self::It<'_> {
874        match archetype.components.get(&TypeId::of::<T>()) {
875            Some(columns) => {
876                Box::new(unsafe { (&*columns.get()).as_slice::<T>().iter() }.map(Some))
877            }
878            None => Box::new((0..archetype.rows).map(|_| None)),
879        }
880    }
881
882    fn iter_mut(archetype: &EntityTable) -> Self::ItMut<'_> {
883        match archetype.components.get(&TypeId::of::<T>()) {
884            Some(columns) => {
885                Box::new(unsafe { (&mut *columns.get()).as_slice_mut::<T>().iter_mut() }.map(Some))
886            }
887            None => Box::new((0..archetype.rows).map(|_| None)),
888        }
889    }
890
891    unsafe fn iter_unsafe(archetype: &EntityTable) -> Self::ItUnsafe<'_> {
892        match archetype.components.get(&TypeId::of::<T>()) {
893            Some(columns) => Box::new(
894                unsafe { (&mut *columns.get()).as_slice_mut::<T>().iter_mut() }
895                    .map(|x| x as *mut _)
896                    .map(Some),
897            ),
898            None => Box::new((0..archetype.rows).map(|_| None)),
899        }
900    }
901
902    fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>> {
903        Some(archetype.get_component::<T>(index))
904    }
905
906    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
907        Some(unsafe { archetype.get_component_mut::<T>(index) })
908    }
909
910    unsafe fn fetch_unsafe(
911        archetype: &EntityTable,
912        index: RowIndex,
913    ) -> Option<Self::ItemUnsafe<'_>> {
914        unsafe { Some(archetype.get_component_mut::<T>(index).map(|x| x as *mut _)) }
915    }
916
917    fn types_mut(set: &mut HashSet<TypeId>) {
918        set.insert(TypeId::of::<T>());
919    }
920
921    fn types_const(_set: &mut HashSet<TypeId>) {
922        // noop
923    }
924
925    fn contains(_archetype: &EntityTable) -> bool {
926        true
927    }
928
929    fn read_only() -> bool {
930        false
931    }
932
933    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize>) -> Self::It<'_> {
934        let len = archetype.len();
935        let range = slice::range(range, ..len);
936        match archetype.components.get(&TypeId::of::<T>()) {
937            Some(columns) => unsafe {
938                let col = (&*columns.get()).as_slice::<T>();
939                Box::new(col[range].iter().map(Some))
940            },
941            None => Box::new(range.into_iter().map(|_| None)),
942        }
943    }
944
945    fn iter_range_mut(
946        archetype: &EntityTable,
947        range: impl RangeBounds<usize> + Clone,
948    ) -> Self::ItMut<'_> {
949        let len = archetype.len();
950        let range = slice::range(range, ..len);
951        match archetype.components.get(&TypeId::of::<T>()) {
952            Some(columns) => unsafe {
953                let col = (&mut *columns.get()).as_slice_mut::<T>();
954                Box::new(col[range].iter_mut().map(Some))
955            },
956            None => Box::new(range.into_iter().map(|_| None)),
957        }
958    }
959}
960
961impl<'a, T: Component> QueryFragment for &'a T {
962    type ItemUnsafe<'b> = *mut T;
963    type ItUnsafe<'b> = Box<dyn Iterator<Item = Self::ItemUnsafe<'b>>>;
964    type Item<'b> = &'b T;
965    type It<'b> = std::iter::Flatten<std::option::IntoIter<std::slice::Iter<'b, T>>>;
966    type ItemMut<'b> = &'b T;
967    type ItMut<'b> = std::iter::Flatten<std::option::IntoIter<std::slice::Iter<'b, T>>>;
968
969    fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>> {
970        archetype.get_component::<T>(index)
971    }
972
973    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
974        Self::fetch(archetype, index)
975    }
976
977    unsafe fn fetch_unsafe(
978        archetype: &EntityTable,
979        index: RowIndex,
980    ) -> Option<Self::ItemUnsafe<'_>> {
981        unsafe { archetype.get_component_mut::<T>(index).map(|x| x as *mut _) }
982    }
983
984    fn contains(archetype: &EntityTable) -> bool {
985        archetype.contains_column::<T>()
986    }
987
988    fn types_mut(_set: &mut HashSet<TypeId>) {
989        // noop
990    }
991
992    fn types_const(set: &mut HashSet<TypeId>) {
993        set.insert(TypeId::of::<T>());
994    }
995
996    fn iter(archetype: &EntityTable) -> Self::It<'_> {
997        archetype
998            .components
999            .get(&TypeId::of::<T>())
1000            .map(|columns| unsafe { (&*columns.get()).as_slice::<T>().iter() })
1001            .into_iter()
1002            .flatten()
1003    }
1004
1005    fn iter_mut(archetype: &EntityTable) -> Self::ItMut<'_> {
1006        Self::iter(archetype)
1007    }
1008
1009    unsafe fn iter_unsafe(archetype: &EntityTable) -> Self::ItUnsafe<'_> {
1010        Box::new(
1011            archetype
1012                .components
1013                .get(&TypeId::of::<T>())
1014                .map(|columns| unsafe {
1015                    let slice = (&mut *columns.get()).as_slice_mut::<T>();
1016                    let ptr = slice.as_mut_ptr();
1017                    let len = slice.len();
1018                    (0..len).map(move |i| ptr.add(i))
1019                })
1020                .into_iter()
1021                .flatten(),
1022        )
1023    }
1024
1025    fn read_only() -> bool {
1026        true
1027    }
1028
1029    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize>) -> Self::ItMut<'_> {
1030        archetype
1031            .components
1032            .get(&TypeId::of::<T>())
1033            .map(|columns| unsafe {
1034                let col = (&*columns.get()).as_slice::<T>();
1035                let len = col.len();
1036                let range = slice::range(range, ..len);
1037                col[range].iter()
1038            })
1039            .into_iter()
1040            .flatten()
1041    }
1042
1043    fn iter_range_mut(
1044        archetype: &EntityTable,
1045        range: impl RangeBounds<usize> + Clone,
1046    ) -> Self::ItMut<'_> {
1047        Self::iter_range(archetype, range)
1048    }
1049}
1050
1051impl<'a, T: Component> QueryFragment for &'a mut T {
1052    type ItemUnsafe<'b> = *mut T;
1053    type ItUnsafe<'b> = Box<dyn Iterator<Item = *mut T>>;
1054    type Item<'b> = &'b T;
1055    type It<'b> = std::iter::Flatten<std::option::IntoIter<std::slice::Iter<'b, T>>>;
1056    type ItemMut<'b> = &'b mut T;
1057    type ItMut<'b> = std::iter::Flatten<std::option::IntoIter<std::slice::IterMut<'b, T>>>;
1058
1059    fn iter(archetype: &EntityTable) -> Self::It<'_> {
1060        archetype
1061            .components
1062            .get(&TypeId::of::<T>())
1063            .map(|columns| unsafe { (&*columns.get()).as_slice::<T>().iter() })
1064            .into_iter()
1065            .flatten()
1066    }
1067
1068    fn iter_mut(archetype: &EntityTable) -> Self::ItMut<'_> {
1069        archetype
1070            .components
1071            .get(&TypeId::of::<T>())
1072            .map(|columns| unsafe { (&mut *columns.get()).as_slice_mut::<T>().iter_mut() })
1073            .into_iter()
1074            .flatten()
1075    }
1076
1077    unsafe fn iter_unsafe(archetype: &EntityTable) -> Self::ItUnsafe<'_> {
1078        Box::new(
1079            archetype
1080                .components
1081                .get(&TypeId::of::<T>())
1082                .map(|columns| unsafe {
1083                    let slice = (&mut *columns.get()).as_slice_mut::<T>();
1084                    let ptr = slice.as_mut_ptr();
1085                    let len = slice.len();
1086                    (0..len).map(move |i| ptr.add(i))
1087                })
1088                .into_iter()
1089                .flatten(),
1090        )
1091    }
1092
1093    fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>> {
1094        archetype.get_component::<T>(index)
1095    }
1096
1097    fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
1098        unsafe { archetype.get_component_mut::<T>(index) }
1099    }
1100
1101    unsafe fn fetch_unsafe(
1102        archetype: &EntityTable,
1103        index: RowIndex,
1104    ) -> Option<Self::ItemUnsafe<'_>> {
1105        unsafe { archetype.get_component_mut::<T>(index).map(|x| x as *mut _) }
1106    }
1107
1108    fn contains(archetype: &EntityTable) -> bool {
1109        archetype.contains_column::<T>()
1110    }
1111
1112    fn types_mut(set: &mut HashSet<TypeId>) {
1113        let ty = TypeId::of::<T>();
1114        debug_assert!(!set.contains(&ty), "A query may only borrow a type once");
1115        set.insert(ty);
1116    }
1117
1118    fn types_const(_set: &mut HashSet<TypeId>) {
1119        // noop
1120    }
1121
1122    fn read_only() -> bool {
1123        false
1124    }
1125
1126    fn iter_range(archetype: &EntityTable, range: impl RangeBounds<usize>) -> Self::It<'_> {
1127        archetype
1128            .components
1129            .get(&TypeId::of::<T>())
1130            .map(|columns| unsafe {
1131                let col = (&mut *columns.get()).as_slice::<T>();
1132                let len = col.len();
1133                let range = slice::range(range, ..len);
1134                col[range].iter()
1135            })
1136            .into_iter()
1137            .flatten()
1138    }
1139
1140    fn iter_range_mut(
1141        archetype: &EntityTable,
1142        range: impl RangeBounds<usize> + Clone,
1143    ) -> Self::ItMut<'_> {
1144        archetype
1145            .components
1146            .get(&TypeId::of::<T>())
1147            .map(|columns| unsafe {
1148                let col = (&mut *columns.get()).as_slice_mut::<T>();
1149                let len = col.len();
1150                let range = slice::range(range, ..len);
1151                col[range].iter_mut()
1152            })
1153            .into_iter()
1154            .flatten()
1155    }
1156}
1157
1158// macro implementing more combinations
1159//
1160
1161pub struct TupleIterator<Inner>(Inner);
1162
1163unsafe impl<Inner> Send for TupleIterator<Inner> {}
1164unsafe impl<Inner> Sync for TupleIterator<Inner> {}
1165
1166macro_rules! impl_tuple {
1167    ($($idx: tt : $t: ident),+ $(,)?) => {
1168        impl<$($t,)+> Iterator for TupleIterator<
1169            ($($t),+)
1170        >
1171        where
1172            $( $t: Iterator ),+
1173        {
1174            type Item = ( $( $t::Item ),* );
1175
1176            fn next(&mut self) -> Option<Self::Item> {
1177                Some((
1178                    $(
1179                        // TODO: optimization opportunity: only call next() on the first iterator
1180                        // and call next_unchecked() on the rest
1181                        self.0.$idx.next()?
1182                    ),+
1183                ))
1184            }
1185        }
1186
1187        impl<$($t,)+> QueryFragment for ($($t,)+)
1188        where
1189        $(
1190            $t: QueryFragment,
1191        )+
1192        {
1193            type ItemUnsafe<'a> = ($(<$t as QueryFragment>::ItemUnsafe<'a>),+);
1194            type ItUnsafe<'a> = TupleIterator<($(<$t as QueryFragment>::ItUnsafe<'a>,)+)>;
1195            type Item<'a> = ($(<$t as QueryFragment>::Item<'a>),+);
1196            type It<'a> = TupleIterator<($(<$t as QueryFragment>::It<'a>,)+)>;
1197            type ItemMut<'a> = ($(<$t as QueryFragment>::ItemMut<'a>),+);
1198            type ItMut<'a> = TupleIterator<($(<$t as QueryFragment>::ItMut<'a>,)+)>;
1199
1200            fn iter(archetype: &EntityTable) -> Self::It<'_>
1201            {
1202                TupleIterator(($( $t::iter(archetype) ),+))
1203            }
1204
1205            fn iter_mut(archetype: &EntityTable) -> Self::ItMut<'_>
1206            {
1207                TupleIterator(($( $t::iter_mut(archetype) ),+))
1208            }
1209
1210            fn iter_range(
1211                archetype: &EntityTable,
1212                range: impl RangeBounds<usize> + Clone,
1213            ) -> Self::It<'_> {
1214                TupleIterator(($( $t::iter_range(archetype, range.clone()) ),+))
1215            }
1216
1217            fn iter_range_mut(
1218                archetype: &EntityTable,
1219                range: impl RangeBounds<usize> + Clone,
1220            ) -> Self::ItMut<'_> {
1221                TupleIterator(($( $t::iter_range_mut(archetype, range.clone()) ),+))
1222            }
1223
1224            unsafe fn iter_unsafe(archetype: &EntityTable) -> Self::ItUnsafe<'_>
1225            {
1226                unsafe {
1227                    TupleIterator(($( $t::iter_unsafe(archetype) ),+))
1228                }
1229            }
1230
1231            fn fetch(archetype: &EntityTable, index: RowIndex) -> Option<Self::Item<'_>> {
1232                Some((
1233                    $(
1234                        $t::fetch(archetype, index)?,
1235                    )*
1236                ))
1237            }
1238
1239            fn fetch_mut(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemMut<'_>> {
1240                Some((
1241                    $(
1242                        $t::fetch_mut(archetype, index)?,
1243                    )*
1244                ))
1245            }
1246
1247            unsafe fn fetch_unsafe(archetype: &EntityTable, index: RowIndex) -> Option<Self::ItemUnsafe<'_>> {
1248                unsafe {
1249                    Some((
1250                        $(
1251                            $t::fetch_unsafe(archetype, index)?,
1252                        )*
1253                    ))
1254                }
1255            }
1256
1257            fn contains(archetype: &EntityTable) -> bool {
1258                    $(
1259                        $t::contains(archetype)
1260                    )&&*
1261            }
1262
1263            fn types_mut(set: &mut HashSet<TypeId>) {
1264                $(<$t as QueryFragment>::types_mut(set));+
1265            }
1266
1267            fn types_const(set: &mut HashSet<TypeId>) {
1268                $(<$t as QueryFragment>::types_const(set));+
1269            }
1270
1271            fn read_only() -> bool {
1272                $(<$t as QueryFragment>::read_only())&&+
1273            }
1274        }
1275
1276        unsafe impl<'a, $($t,)+> WorldQuery<'a> for ($($t,)+)
1277        where
1278            $(
1279                $t: WorldQuery<'a>,
1280            )+
1281        {
1282            fn new(db: &'a World, system_idx: usize) -> Self {
1283                (
1284                    $(
1285                    <$t as WorldQuery>::new(db, system_idx),
1286                    )+
1287                )
1288            }
1289
1290            fn exclusive() -> bool {
1291                $(<$t as WorldQuery>::exclusive())||+
1292            }
1293
1294            fn read_only() -> bool {
1295                $(<$t as WorldQuery>::read_only())&&+
1296            }
1297
1298            fn resources_const(_set: &mut HashSet<TypeId>) {
1299                $(<$t as WorldQuery>::resources_const(_set));+
1300            }
1301            fn resources_mut(_set: &mut HashSet<TypeId>) {
1302                $(<$t as WorldQuery>::resources_mut(_set));+
1303            }
1304            fn components_const(_set: &mut HashSet<TypeId>) {
1305                $(<$t as WorldQuery>::components_const(_set));+
1306            }
1307            fn components_mut(_set: &mut HashSet<TypeId>) {
1308                $(<$t as WorldQuery>::components_mut(_set));+
1309            }
1310        }
1311    };
1312}
1313
1314impl_tuple!(0: T0, 1: T1);
1315impl_tuple!(0: T0, 1: T1, 2: T2);
1316impl_tuple!(0: T0, 1: T1, 2: T2, 3: T3);
1317impl_tuple!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4);
1318impl_tuple!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5);
1319impl_tuple!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6);
1320impl_tuple!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7);
1321impl_tuple!(
1322    0: T0,
1323    1: T1,
1324    2: T2,
1325    3: T3,
1326    4: T4,
1327    5: T5,
1328    6: T6,
1329    7: T7,
1330    8: T8
1331);
1332impl_tuple!(
1333    0: T0,
1334    1: T1,
1335    2: T2,
1336    3: T3,
1337    4: T4,
1338    5: T5,
1339    6: T6,
1340    7: T7,
1341    8: T8,
1342    9: T9
1343);
1344impl_tuple!(
1345    0: T0,
1346    1: T1,
1347    2: T2,
1348    3: T3,
1349    4: T4,
1350    5: T5,
1351    6: T6,
1352    7: T7,
1353    8: T8,
1354    9: T9,
1355    10: T10
1356);
1357impl_tuple!(
1358    0: T0,
1359    1: T1,
1360    2: T2,
1361    3: T3,
1362    4: T4,
1363    5: T5,
1364    6: T6,
1365    7: T7,
1366    8: T8,
1367    9: T9,
1368    10: T10,
1369    11: T11
1370);
1371impl_tuple!(
1372    0: T0,
1373    1: T1,
1374    2: T2,
1375    3: T3,
1376    4: T4,
1377    5: T5,
1378    6: T6,
1379    7: T7,
1380    8: T8,
1381    9: T9,
1382    10: T10,
1383    11: T11,
1384    12: T12
1385);
1386impl_tuple!(
1387    0: T0,
1388    1: T1,
1389    2: T2,
1390    3: T3,
1391    4: T4,
1392    5: T5,
1393    6: T6,
1394    7: T7,
1395    8: T8,
1396    9: T9,
1397    10: T10,
1398    11: T11,
1399    12: T12,
1400    13: T13
1401);
1402impl_tuple!(
1403    0: T0,
1404    1: T1,
1405    2: T2,
1406    3: T3,
1407    4: T4,
1408    5: T5,
1409    6: T6,
1410    7: T7,
1411    8: T8,
1412    9: T9,
1413    10: T10,
1414    11: T11,
1415    12: T12,
1416    13: T13,
1417    14: T14
1418);
1419impl_tuple!(
1420    0: T0,
1421    1: T1,
1422    2: T2,
1423    3: T3,
1424    4: T4,
1425    5: T5,
1426    6: T6,
1427    7: T7,
1428    8: T8,
1429    9: T9,
1430    10: T10,
1431    11: T11,
1432    12: T12,
1433    13: T13,
1434    14: T14,
1435    15: T15
1436);