legion/internals/query/filter/
or.rs

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