Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/derive/src/impls/common.rs
6600 views
1
use bevy_macro_utils::fq_std::{FQAny, FQOption, FQResult};
2
3
use quote::quote;
4
5
use crate::{derive_data::ReflectMeta, where_clause_options::WhereClauseOptions};
6
7
pub fn impl_full_reflect(where_clause_options: &WhereClauseOptions) -> proc_macro2::TokenStream {
8
let meta = where_clause_options.meta();
9
let bevy_reflect_path = meta.bevy_reflect_path();
10
let type_path = meta.type_path();
11
12
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
13
let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);
14
15
let any_impls = if meta.is_remote_wrapper() {
16
quote! {
17
#[inline]
18
fn into_any(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #FQAny> {
19
#bevy_reflect_path::__macro_exports::alloc_utils::Box::new(self.0)
20
}
21
22
#[inline]
23
fn as_any(&self) -> &dyn #FQAny {
24
&self.0
25
}
26
27
#[inline]
28
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
29
&mut self.0
30
}
31
}
32
} else {
33
quote! {
34
#[inline]
35
fn into_any(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #FQAny> {
36
self
37
}
38
39
#[inline]
40
fn as_any(&self) -> &dyn #FQAny {
41
self
42
}
43
44
#[inline]
45
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
46
self
47
}
48
}
49
};
50
51
quote! {
52
impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause {
53
#any_impls
54
55
#[inline]
56
fn into_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect> {
57
self
58
}
59
60
#[inline]
61
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
62
self
63
}
64
65
#[inline]
66
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
67
self
68
}
69
70
#[inline]
71
fn set(
72
&mut self,
73
value: #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>
74
) -> #FQResult<(), #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>> {
75
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
76
#FQResult::Ok(())
77
}
78
}
79
}
80
}
81
82
pub fn common_partial_reflect_methods(
83
meta: &ReflectMeta,
84
default_partial_eq_delegate: impl FnOnce() -> Option<proc_macro2::TokenStream>,
85
default_hash_delegate: impl FnOnce() -> Option<proc_macro2::TokenStream>,
86
) -> proc_macro2::TokenStream {
87
let bevy_reflect_path = meta.bevy_reflect_path();
88
89
let debug_fn = meta.attrs().get_debug_impl();
90
let partial_eq_fn = meta
91
.attrs()
92
.get_partial_eq_impl(bevy_reflect_path)
93
.or_else(move || {
94
let default_delegate = default_partial_eq_delegate();
95
default_delegate.map(|func| {
96
quote! {
97
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<bool> {
98
(#func)(self, value)
99
}
100
}
101
})
102
});
103
let hash_fn = meta
104
.attrs()
105
.get_hash_impl(bevy_reflect_path)
106
.or_else(move || {
107
let default_delegate = default_hash_delegate();
108
default_delegate.map(|func| {
109
quote! {
110
fn reflect_hash(&self) -> #FQOption<u64> {
111
(#func)(self)
112
}
113
}
114
})
115
});
116
117
quote! {
118
#[inline]
119
fn try_into_reflect(
120
self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>
121
) -> #FQResult<#bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect>, #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect>> {
122
#FQResult::Ok(self)
123
}
124
125
#[inline]
126
fn try_as_reflect(&self) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
127
#FQOption::Some(self)
128
}
129
130
#[inline]
131
fn try_as_reflect_mut(&mut self) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
132
#FQOption::Some(self)
133
}
134
135
#[inline]
136
fn into_partial_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
137
self
138
}
139
140
#[inline]
141
fn as_partial_reflect(&self) -> &dyn #bevy_reflect_path::PartialReflect {
142
self
143
}
144
145
#[inline]
146
fn as_partial_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::PartialReflect {
147
self
148
}
149
150
#hash_fn
151
152
#partial_eq_fn
153
154
#debug_fn
155
}
156
}
157
158
#[cfg(feature = "auto_register")]
159
pub fn reflect_auto_registration(meta: &ReflectMeta) -> Option<proc_macro2::TokenStream> {
160
if meta.attrs().no_auto_register() {
161
return None;
162
}
163
164
let bevy_reflect_path = meta.bevy_reflect_path();
165
let type_path = meta.type_path();
166
167
if type_path.impl_is_generic() {
168
return None;
169
};
170
171
#[cfg(feature = "auto_register_static")]
172
{
173
use std::{
174
env, fs,
175
io::Write,
176
path::PathBuf,
177
sync::{LazyLock, Mutex},
178
};
179
180
// Skip unless env var is set, otherwise this might slow down rust-analyzer
181
if env::var("BEVY_REFLECT_AUTO_REGISTER_STATIC").is_err() {
182
return None;
183
}
184
185
// Names of registrations functions will be stored in this file.
186
// To allow writing to this file from multiple threads during compilation it is protected by mutex.
187
// This static is valid for the duration of compilation of one crate and we have one file per crate,
188
// so it is enough to protect compilation threads from overwriting each other.
189
// This file is reset on every crate recompilation.
190
//
191
// It might make sense to replace the mutex with File::lock when file_lock feature becomes stable.
192
static REGISTRATION_FNS_EXPORT: LazyLock<Mutex<fs::File>> = LazyLock::new(|| {
193
let path = PathBuf::from("target").join("bevy_reflect_type_registrations");
194
fs::DirBuilder::new()
195
.recursive(true)
196
.create(&path)
197
.unwrap_or_else(|_| panic!("Failed to create {path:?}"));
198
let file_path = path.join(env::var("CARGO_CRATE_NAME").unwrap());
199
let file = fs::OpenOptions::new()
200
.create(true)
201
.write(true)
202
.truncate(true)
203
.open(&file_path)
204
.unwrap_or_else(|_| panic!("Failed to create {file_path:?}"));
205
Mutex::new(file)
206
});
207
208
let export_name = format!("_bevy_reflect_register_{}", uuid::Uuid::new_v4().as_u128());
209
210
{
211
let mut file = REGISTRATION_FNS_EXPORT.lock().unwrap();
212
writeln!(file, "{export_name}")
213
.unwrap_or_else(|_| panic!("Failed to write registration function {export_name}"));
214
// We must sync_data to ensure all content is written before releasing the lock.
215
file.sync_data().unwrap();
216
};
217
218
Some(quote! {
219
/// # Safety
220
/// This function must only be used by the `load_type_registrations` macro.
221
#[unsafe(export_name=#export_name)]
222
pub unsafe extern "Rust" fn bevy_register_type(registry: &mut #bevy_reflect_path::TypeRegistry) {
223
<#type_path as #bevy_reflect_path::__macro_exports::RegisterForReflection>::__register(registry);
224
}
225
})
226
}
227
228
#[cfg(all(
229
feature = "auto_register_inventory",
230
not(feature = "auto_register_static")
231
))]
232
{
233
Some(quote! {
234
#bevy_reflect_path::__macro_exports::auto_register::inventory::submit!{
235
#bevy_reflect_path::__macro_exports::auto_register::AutomaticReflectRegistrations(
236
<#type_path as #bevy_reflect_path::__macro_exports::auto_register::RegisterForReflection>::__register
237
)
238
}
239
})
240
}
241
}
242
243