legion/internals/query/filter/
or.rs1use 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#[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);