bevy_either/
either_many.rs

1#[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}