bevy_ecs_macros/
world_query.rs1use proc_macro2::Ident;
2use quote::quote;
3use syn::{Attribute, Fields, ImplGenerics, TypeGenerics, Visibility, WhereClause};
4
5#[allow(clippy::too_many_arguments)]
6pub(crate) fn item_struct(
7 path: &syn::Path,
8 fields: &Fields,
9 derive_macro_call: &proc_macro2::TokenStream,
10 struct_name: &Ident,
11 visibility: &Visibility,
12 item_struct_name: &Ident,
13 field_types: &Vec<proc_macro2::TokenStream>,
14 user_impl_generics_with_world: &ImplGenerics,
15 field_attrs: &Vec<Vec<Attribute>>,
16 field_visibilities: &Vec<Visibility>,
17 field_idents: &Vec<proc_macro2::TokenStream>,
18 user_ty_generics: &TypeGenerics,
19 user_ty_generics_with_world: &TypeGenerics,
20 user_where_clauses_with_world: Option<&WhereClause>,
21) -> proc_macro2::TokenStream {
22 let item_attrs = quote!(
23 #[doc = "Automatically generated [`WorldQuery`] item type for [`"]
24 #[doc = stringify!(#struct_name)]
25 #[doc = "`], returned when iterating over query results."]
26 #[automatically_derived]
27 );
28
29 match fields {
30 Fields::Named(_) => quote! {
31 #derive_macro_call
32 #item_attrs
33 #visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
34 #(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::WorldQuery>::Item<'__w>,)*
35 }
36 },
37 Fields::Unnamed(_) => quote! {
38 #derive_macro_call
39 #item_attrs
40 #visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world(
41 #( #field_visibilities <#field_types as #path::query::WorldQuery>::Item<'__w>, )*
42 );
43 },
44 Fields::Unit => quote! {
45 #item_attrs
46 #visibility type #item_struct_name #user_ty_generics_with_world = #struct_name #user_ty_generics;
47 },
48 }
49}
50
51#[allow(clippy::too_many_arguments)]
52pub(crate) fn world_query_impl(
53 path: &syn::Path,
54 struct_name: &Ident,
55 visibility: &Visibility,
56 item_struct_name: &Ident,
57 fetch_struct_name: &Ident,
58 field_types: &Vec<proc_macro2::TokenStream>,
59 user_impl_generics: &ImplGenerics,
60 user_impl_generics_with_world: &ImplGenerics,
61 field_idents: &Vec<proc_macro2::TokenStream>,
62 user_ty_generics: &TypeGenerics,
63 user_ty_generics_with_world: &TypeGenerics,
64 named_field_idents: &Vec<Ident>,
65 marker_name: &Ident,
66 state_struct_name: &Ident,
67 user_where_clauses: Option<&WhereClause>,
68 user_where_clauses_with_world: Option<&WhereClause>,
69) -> proc_macro2::TokenStream {
70 quote! {
71 #[doc(hidden)]
72 #[doc = "Automatically generated internal [`WorldQuery`] fetch type for [`"]
73 #[doc = stringify!(#struct_name)]
74 #[doc = "`], used to define the world data accessed by this query."]
75 #[automatically_derived]
76 #visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
77 #(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w>,)*
78 #marker_name: &'__w (),
79 }
80
81 impl #user_impl_generics_with_world Clone for #fetch_struct_name #user_ty_generics_with_world
82 #user_where_clauses_with_world {
83 fn clone(&self) -> Self {
84 Self {
85 #(#named_field_idents: self.#named_field_idents.clone(),)*
86 #marker_name: &(),
87 }
88 }
89 }
90
91 unsafe impl #user_impl_generics #path::query::WorldQuery
93 for #struct_name #user_ty_generics #user_where_clauses {
94
95 type Item<'__w> = #item_struct_name #user_ty_generics_with_world;
96 type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world;
97 type State = #state_struct_name #user_ty_generics;
98
99 fn shrink<'__wlong: '__wshort, '__wshort>(
100 item: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wlong>
101 ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wshort> {
102 #item_struct_name {
103 #(
104 #field_idents: <#field_types>::shrink(item.#field_idents),
105 )*
106 }
107 }
108
109 unsafe fn init_fetch<'__w>(
110 _world: #path::world::unsafe_world_cell::UnsafeWorldCell<'__w>,
111 state: &Self::State,
112 _last_run: #path::component::Tick,
113 _this_run: #path::component::Tick,
114 ) -> <Self as #path::query::WorldQuery>::Fetch<'__w> {
115 #fetch_struct_name {
116 #(#named_field_idents:
117 <#field_types>::init_fetch(
118 _world,
119 &state.#named_field_idents,
120 _last_run,
121 _this_run,
122 ),
123 )*
124 #marker_name: &(),
125 }
126 }
127
128 const IS_DENSE: bool = true #(&& <#field_types>::IS_DENSE)*;
129
130 #[inline]
132 unsafe fn set_archetype<'__w>(
133 _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
134 _state: &Self::State,
135 _archetype: &'__w #path::archetype::Archetype,
136 _table: &'__w #path::storage::Table
137 ) {
138 #(<#field_types>::set_archetype(&mut _fetch.#named_field_idents, &_state.#named_field_idents, _archetype, _table);)*
139 }
140
141 #[inline]
143 unsafe fn set_table<'__w>(
144 _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
145 _state: &Self::State,
146 _table: &'__w #path::storage::Table
147 ) {
148 #(<#field_types>::set_table(&mut _fetch.#named_field_idents, &_state.#named_field_idents, _table);)*
149 }
150
151 #[inline(always)]
153 unsafe fn fetch<'__w>(
154 _fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
155 _entity: #path::entity::Entity,
156 _table_row: #path::storage::TableRow,
157 ) -> <Self as #path::query::WorldQuery>::Item<'__w> {
158 Self::Item {
159 #(#field_idents: <#field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)*
160 }
161 }
162
163 fn update_component_access(state: &Self::State, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
164 #( <#field_types>::update_component_access(&state.#named_field_idents, _access); )*
165 }
166
167 fn init_state(world: &mut #path::world::World) -> #state_struct_name #user_ty_generics {
168 #state_struct_name {
169 #(#named_field_idents: <#field_types>::init_state(world),)*
170 }
171 }
172
173 fn get_state(components: &#path::component::Components) -> Option<#state_struct_name #user_ty_generics> {
174 Some(#state_struct_name {
175 #(#named_field_idents: <#field_types>::get_state(components)?,)*
176 })
177 }
178
179 fn matches_component_set(state: &Self::State, _set_contains_id: &impl Fn(#path::component::ComponentId) -> bool) -> bool {
180 true #(&& <#field_types>::matches_component_set(&state.#named_field_idents, _set_contains_id))*
181 }
182 }
183 }
184}