Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/derive/src/impls/structs.rs
9353 views
1
use crate::{
2
impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed},
3
struct_utility::FieldAccessors,
4
ReflectStruct,
5
};
6
use bevy_macro_utils::fq_std::{FQDefault, FQOption, FQResult};
7
use quote::{quote, ToTokens};
8
9
/// Implements `Struct`, `GetTypeRegistration`, and `Reflect` for the given derive data.
10
pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenStream {
11
let fqoption = FQOption.into_token_stream();
12
13
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
14
let struct_path = reflect_struct.meta().type_path();
15
16
let field_names = reflect_struct
17
.active_fields()
18
.map(|field| {
19
field
20
.data
21
.ident
22
.as_ref()
23
.map(ToString::to_string)
24
.unwrap_or_else(|| field.declaration_index.to_string())
25
})
26
.collect::<Vec<String>>();
27
28
let FieldAccessors {
29
fields_ref,
30
fields_mut,
31
field_indices,
32
field_count,
33
..
34
} = FieldAccessors::new(reflect_struct);
35
36
let where_clause_options = reflect_struct.where_clause_options();
37
let typed_impl = impl_typed(&where_clause_options, reflect_struct.to_info_tokens(false));
38
39
let type_path_impl = impl_type_path(reflect_struct.meta());
40
let full_reflect_impl = impl_full_reflect(&where_clause_options);
41
let common_methods = common_partial_reflect_methods(
42
reflect_struct.meta(),
43
|| Some(quote!(#bevy_reflect_path::structs::struct_partial_eq)),
44
|| None,
45
|| Some(quote!(#bevy_reflect_path::structs::struct_partial_cmp)),
46
);
47
let clone_fn = reflect_struct.get_clone_impl();
48
49
#[cfg(not(feature = "functions"))]
50
let function_impls = None::<proc_macro2::TokenStream>;
51
#[cfg(feature = "functions")]
52
let function_impls = crate::impls::impl_function_traits(&where_clause_options);
53
54
let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options);
55
56
let (impl_generics, ty_generics, where_clause) = reflect_struct
57
.meta()
58
.type_path()
59
.generics()
60
.split_for_impl();
61
62
#[cfg(not(feature = "auto_register"))]
63
let auto_register = None::<proc_macro2::TokenStream>;
64
#[cfg(feature = "auto_register")]
65
let auto_register = crate::impls::reflect_auto_registration(reflect_struct.meta());
66
67
let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);
68
69
quote! {
70
#get_type_registration_impl
71
72
#typed_impl
73
74
#type_path_impl
75
76
#full_reflect_impl
77
78
#function_impls
79
80
#auto_register
81
82
impl #impl_generics #bevy_reflect_path::structs::Struct for #struct_path #ty_generics #where_reflect_clause {
83
fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
84
match name {
85
#(#field_names => #fqoption::Some(#fields_ref),)*
86
_ => #FQOption::None,
87
}
88
}
89
90
fn field_mut(&mut self, name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
91
match name {
92
#(#field_names => #fqoption::Some(#fields_mut),)*
93
_ => #FQOption::None,
94
}
95
}
96
97
fn field_at(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
98
match index {
99
#(#field_indices => #fqoption::Some(#fields_ref),)*
100
_ => #FQOption::None,
101
}
102
}
103
104
fn field_at_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
105
match index {
106
#(#field_indices => #fqoption::Some(#fields_mut),)*
107
_ => #FQOption::None,
108
}
109
}
110
111
fn name_at(&self, index: usize) -> #FQOption<&str> {
112
match index {
113
#(#field_indices => #fqoption::Some(#field_names),)*
114
_ => #FQOption::None,
115
}
116
}
117
118
fn field_len(&self) -> usize {
119
#field_count
120
}
121
122
fn iter_fields(&self) -> #bevy_reflect_path::structs::FieldIter {
123
#bevy_reflect_path::structs::FieldIter::new(self)
124
}
125
126
fn to_dynamic_struct(&self) -> #bevy_reflect_path::structs::DynamicStruct {
127
let mut dynamic: #bevy_reflect_path::structs::DynamicStruct = #FQDefault::default();
128
dynamic.set_represented_type(#bevy_reflect_path::PartialReflect::get_represented_type_info(self));
129
#(dynamic.insert_boxed(#field_names, #bevy_reflect_path::PartialReflect::to_dynamic(#fields_ref));)*
130
dynamic
131
}
132
}
133
134
impl #impl_generics #bevy_reflect_path::PartialReflect for #struct_path #ty_generics #where_reflect_clause {
135
#[inline]
136
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
137
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
138
}
139
140
#[inline]
141
fn try_apply(
142
&mut self,
143
value: &dyn #bevy_reflect_path::PartialReflect
144
) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
145
if let #bevy_reflect_path::ReflectRef::Struct(struct_value)
146
= #bevy_reflect_path::PartialReflect::reflect_ref(value) {
147
for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::structs::Struct::iter_fields(struct_value)) {
148
let name = #bevy_reflect_path::structs::Struct::name_at(struct_value, i).unwrap();
149
if let #FQOption::Some(v) = #bevy_reflect_path::structs::Struct::field_mut(self, name) {
150
#bevy_reflect_path::PartialReflect::try_apply(v, value)?;
151
}
152
}
153
} else {
154
return #FQResult::Err(
155
#bevy_reflect_path::ApplyError::MismatchedKinds {
156
from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(value),
157
to_kind: #bevy_reflect_path::ReflectKind::Struct
158
}
159
);
160
}
161
#FQResult::Ok(())
162
}
163
#[inline]
164
fn reflect_kind(&self) -> #bevy_reflect_path::ReflectKind {
165
#bevy_reflect_path::ReflectKind::Struct
166
}
167
#[inline]
168
fn reflect_ref(&self) -> #bevy_reflect_path::ReflectRef {
169
#bevy_reflect_path::ReflectRef::Struct(self)
170
}
171
#[inline]
172
fn reflect_mut(&mut self) -> #bevy_reflect_path::ReflectMut {
173
#bevy_reflect_path::ReflectMut::Struct(self)
174
}
175
#[inline]
176
fn reflect_owned(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::ReflectOwned {
177
#bevy_reflect_path::ReflectOwned::Struct(self)
178
}
179
180
#common_methods
181
182
#clone_fn
183
}
184
}
185
}
186
187