summaryrefslogtreecommitdiff
path: root/engine-macros/src/reflection/field.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine-macros/src/reflection/field.rs')
-rw-r--r--engine-macros/src/reflection/field.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/engine-macros/src/reflection/field.rs b/engine-macros/src/reflection/field.rs
new file mode 100644
index 0000000..489d165
--- /dev/null
+++ b/engine-macros/src/reflection/field.rs
@@ -0,0 +1,96 @@
+use quote::{quote, ToTokens};
+
+use crate::reflection::visibility::generate as generate_visibility;
+
+pub struct ReflectionFieldGenOptions
+{
+ pub field_vis_override: Option<syn::Visibility>,
+ pub include_byte_offset: bool,
+}
+
+pub fn generate(
+ field: &syn::Field,
+ field_index: usize,
+ engine_crate_path: &syn::Path,
+ options: ReflectionFieldGenOptions,
+) -> proc_macro2::TokenStream
+{
+ let field_ident = &field.ident;
+
+ let field_type = &field.ty;
+
+ let field_name = if let Some(field_ident) = field_ident {
+ let field_name = syn::LitStr::new(&field_ident.to_string(), field_ident.span());
+
+ quote! { Some(#field_name) }
+ } else {
+ quote! { None }
+ };
+
+ let field_byte_offset = if options.include_byte_offset {
+ if let Some(field_ident) = field_ident {
+ quote! { Some(std::mem::offset_of!(Self, #field_ident)) }
+ } else {
+ quote! { Some(std::mem::offset_of!(Self, #field_index)) }
+ }
+ } else {
+ quote! { None }
+ };
+
+ // since std::any::type_name as const is not stable yet
+ let field_type_name = field_type.to_token_stream().to_string();
+
+ let field_vis = options.field_vis_override.as_ref().unwrap_or(&field.vis);
+
+ let field_reflection_vis = generate_visibility(field_vis, &engine_crate_path);
+
+ quote! {
+ #engine_crate_path::reflection::Field {
+ name: #field_name,
+ index: #field_index,
+ layout: std::alloc::Layout::new::<#field_type>(),
+ byte_offset: #field_byte_offset,
+ type_id: std::any::TypeId::of::<#field_type>(),
+ type_name: #field_type_name,
+ get_type: #engine_crate_path::reflection::FnWithDebug::new(|| {
+ struct SpecializationTarget<Field>(std::marker::PhantomData<Field>);
+
+ trait FieldHasReflection
+ {
+ fn field_type_reflection(&self)
+ -> Option<&'static #engine_crate_path::reflection::Type>;
+ }
+
+ trait FieldDoesNotHaveReflection
+ {
+ fn field_type_reflection(&self)
+ -> Option<&'static #engine_crate_path::reflection::Type>;
+ }
+
+ impl<Field> FieldDoesNotHaveReflection for &SpecializationTarget<Field>
+ {
+ fn field_type_reflection(&self)
+ -> Option<&'static #engine_crate_path::reflection::Type>
+ {
+ None
+ }
+ }
+
+ impl<Field> FieldHasReflection for SpecializationTarget<Field>
+ where
+ Field: #engine_crate_path::reflection::Reflection
+ {
+ fn field_type_reflection(&self)
+ -> Option<&'static #engine_crate_path::reflection::Type>
+ {
+ Some(Field::type_reflection())
+ }
+ }
+
+ (&SpecializationTarget::<#field_type>(std::marker::PhantomData))
+ .field_type_reflection()
+ }),
+ visibility: #field_reflection_vis
+ }
+ }
+}