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