summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-06-16 19:07:36 +0200
committerHampusM <hampus@hampusmat.com>2026-06-16 19:20:17 +0200
commitc79f7883c099f1624f9666fb8691ffc5022c1bf5 (patch)
treedd3c4689377d178d1efa993fb2c21d2cc733f49f
parent166da477e761416a87ffd5fb8fc49ceaf7f53690 (diff)
feat(engine): add default value retrieval to type reflectionHEADmaster
-rw-r--r--engine-macros/src/reflection.rs1
-rw-r--r--engine-macros/src/reflection/default_value.rs42
-rw-r--r--engine-macros/src/reflection/enum_impl.rs8
-rw-r--r--engine-macros/src/reflection/struct_impl.rs8
-rw-r--r--engine-reflection/src/lib.rs78
5 files changed, 133 insertions, 4 deletions
diff --git a/engine-macros/src/reflection.rs b/engine-macros/src/reflection.rs
index 825094b..5d40e0c 100644
--- a/engine-macros/src/reflection.rs
+++ b/engine-macros/src/reflection.rs
@@ -1,3 +1,4 @@
+mod default_value;
mod enum_impl;
mod field;
mod struct_impl;
diff --git a/engine-macros/src/reflection/default_value.rs b/engine-macros/src/reflection/default_value.rs
new file mode 100644
index 0000000..567c3b1
--- /dev/null
+++ b/engine-macros/src/reflection/default_value.rs
@@ -0,0 +1,42 @@
+use quote::quote;
+
+pub fn gen_get_default_value_fn(
+ type_ident: &proc_macro2::Ident,
+ type_generics: &syn::TypeGenerics,
+) -> proc_macro2::TokenStream
+{
+ quote! {
+ struct SpecializationTarget<T>(std::marker::PhantomData<T>);
+
+ trait HasDefaultValue
+ {
+ fn default_value_fn(&self) -> Option<fn() -> Box<dyn std::any::Any>>;
+ }
+
+ trait NoDefaultValue
+ {
+ fn default_value_fn(&self) -> Option<fn() -> Box<dyn std::any::Any>>;
+ }
+
+ impl<T> NoDefaultValue for &SpecializationTarget<T>
+ {
+ fn default_value_fn(&self) -> Option<fn() -> Box<dyn std::any::Any>>
+ {
+ None
+ }
+ }
+
+ impl<T> HasDefaultValue for SpecializationTarget<T>
+ where
+ T: std::default::Default + 'static
+ {
+ fn default_value_fn(&self) -> Option<fn() -> Box<dyn std::any::Any>>
+ {
+ Some(|| Box::new(T::default()))
+ }
+ }
+
+ (&SpecializationTarget::<#type_ident #type_generics>(std::marker::PhantomData))
+ .default_value_fn()
+ }
+}
diff --git a/engine-macros/src/reflection/enum_impl.rs b/engine-macros/src/reflection/enum_impl.rs
index 14142bf..611da6d 100644
--- a/engine-macros/src/reflection/enum_impl.rs
+++ b/engine-macros/src/reflection/enum_impl.rs
@@ -1,5 +1,6 @@
use quote::{format_ident, quote, ToTokens};
+use crate::reflection::default_value::gen_get_default_value_fn;
use crate::reflection::field::{generate as generate_field, ReflectionFieldGenOptions};
use crate::util::{find_engine_crate_path, syn_path, SynPathExt};
@@ -238,6 +239,8 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream
}
};
+ let get_default_value_fn = gen_get_default_value_fn(&input_ident, &type_generics);
+
quote! {
#[doc(hidden)]
mod #mod_name {
@@ -254,7 +257,10 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream
variants: &[#(#variants),*],
is_unit_only: #is_unit_only,
discriminant_layout: #discriminant_layout,
- fields_layout: #fields_layout
+ fields_layout: #fields_layout,
+ get_default_value: || {
+ #get_default_value_fn
+ }
}
)
};
diff --git a/engine-macros/src/reflection/struct_impl.rs b/engine-macros/src/reflection/struct_impl.rs
index b1adea5..ce1086b 100644
--- a/engine-macros/src/reflection/struct_impl.rs
+++ b/engine-macros/src/reflection/struct_impl.rs
@@ -1,5 +1,6 @@
use quote::quote;
+use crate::reflection::default_value::gen_get_default_value_fn;
use crate::reflection::field::{generate as generate_field, ReflectionFieldGenOptions};
use crate::util::{find_engine_crate_path, syn_path, SynPathExt};
@@ -49,6 +50,8 @@ pub fn generate(input: syn::ItemStruct) -> proc_macro2::TokenStream
)
});
+ let get_default_value_fn = gen_get_default_value_fn(&input_ident, &type_generics);
+
quote! {
unsafe impl #impl_generics #engine_crate_path::reflection::Reflection for
#input_ident #type_generics #where_clause
@@ -59,7 +62,10 @@ pub fn generate(input: syn::ItemStruct) -> proc_macro2::TokenStream
#engine_crate_path::reflection::Struct {
fields: &[
#(#fields),*
- ]
+ ],
+ get_default_value: || {
+ #get_default_value_fn
+ }
}
)
};
diff --git a/engine-reflection/src/lib.rs b/engine-reflection/src/lib.rs
index c8b0004..4e5e8d8 100644
--- a/engine-reflection/src/lib.rs
+++ b/engine-reflection/src/lib.rs
@@ -1,5 +1,5 @@
use std::alloc::Layout;
-use std::any::{type_name, TypeId};
+use std::any::{type_name, Any, TypeId};
use std::borrow::Cow;
use std::fmt::Debug;
@@ -64,12 +64,50 @@ impl Type
_ => None,
}
}
+
+ #[inline]
+ pub fn default_value(&self) -> Option<Box<dyn Any>>
+ {
+ match self {
+ Self::Struct(struct_type) => struct_type.default_value(),
+ Self::Enum(enum_type) => enum_type.default_value(),
+ Self::Literal(literal_type) => literal_type.default_value(),
+ Self::Array(_) | Self::Slice(_) => None,
+ }
+ }
+
+ #[inline]
+ pub fn has_default_value(&self) -> bool
+ {
+ match self {
+ Self::Struct(struct_type) => struct_type.has_default_value(),
+ Self::Enum(enum_type) => enum_type.has_default_value(),
+ Self::Literal(literal_type) => literal_type.has_default_value(),
+ Self::Array(_) | Self::Slice(_) => false,
+ }
+ }
}
#[derive(Debug, Clone)]
pub struct Struct
{
pub fields: &'static [Field],
+ pub get_default_value: fn() -> Option<DefaultValueFn>,
+}
+
+impl Struct
+{
+ #[inline]
+ pub fn default_value(&self) -> Option<Box<dyn Any>>
+ {
+ Some((self.get_default_value)()?())
+ }
+
+ #[inline]
+ pub fn has_default_value(&self) -> bool
+ {
+ (self.get_default_value)().is_some()
+ }
}
#[derive(Debug, Clone)]
@@ -83,6 +121,23 @@ pub struct Enum
pub discriminant_layout: Layout,
pub fields_layout: Option<Layout>,
+
+ pub get_default_value: fn() -> Option<DefaultValueFn>,
+}
+
+impl Enum
+{
+ #[inline]
+ pub fn default_value(&self) -> Option<Box<dyn Any>>
+ {
+ Some((self.get_default_value)()?())
+ }
+
+ #[inline]
+ pub fn has_default_value(&self) -> bool
+ {
+ (self.get_default_value)().is_some()
+ }
}
#[derive(Debug, Clone)]
@@ -169,6 +224,22 @@ pub struct Literal
pub type_id: TypeId,
pub ty: LiteralType,
pub type_name: fn() -> &'static str,
+ pub get_default_value: fn() -> Option<DefaultValueFn>,
+}
+
+impl Literal
+{
+ #[inline]
+ pub fn default_value(&self) -> Option<Box<dyn Any>>
+ {
+ Some((self.get_default_value)()?())
+ }
+
+ #[inline]
+ pub fn has_default_value(&self) -> bool
+ {
+ (self.get_default_value)().is_some()
+ }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -219,7 +290,8 @@ macro_rules! impl_reflection_for_literals {
layout: Layout::new::<$literal>(),
type_id: TypeId::of::<$literal>(),
ty: LiteralType::$literal_type,
- type_name: || type_name::<$literal>()
+ type_name: || type_name::<$literal>(),
+ get_default_value: || Some(|| Box::new(Self::default()))
});
}
)*
@@ -288,3 +360,5 @@ impl<Value: Debug> Debug for FnWithDebug<Value>
.finish()
}
}
+
+type DefaultValueFn = fn() -> Box<dyn Any>;