my_ecs/ecs/sys/
query.rs

1use super::select::{
2    FilterInfo, FilterKey, FilteredRaw, SelectInfo, SelectKey, SelectedRaw, StoreSelectInfo,
3};
4use crate::{
5    ds::{ATypeId, Borrowed, ManagedConstPtr, ManagedMutPtr, NonNullExt},
6    ecs::resource::ResourceKey,
7    util::TakeRecur,
8};
9use my_ecs_macros::repeat_macro;
10use std::{
11    fmt,
12    ops::{Deref, DerefMut},
13    sync::Arc,
14};
15
16pub(crate) trait StoreQueryInfo: StoreSelectInfo {
17    fn contains(&self, key: &QueryKey) -> bool;
18    fn get(&self, key: &QueryKey) -> Option<&Arc<QueryInfo>>;
19    fn insert(&mut self, key: QueryKey, info: Arc<QueryInfo>);
20}
21
22pub(crate) trait StoreResQueryInfo {
23    fn contains(&self, key: &ResQueryKey) -> bool;
24    fn get(&self, key: &ResQueryKey) -> Option<&Arc<ResQueryInfo>>;
25    fn insert(&mut self, key: ResQueryKey, info: Arc<ResQueryInfo>);
26}
27
28pub(crate) trait StoreEntQueryInfo: StoreSelectInfo {
29    fn contains(&self, key: &EntQueryKey) -> bool;
30    fn get(&self, key: &EntQueryKey) -> Option<&Arc<EntQueryInfo>>;
31    fn insert(&mut self, key: EntQueryKey, info: Arc<EntQueryInfo>);
32}
33
34#[allow(private_interfaces, private_bounds)]
35pub trait Query: 'static {
36    type Output<'buf>;
37
38    #[doc(hidden)]
39    fn info_from<S>(stor: &mut S) -> QueryInfo
40    where
41        S: StoreQueryInfo + ?Sized;
42
43    #[doc(hidden)]
44    fn convert(buf: &mut [SelectedRaw]) -> Self::Output<'_>;
45
46    #[doc(hidden)]
47    fn key() -> QueryKey {
48        QueryKey::of::<Self>()
49    }
50
51    #[doc(hidden)]
52    fn get_info_from<S>(stor: &mut S) -> &Arc<QueryInfo>
53    where
54        S: StoreQueryInfo + ?Sized,
55    {
56        let key = Self::key();
57
58        if !StoreQueryInfo::contains(stor, &key) {
59            let qinfo = Arc::new(Self::info_from(stor));
60            StoreQueryInfo::insert(stor, key, qinfo);
61        }
62
63        // Safety: Inserted right before.
64        unsafe { StoreQueryInfo::get(stor, &key).unwrap_unchecked() }
65    }
66}
67
68#[allow(private_interfaces, private_bounds)]
69pub trait QueryMut: 'static {
70    type Output<'buf>;
71
72    #[doc(hidden)]
73    fn info_from<S>(stor: &mut S) -> QueryInfo
74    where
75        S: StoreQueryInfo + ?Sized;
76
77    #[doc(hidden)]
78    fn convert(buf: &mut [SelectedRaw]) -> Self::Output<'_>;
79
80    #[doc(hidden)]
81    fn key() -> QueryKey {
82        QueryKey::of::<Self>()
83    }
84
85    #[doc(hidden)]
86    fn get_info_from<S>(stor: &mut S) -> &Arc<QueryInfo>
87    where
88        S: StoreQueryInfo + ?Sized,
89    {
90        let key = Self::key();
91
92        if !StoreQueryInfo::contains(stor, &key) {
93            let qinfo = Arc::new(Self::info_from(stor));
94            StoreQueryInfo::insert(stor, key, qinfo);
95        }
96
97        // Safety: Inserted right before.
98        unsafe { StoreQueryInfo::get(stor, &key).unwrap_unchecked() }
99    }
100}
101
102#[allow(private_interfaces, private_bounds)]
103pub trait ResQuery: 'static {
104    type Output<'buf>;
105
106    #[doc(hidden)]
107    fn info() -> ResQueryInfo;
108
109    #[doc(hidden)]
110    fn convert(buf: &mut Vec<Borrowed<ManagedConstPtr<u8>>>) -> Self::Output<'_>;
111
112    #[doc(hidden)]
113    fn key() -> ResQueryKey {
114        ResQueryKey::of::<Self>()
115    }
116
117    #[doc(hidden)]
118    fn get_info_from<S>(stor: &mut S) -> &Arc<ResQueryInfo>
119    where
120        S: StoreResQueryInfo + ?Sized,
121    {
122        let key = Self::key();
123
124        if !stor.contains(&key) {
125            let rqinfo = Arc::new(Self::info());
126            stor.insert(key, rqinfo);
127        }
128
129        // Safety: Inserted right before.
130        unsafe { stor.get(&key).unwrap_unchecked() }
131    }
132}
133
134#[allow(private_interfaces, private_bounds)]
135pub trait ResQueryMut: 'static {
136    type Output<'buf>;
137
138    fn info() -> ResQueryInfo;
139
140    fn convert(buf: &mut Vec<Borrowed<ManagedMutPtr<u8>>>) -> Self::Output<'_>;
141
142    #[doc(hidden)]
143    fn key() -> ResQueryKey {
144        ResQueryKey::of::<Self>()
145    }
146
147    #[doc(hidden)]
148    fn get_info_from<S>(stor: &mut S) -> &Arc<ResQueryInfo>
149    where
150        S: StoreResQueryInfo + ?Sized,
151    {
152        let key = Self::key();
153
154        if !stor.contains(&key) {
155            let rqinfo = Arc::new(Self::info());
156            stor.insert(key, rqinfo);
157        }
158
159        // Safety: Inserted right before.
160        unsafe { stor.get(&key).unwrap_unchecked() }
161    }
162}
163
164#[allow(private_interfaces, private_bounds)]
165pub trait EntQueryMut: 'static {
166    type Output<'buf>;
167
168    #[doc(hidden)]
169    fn info_from<S>(stor: &mut S) -> EntQueryInfo
170    where
171        S: StoreEntQueryInfo + ?Sized;
172
173    fn convert(buf: &mut [FilteredRaw]) -> Self::Output<'_>;
174
175    #[doc(hidden)]
176    fn key() -> EntQueryKey {
177        EntQueryKey::of::<Self>()
178    }
179
180    #[doc(hidden)]
181    fn get_info_from<S>(stor: &mut S) -> &Arc<EntQueryInfo>
182    where
183        S: StoreEntQueryInfo + ?Sized,
184    {
185        let key = Self::key();
186
187        if !StoreEntQueryInfo::contains(stor, &key) {
188            let eqinfo = Arc::new(Self::info_from(stor));
189            StoreEntQueryInfo::insert(stor, key, eqinfo);
190        }
191
192        // Safety: Inserted right before.
193        unsafe { StoreEntQueryInfo::get(stor, &key).unwrap_unchecked() }
194    }
195}
196
197/// Read request for a set of components.
198///
199/// This is a part of a system request, clients need to declare the whole system
200/// request. Take a look at [`request`](crate::prelude::request).
201#[repr(transparent)]
202pub struct Read<'buf, R: Query>(pub(crate) R::Output<'buf>);
203
204impl<'buf, R: Query> Read<'buf, R> {
205    pub fn take(self) -> R::Output<'buf> {
206        self.0
207    }
208}
209
210impl<'buf, R: Query> Deref for Read<'buf, R> {
211    type Target = R::Output<'buf>;
212
213    fn deref(&self) -> &Self::Target {
214        &self.0
215    }
216}
217
218impl<'buf, R: Query> TakeRecur for Read<'buf, R>
219where
220    R::Output<'buf>: TakeRecur,
221{
222    type Inner = <R::Output<'buf> as TakeRecur>::Inner;
223
224    fn take_recur(self) -> Self::Inner {
225        self.0.take_recur()
226    }
227}
228
229/// Write request for a set of components.
230///
231/// This is a part of a system request, clients need to declare the whole system
232/// request. Take a look at [`request`](crate::prelude::request).
233#[repr(transparent)]
234pub struct Write<'buf, W: QueryMut>(pub(crate) W::Output<'buf>);
235
236impl<'buf, W: QueryMut> Write<'buf, W> {
237    pub fn take(self) -> W::Output<'buf> {
238        self.0
239    }
240}
241
242impl<'buf, W: QueryMut> Deref for Write<'buf, W> {
243    type Target = W::Output<'buf>;
244
245    fn deref(&self) -> &Self::Target {
246        &self.0
247    }
248}
249
250impl<W: QueryMut> DerefMut for Write<'_, W> {
251    fn deref_mut(&mut self) -> &mut Self::Target {
252        &mut self.0
253    }
254}
255
256impl<'buf, W: QueryMut> TakeRecur for Write<'buf, W>
257where
258    W::Output<'buf>: TakeRecur,
259{
260    type Inner = <W::Output<'buf> as TakeRecur>::Inner;
261
262    fn take_recur(self) -> Self::Inner {
263        self.0.take_recur()
264    }
265}
266
267/// Read request for a set of resources.
268///
269/// This is a part of a system request, clients need to declare the whole system
270/// request. Take a look at [`request`](crate::prelude::request).
271#[repr(transparent)]
272pub struct ResRead<'buf, RR: ResQuery>(pub(crate) RR::Output<'buf>);
273
274impl<'buf, RR: ResQuery> ResRead<'buf, RR> {
275    pub fn take(self) -> RR::Output<'buf> {
276        self.0
277    }
278}
279
280impl<'buf, RR: ResQuery> Deref for ResRead<'buf, RR> {
281    type Target = RR::Output<'buf>;
282
283    fn deref(&self) -> &Self::Target {
284        &self.0
285    }
286}
287
288impl<'buf, RR: ResQuery> TakeRecur for ResRead<'buf, RR>
289where
290    RR::Output<'buf>: TakeRecur,
291{
292    type Inner = <RR::Output<'buf> as TakeRecur>::Inner;
293
294    fn take_recur(self) -> Self::Inner {
295        self.0.take_recur()
296    }
297}
298
299/// Write request for a set of resources.
300///
301/// This is a part of a system request, clients need to declare the whole system
302/// request. Take a look at [`request`](crate::prelude::request).
303#[repr(transparent)]
304pub struct ResWrite<'buf, RW: ResQueryMut>(pub(crate) RW::Output<'buf>);
305
306impl<'buf, RW: ResQueryMut> ResWrite<'buf, RW> {
307    pub fn take(self) -> RW::Output<'buf> {
308        self.0
309    }
310}
311
312impl<'buf, RW: ResQueryMut> Deref for ResWrite<'buf, RW> {
313    type Target = RW::Output<'buf>;
314
315    fn deref(&self) -> &Self::Target {
316        &self.0
317    }
318}
319
320impl<RW: ResQueryMut> DerefMut for ResWrite<'_, RW> {
321    fn deref_mut(&mut self) -> &mut Self::Target {
322        &mut self.0
323    }
324}
325
326impl<'buf, RW: ResQueryMut> TakeRecur for ResWrite<'buf, RW>
327where
328    RW::Output<'buf>: TakeRecur,
329{
330    type Inner = <RW::Output<'buf> as TakeRecur>::Inner;
331
332    fn take_recur(self) -> Self::Inner {
333        self.0.take_recur()
334    }
335}
336
337/// Write request for a set of entity container.
338///
339/// This is a part of a system request, clients need to declare the whole system
340/// request. Take a look at [`request`](crate::prelude::request).
341#[repr(transparent)]
342pub struct EntWrite<'buf, EW: EntQueryMut>(pub(crate) EW::Output<'buf>);
343
344impl<'buf, EW: EntQueryMut> EntWrite<'buf, EW> {
345    pub fn take(self) -> EW::Output<'buf> {
346        self.0
347    }
348}
349
350impl<'buf, EW: EntQueryMut> Deref for EntWrite<'buf, EW> {
351    type Target = EW::Output<'buf>;
352
353    fn deref(&self) -> &Self::Target {
354        &self.0
355    }
356}
357
358impl<EW: EntQueryMut> DerefMut for EntWrite<'_, EW> {
359    fn deref_mut(&mut self) -> &mut Self::Target {
360        &mut self.0
361    }
362}
363
364impl<'buf, EW: EntQueryMut> TakeRecur for EntWrite<'buf, EW>
365where
366    EW::Output<'buf>: TakeRecur,
367{
368    type Inner = <EW::Output<'buf> as TakeRecur>::Inner;
369
370    fn take_recur(self) -> Self::Inner {
371        self.0.take_recur()
372    }
373}
374
375/// Unique identifier for a type implementing [`Query`] or [`QueryMut`].
376pub(crate) type QueryKey = ATypeId<QueryKey_>;
377pub(crate) struct QueryKey_;
378
379/// Unique identifier for a type implementing [`ResQuery`] or [`ResQueryMut`].
380pub(crate) type ResQueryKey = ATypeId<ResQueryKey_>;
381pub(crate) struct ResQueryKey_;
382
383/// Unique identifier for a type implementing [`EntQueryMut`].
384pub(crate) type EntQueryKey = ATypeId<EntQueryKey_>;
385pub(crate) struct EntQueryKey_;
386
387#[derive(Clone)]
388pub(crate) struct QueryInfo {
389    sels: Box<[(SelectKey, Arc<SelectInfo>)]>,
390    name: &'static str,
391}
392
393impl fmt::Debug for QueryInfo {
394    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395        let sinfos = self.select_infos().collect::<Vec<_>>();
396
397        f.debug_struct("QueryInfo")
398            .field("name", &self.name())
399            .field("sels", &sinfos)
400            .finish()
401    }
402}
403
404impl QueryInfo {
405    const fn new(sels: Box<[(SelectKey, Arc<SelectInfo>)]>, name: &'static str) -> Self {
406        Self { sels, name }
407    }
408
409    pub(crate) const fn selectors(&self) -> &[(SelectKey, Arc<SelectInfo>)] {
410        &self.sels
411    }
412
413    pub(crate) fn select_infos(&self) -> impl ExactSizeIterator<Item = &Arc<SelectInfo>> + Clone {
414        self.sels.iter().map(|(_key, info)| info)
415    }
416
417    pub(crate) const fn name(&self) -> &'static str {
418        self.name
419    }
420}
421
422#[derive(Clone)]
423pub(crate) struct ResQueryInfo {
424    rkeys: Box<[ResourceKey]>,
425    name: &'static str,
426}
427
428impl fmt::Debug for ResQueryInfo {
429    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
430        f.debug_struct("ResQueryInfo")
431            .field("name", &self.name())
432            .field("rkeys", &self.resource_keys())
433            .finish()
434    }
435}
436
437impl ResQueryInfo {
438    const fn new(rkeys: Box<[ResourceKey]>, name: &'static str) -> Self {
439        Self { rkeys, name }
440    }
441
442    pub(crate) const fn resource_keys(&self) -> &[ResourceKey] {
443        &self.rkeys
444    }
445
446    pub(crate) const fn name(&self) -> &'static str {
447        self.name
448    }
449}
450
451#[derive(Clone)]
452pub(crate) struct EntQueryInfo {
453    filters: Box<[(FilterKey, Arc<FilterInfo>)]>,
454    name: &'static str,
455}
456
457impl fmt::Debug for EntQueryInfo {
458    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459        f.debug_struct("EntQueryInfo")
460            .field("name", &self.name())
461            .field("filters", &self.filters())
462            .finish()
463    }
464}
465
466impl EntQueryInfo {
467    const fn new(filters: Box<[(FilterKey, Arc<FilterInfo>)]>, name: &'static str) -> Self {
468        Self { filters, name }
469    }
470
471    pub(crate) const fn filters(&self) -> &[(FilterKey, Arc<FilterInfo>)] {
472        &self.filters
473    }
474
475    pub(crate) const fn name(&self) -> &'static str {
476        self.name
477    }
478}
479
480/// Implements [`Query`] and [`QueryMut`] for a tuple of
481/// [`Select`](crate::ecs::sys::select::Select).
482macro_rules! impl_query {
483    ($n:expr, $($i:expr),*) => {const _: () = {
484        #[allow(unused_imports)]
485        use $crate::ecs::sys::{
486            query::{Query, QueryInfo, StoreQueryInfo, StoreSelectInfo},
487            select::{Select, SelectKey, SelectedRaw, Selected, SelectedMut},
488        };
489        use std::{any::type_name, sync::Arc};
490        use paste::paste;
491
492        // Implements `Query` for (A0, A1, ...).
493        paste! {
494            #[allow(unused_parens)]
495            #[allow(private_interfaces, private_bounds)]
496            impl<$([<A $i>]: Select),*> Query for ( $([<A $i>]),* ) {
497                type Output<'buf> = ( $(Selected<'buf, [<A $i>]::Target>),* );
498
499                fn info_from<S>(_stor: &mut S) -> QueryInfo
500                where
501                    S: StoreQueryInfo + ?Sized
502                {
503                    let sels = [ $(
504                        (
505                            [<A $i>]::key(),
506                            Arc::clone([<A $i>]::get_info_from(_stor))
507                        )
508                    ),* ];
509                    let sels: Box<[(SelectKey, Arc<SelectInfo>)]> = sels.into();
510                    let name = type_name::<Self>();
511                    QueryInfo::new(sels, name)
512                }
513
514                fn convert(buf: &mut [SelectedRaw]) -> Self::Output<'_> {
515                    debug_assert_eq!($n, buf.len());
516
517                    #[allow(clippy::unused_unit)]
518                    ( $(
519                        // Splitting slice via `split_first_mut` is quite tiresome task.
520                        // Anyway, we're connecting lifetime from each input to output,
521                        // so no problem.
522                        // Safety: Infallible.
523                        {
524                            let x: *mut SelectedRaw = &mut buf[$i] as *mut _;
525                            let x: &mut SelectedRaw = unsafe { x.as_mut().unwrap_unchecked() };
526                            Selected::new(x)
527                        }
528                    ),* )
529                }
530            }
531        }
532
533        // Implements `QueryMut` for (A0, A1, ...).
534        paste! {
535            #[allow(unused_parens)]
536            #[allow(private_interfaces, private_bounds)]
537            impl<$([<A $i>]: Select),*> QueryMut for ( $([<A $i>]),* ) {
538                type Output<'buf> = ( $(SelectedMut<'buf, [<A $i>]::Target>),* );
539
540                fn info_from<S>(_stor: &mut S) -> QueryInfo
541                where
542                    S: StoreQueryInfo + ?Sized
543                {
544                    let sels = [ $(
545                        (
546                            [<A $i>]::key(),
547                            Arc::clone([<A $i>]::get_info_from(_stor))
548                        )
549                    ),* ];
550                    let sels: Box<[(SelectKey, Arc<SelectInfo>)]> = sels.into();
551                    let name = type_name::<Self>();
552                    QueryInfo::new(sels, name)
553                }
554
555                fn convert(buf: &mut [SelectedRaw]) -> Self::Output<'_> {
556                    debug_assert_eq!($n, buf.len());
557
558                    #[allow(clippy::unused_unit)]
559                    ( $(
560                        // Splitting slice via `split_first_mut` is quite tiresome task.
561                        // Anyway, we're connecting lifetime from each input to output,
562                        // so no problem.
563                        // Safety: Infallible.
564                        {
565                            let x: *mut SelectedRaw = &mut buf[$i] as *mut _;
566                            let x: &mut SelectedRaw = unsafe { x.as_mut().unwrap_unchecked() };
567                            SelectedMut::new(x)
568                        }
569                    ),* )
570                }
571            }
572        }
573    };};
574}
575repeat_macro!(impl_query, ..=8);
576
577/// Implements the trait [`ResQuery`] and [`ResQueryMut`] for an anonymous tuple of [`Resource`](super::resource::Resource)s.
578macro_rules! impl_res_query {
579    ($n:expr, $($i:expr),*) => {const _: () = {
580        #[allow(unused_imports)]
581        use $crate::{
582            ecs::{
583                sys::query::{ResQuery, ResQueryInfo},
584                resource::Resource,
585            },
586            ds::{Borrowed, ManagedConstPtr, ManagedMutPtr, TypeIdExt},
587        };
588        use std::any::type_name;
589        use paste::paste;
590
591        // Implements `ResQuery` for (A0, A1, ...).
592        paste! {
593            #[allow(unused_parens)]
594            #[allow(private_interfaces, private_bounds)]
595            impl<$([<A $i>]: Resource),*> ResQuery for ( $([<A $i>]),* ) {
596                type Output<'buf> = ( $( &'buf [<A $i>] ),* );
597
598                fn info() -> ResQueryInfo {
599                    let rkeys = [$([<A $i>]::key()),*].into();
600                    let name = type_name::<Self>();
601                    ResQueryInfo::new(rkeys, name)
602                }
603
604                fn convert(_buf: &mut Vec<Borrowed<ManagedConstPtr<u8>>>) -> Self::Output<'_> {
605                    debug_assert_eq!($n, _buf.len());
606
607                    // Managed pointer may have type info in it.
608                    // But resource pointer must have the type info.
609                    // So we can check if the pointers are correctly given.
610                    #[cfg(feature = "check")]
611                    {
612                        $(
613                            let ptr: NonNullExt<_> = _buf[$i].as_nonnullext();
614                            let lhs: &TypeIdExt = ptr.get_type().unwrap();
615
616                            let rkey: ResourceKey = [<A $i>]::key();
617                            let rhs: &TypeIdExt = rkey.get_inner();
618
619                            assert_eq!(lhs, rhs);
620                        )*
621                    }
622
623                    #[allow(clippy::unused_unit)]
624                    ( $( {
625                        let ptr: NonNullExt<[<A $i>]> = _buf[$i].as_nonnullext().cast();
626                        // Safety: Infallible, Plus output is bounded by input's
627                        // 'buf lifetime
628                        unsafe { ptr.as_ref() } // &'buf mut A#
629                    } ),* )
630                }
631            }
632        }
633
634        // Implements `ResQueryMut` for (A0, A1, ...).
635        paste!{
636            #[allow(unused_parens)]
637            #[allow(private_interfaces, private_bounds)]
638            impl<$([<A $i>]: Resource),*> ResQueryMut for ( $([<A $i>]),* ) {
639                type Output<'buf> = ( $( &'buf mut [<A $i>] ),* );
640
641                fn info() -> ResQueryInfo {
642                    let rkeys = [$([<A $i>]::key()),*].into();
643                    let name = type_name::<Self>();
644                    ResQueryInfo::new(rkeys, name)
645                }
646
647                fn convert(_buf: &mut Vec<Borrowed<ManagedMutPtr<u8>>>) -> Self::Output<'_> {
648                    debug_assert_eq!($n, _buf.len());
649
650                    // Managed pointer may have type info in it.
651                    // But resource pointer must have the type info.
652                    // So we can check if the pointers are correctly given.
653                    #[cfg(feature = "check")]
654                    { $(
655                        let ptr: NonNullExt<_> = _buf[$i].as_nonnullext();
656                        let lhs: &TypeIdExt = ptr.get_type().unwrap();
657
658                        let rkey: ResourceKey = [<A $i>]::key();
659                        let rhs: &TypeIdExt = rkey.get_inner();
660
661                        assert_eq!(lhs, rhs);
662                    )* }
663
664                    #[allow(clippy::unused_unit)]
665                    ( $( {
666                        let mut ptr: NonNullExt<[<A $i>]> = _buf[$i].as_nonnullext().cast();
667                        // Safety: Infallible, Plus output is bounded by input's
668                        // 'buf lifetime
669                        unsafe { ptr.as_mut() } // &'buf mut A#
670                    } ),* )
671                }
672            }
673        }
674    };};
675}
676repeat_macro!(impl_res_query, ..=8);
677
678/// Implements the trait [`EntQueryMut`] for an anonymous tuple of [`ContainEntity`](super::entity::ContainEntity)s.
679macro_rules! impl_ent_query {
680    ($n:expr, $($i:expr),*) => {const _: () = {
681        #[allow(unused_imports)]
682        use $crate::{
683            ecs::{
684                sys::{
685                    query::{EntQueryMut, EntQueryInfo},
686                    select::{Filter, FilteredMut},
687                },
688                ent::{
689                    entity::{Entity, ContainEntity},
690                    storage::EntityContainerRef
691                },
692            },
693            ds::Borrowed,
694        };
695        use std::any::type_name;
696        use paste::paste;
697
698        // Implements `EntQueryMut` for (A0, A1, ...).
699        paste! {
700            #[allow(unused_parens)]
701            #[allow(private_interfaces, private_bounds)]
702            impl<$([<A $i>]: Filter),*> EntQueryMut for ( $([<A $i>]),* ) {
703                type Output<'buf> = ( $(FilteredMut<'buf, [<A $i>]>),* );
704
705                fn info_from<S>(_stor: &mut S) -> EntQueryInfo
706                where
707                    S: StoreEntQueryInfo + ?Sized
708                {
709                    let finfos = [$(
710                        (
711                            [<A $i>]::key(),
712                            Arc::clone([<A $i>]::get_info_from(_stor))
713                        )
714                    ),*].into();
715                    let name = type_name::<Self>();
716                    EntQueryInfo::new(finfos, name)
717                }
718
719                fn convert(buf: &mut [FilteredRaw]) -> Self::Output<'_> {
720                    debug_assert_eq!($n, buf.len());
721
722                    #[allow(clippy::unused_unit)]
723                    ( $(
724                        // Splitting slice via `split_first_mut` is quite tiresome task.
725                        // Anyway, we're connecting lifetime from each input to output,
726                        // so no problem.
727                        // Safety: Infallible.
728                        {
729                            let x: *mut FilteredRaw = &mut buf[$i] as *mut _;
730                            let x: &mut FilteredRaw = unsafe { x.as_mut().unwrap_unchecked() };
731                            FilteredMut::new(x)
732                        }
733                    ),* )
734                }
735            }
736        }
737    };};
738}
739repeat_macro!(impl_ent_query, ..=8);