bevy_either/
either_many.rs1#[macro_export]
2macro_rules! either_many {
3 (@__first $first:tt $(, $($others:tt),+)?) => {
4 $first
5 };
6 (readonly $(#[$($m:meta),*])? $name:ident $(< $($lf:lifetime),* $(, )? >)?, $($varn:ident($($vart:tt)+)),+ $(, )?) => {
7 $crate::either_many!($(#[$($m),*])? $name $(< $($lf),*>)?, $($varn($($vart)+)),+);
8
9 $crate::exports::paste!{
10 unsafe impl $(< $($lf),*>)? ::bevy::ecs::query::ReadOnlyFetch for [<__ $name:lower>]::[<$name Fetch>] $(< $($lf),*>)? {}
11 }
12 };
13 ($(#[$($m:meta),*])? $name:ident $(< $($lf:lifetime),* >)?, $($varn:ident($($vart:tt)+)),+ $(, )?) => {
14 $crate::exports::paste!{
15 $(#[$($m),*])?
16 #[doc =
17 "A [world query](::bevy::ecs::query::WorldQuery) allowing you to match one of "
18 "multiple other [world queries](::bevy::ecs::query::WorldQuery).\n"
19 "There is exactly one variant per [world query](::bevy::ecs::query::WorldQuery) "
20 "that [`" $name "`] can fulfill.\n\nIn priority order, [`" $name "`] matches:"
21 $("\n * [`" $name "::" $varn "(_)`](" $name "::" $varn ")")+
22 ]
23 pub enum $name $(< $($lf),*>)? {
24 $($varn(<
25 <$($vart)+ as ::bevy::ecs::query::WorldQuery>::Fetch
26 as ::bevy::ecs::query::Fetch<'static>
27 >::Item)),+
28 }
29 }
30
31 $crate::exports::paste!{mod [<__ $name:lower>] {
32 use super::*;
33 use ::bevy::prelude::*;
34 use ::bevy::ecs::{storage::*, component::*, archetype::*, query::*};
35
36 #[derive(Copy, Clone)]
37 enum Matches {
38 $($varn),+
39 }
40
41 impl Matches {
42 const FIRST: Self = {
43 use Matches::*;
44 $crate::either_many!(@__first $($varn),+)
45 };
46 }
47
48 #[allow(non_snake_case)]
49 pub struct [<$name State>] $(< $($lf),*>)? {
50 $($varn: <$($vart)+ as WorldQuery>::State),+
51 }
52
53 unsafe impl $(< $($lf),*>)? FetchState for [<$name State>] $(< $($lf),*>)? {
54 fn init(world: &mut World) -> Self {
55 Self {
56 $($varn: <$($vart)+ as WorldQuery>::State::init(world)),+
57 }
58 }
59
60 fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>) {
61 $(self.$varn.update_component_access(access);)+
62 }
63
64 fn update_archetype_component_access(
65 &self,
66 archetype: &Archetype,
67 access: &mut Access<ArchetypeComponentId>,
68 ) {
69 $(self.$varn.update_archetype_component_access(archetype, access);)+
70 }
71
72 fn matches_archetype(&self, archetype: &Archetype) -> bool {
73 $(self.$varn.matches_archetype(archetype))||+
74 }
75
76 fn matches_table(&self, table: &Table) -> bool {
77 $(self.$varn.matches_table(table))||+
78 }
79 }
80
81 #[allow(non_snake_case)]
82 pub struct [<$name Fetch>] $(< $($lf),*>)? {
83 matches: Matches,
84 $($varn: <$($vart)+ as WorldQuery>::Fetch),+
85 }
86
87 impl $(< $($lf),*>)? Fetch<'_> for [<$name Fetch>] $(< $($lf),*>)? {
88 type Item = $name $(< $($lf),*>)?;
89 type State = [<$name State>] $(< $($lf),*>)?;
90
91 fn is_dense(&self) -> bool {
92 $(self.$varn.is_dense())||+
93 }
94
95 unsafe fn init(
96 world: &World,
97 state: &Self::State,
98 last_change_tick: u32,
99 change_tick: u32,
100 ) -> Self {
101 Self {
102 matches: Matches::FIRST,
103 $($varn: <$($vart)+ as WorldQuery>::Fetch::init(
104 world,
105 &state.$varn,
106 last_change_tick,
107 change_tick,
108 ),)+
109 }
110 }
111
112 unsafe fn set_archetype(
113 &mut self,
114 state: &Self::State,
115 archetype: &Archetype,
116 tables: &Tables,
117 ) {
118 $(if state.$varn.matches_archetype(archetype) {
119 self.$varn.set_archetype(&state.$varn, archetype, tables);
120 self.matches = {
121 use Matches::*;
122 $varn
123 };
124 })else+ else if cfg!(debug_assertions) {
125 unreachable!("None of the variants were matched. At least one should be.");
126 }
127 }
128
129 unsafe fn set_table(&mut self, state: &Self::State, table: &Table) {
130 $(if state.$varn.matches_table(table) {
131 self.$varn.set_table(&state.$varn, table);
132 self.matches = {
133 use Matches::*;
134 $varn
135 };
136 })else+ else if cfg!(debug_assertions) {
137 unreachable!("None of the variants were matched. At least one should be.");
138 }
139 }
140
141 unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item {
142 use Matches::*;
143
144 match self.matches {
145 $($varn => $name::$varn(self.$varn.archetype_fetch(archetype_index)),)+
146 }
147 }
148
149 unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item {
150 use Matches::*;
151
152 match self.matches {
153 $($varn => $name::$varn(self.$varn.table_fetch(table_row)),)+
154 }
155 }
156 }
157
158 impl $(< $($lf),*>)? WorldQuery for $name $(< $($lf),*>)? {
159 type Fetch = [<$name Fetch>] $(< $($lf),*>)?;
160 type State = [<$name State>] $(< $($lf),*>)?;
161 }
162 }}
163 };
164}