kaige_ecs/internals/query/filter/
and.rs

1use super::{
2    not::Not, or::Or, passthrough::Passthrough, ActiveFilter, DynamicFilter, FilterResult,
3    GroupMatcher, LayoutFilter,
4};
5use crate::internals::{query::view::Fetch, storage::component::ComponentTypeId, world::WorldId};
6
7/// A filter which requires all filters within `T` match.
8#[derive(Debug, Clone)]
9pub struct And<T> {
10    pub(super) filters: T,
11}
12
13macro_rules! and_filter {
14    ($head_ty:ident) => {
15        impl_and_filter!($head_ty);
16    };
17    ($head_ty:ident, $( $tail_ty:ident ),*) => (
18        impl_and_filter!($head_ty, $( $tail_ty ),*);
19        and_filter!($( $tail_ty ),*);
20    );
21}
22
23macro_rules! impl_and_filter {
24    ( $( $ty:ident ),* ) => {
25        impl<$( $ty ),*> ActiveFilter for And<($( $ty, )*)> {}
26
27        impl<$( $ty: Default ),*> Default for And<($( $ty, )*)> {
28            fn default() -> Self {
29                Self {
30                    filters: ($( $ty::default(), )*)
31                }
32            }
33        }
34
35        impl<$( $ty: GroupMatcher ),*> GroupMatcher for And<($( $ty, )*)> {
36            fn can_match_group() -> bool {
37                $( $ty::can_match_group() )&&*
38            }
39            fn group_components() -> Vec<ComponentTypeId> {
40                let mut components = Vec::new();
41                $( components.extend($ty::group_components()); )*
42                components
43            }
44        }
45
46        impl<$( $ty: LayoutFilter ),*> LayoutFilter for And<($( $ty, )*)> {
47            #[inline]
48            fn matches_layout(&self, components: &[ComponentTypeId]) -> FilterResult {
49                #![allow(non_snake_case)]
50                let ($( $ty, )*) = &self.filters;
51                let mut result = FilterResult::Defer;
52                $( result = result.coalesce_and($ty.matches_layout(components)); )*
53                result
54            }
55        }
56
57        impl<$( $ty: DynamicFilter ),*> DynamicFilter for And<($( $ty, )*)> {
58            #[inline]
59            fn prepare(&mut self, world: WorldId) {
60                #![allow(non_snake_case)]
61                let ($( $ty, )*) = &mut self.filters;
62                $( $ty.prepare(world); )*
63            }
64
65            #[inline]
66            fn matches_archetype<Fet: Fetch>(&mut self, fetch: &Fet) -> FilterResult {
67                #![allow(non_snake_case)]
68                let ($( $ty, )*) = &mut self.filters;
69                let mut result = FilterResult::Defer;
70                $( result = result.coalesce_and($ty.matches_archetype(fetch)); )*
71                result
72            }
73        }
74
75        impl<$( $ty ),*> std::ops::Not for And<($( $ty, )*)> {
76            type Output = Not<Self>;
77
78            #[inline]
79            fn not(self) -> Self::Output {
80                Not { filter: self }
81            }
82        }
83
84        impl<$( $ty ),*, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for And<($( $ty, )*)> {
85            type Output = And<($( $ty, )* Rhs)>;
86
87            #[inline]
88            fn bitand(self, rhs: Rhs) -> Self::Output {
89                #![allow(non_snake_case)]
90                let ($( $ty, )*) = self.filters;
91                And {
92                    filters: ($( $ty, )* rhs),
93                }
94            }
95        }
96
97        impl<$( $ty ),*> std::ops::BitAnd<Passthrough> for And<($( $ty, )*)> {
98            type Output = Self;
99
100            #[inline]
101            fn bitand(self, _: Passthrough) -> Self::Output {
102                self
103            }
104        }
105
106        impl<$( $ty ),*, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for And<($( $ty, )*)> {
107            type Output = Or<(Self, Rhs)>;
108
109            #[inline]
110            fn bitor(self, rhs: Rhs) -> Self::Output {
111                Or {
112                    filters: (self, rhs),
113                }
114            }
115        }
116
117        impl<$( $ty ),*> std::ops::BitOr<Passthrough> for And<($( $ty, )*)> {
118            type Output = Self;
119
120            #[inline]
121            fn bitor(self, _: Passthrough) -> Self::Output {
122                self
123            }
124        }
125    };
126}
127
128#[cfg(feature = "extended-tuple-impls")]
129and_filter!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
130
131#[cfg(not(feature = "extended-tuple-impls"))]
132and_filter!(A, B, C, D, E, F, G, H);