bevy_reflect_derive/impls/
structs.rs1use crate::{
2 impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed},
3 struct_utility::FieldAccessors,
4 ReflectStruct,
5};
6use bevy_macro_utils::fq_std::{FQDefault, FQOption, FQResult};
7use quote::{quote, ToTokens};
8
9pub(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::struct_partial_eq)),
44 || None,
45 );
46 let clone_fn = reflect_struct.get_clone_impl();
47
48 #[cfg(not(feature = "functions"))]
49 let function_impls = None::<proc_macro2::TokenStream>;
50 #[cfg(feature = "functions")]
51 let function_impls = crate::impls::impl_function_traits(&where_clause_options);
52
53 let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options);
54
55 let (impl_generics, ty_generics, where_clause) = reflect_struct
56 .meta()
57 .type_path()
58 .generics()
59 .split_for_impl();
60
61 #[cfg(not(feature = "auto_register"))]
62 let auto_register = None::<proc_macro2::TokenStream>;
63 #[cfg(feature = "auto_register")]
64 let auto_register = crate::impls::reflect_auto_registration(reflect_struct.meta());
65
66 let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);
67
68 quote! {
69 #get_type_registration_impl
70
71 #typed_impl
72
73 #type_path_impl
74
75 #full_reflect_impl
76
77 #function_impls
78
79 #auto_register
80
81 impl #impl_generics #bevy_reflect_path::Struct for #struct_path #ty_generics #where_reflect_clause {
82 fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
83 match name {
84 #(#field_names => #fqoption::Some(#fields_ref),)*
85 _ => #FQOption::None,
86 }
87 }
88
89 fn field_mut(&mut self, name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
90 match name {
91 #(#field_names => #fqoption::Some(#fields_mut),)*
92 _ => #FQOption::None,
93 }
94 }
95
96 fn field_at(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
97 match index {
98 #(#field_indices => #fqoption::Some(#fields_ref),)*
99 _ => #FQOption::None,
100 }
101 }
102
103 fn field_at_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
104 match index {
105 #(#field_indices => #fqoption::Some(#fields_mut),)*
106 _ => #FQOption::None,
107 }
108 }
109
110 fn name_at(&self, index: usize) -> #FQOption<&str> {
111 match index {
112 #(#field_indices => #fqoption::Some(#field_names),)*
113 _ => #FQOption::None,
114 }
115 }
116
117 fn field_len(&self) -> usize {
118 #field_count
119 }
120
121 fn iter_fields(&self) -> #bevy_reflect_path::FieldIter {
122 #bevy_reflect_path::FieldIter::new(self)
123 }
124
125 fn to_dynamic_struct(&self) -> #bevy_reflect_path::DynamicStruct {
126 let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default();
127 dynamic.set_represented_type(#bevy_reflect_path::PartialReflect::get_represented_type_info(self));
128 #(dynamic.insert_boxed(#field_names, #bevy_reflect_path::PartialReflect::to_dynamic(#fields_ref));)*
129 dynamic
130 }
131 }
132
133 impl #impl_generics #bevy_reflect_path::PartialReflect for #struct_path #ty_generics #where_reflect_clause {
134 #[inline]
135 fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
136 #FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
137 }
138
139 #[inline]
140 fn try_apply(
141 &mut self,
142 value: &dyn #bevy_reflect_path::PartialReflect
143 ) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
144 if let #bevy_reflect_path::ReflectRef::Struct(struct_value)
145 = #bevy_reflect_path::PartialReflect::reflect_ref(value) {
146 for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::Struct::iter_fields(struct_value)) {
147 let name = #bevy_reflect_path::Struct::name_at(struct_value, i).unwrap();
148 if let #FQOption::Some(v) = #bevy_reflect_path::Struct::field_mut(self, name) {
149 #bevy_reflect_path::PartialReflect::try_apply(v, value)?;
150 }
151 }
152 } else {
153 return #FQResult::Err(
154 #bevy_reflect_path::ApplyError::MismatchedKinds {
155 from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(value),
156 to_kind: #bevy_reflect_path::ReflectKind::Struct
157 }
158 );
159 }
160 #FQResult::Ok(())
161 }
162 #[inline]
163 fn reflect_kind(&self) -> #bevy_reflect_path::ReflectKind {
164 #bevy_reflect_path::ReflectKind::Struct
165 }
166 #[inline]
167 fn reflect_ref(&self) -> #bevy_reflect_path::ReflectRef {
168 #bevy_reflect_path::ReflectRef::Struct(self)
169 }
170 #[inline]
171 fn reflect_mut(&mut self) -> #bevy_reflect_path::ReflectMut {
172 #bevy_reflect_path::ReflectMut::Struct(self)
173 }
174 #[inline]
175 fn reflect_owned(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::ReflectOwned {
176 #bevy_reflect_path::ReflectOwned::Struct(self)
177 }
178
179 #common_methods
180
181 #clone_fn
182 }
183 }
184}