2023-12-30 23:55:05 +00:00
|
|
|
use proc_macro::TokenStream;
|
2024-01-09 01:25:20 +00:00
|
|
|
use proc_macro2::Ident;
|
2023-12-30 23:55:05 +00:00
|
|
|
use quote::{quote, ToTokens};
|
2024-01-06 20:52:12 +00:00
|
|
|
use syn::{Generics, Path, Attribute, GenericParam, parse_macro_input, DeriveInput, TypeParamBound};
|
2023-12-30 23:55:05 +00:00
|
|
|
|
|
|
|
mod enum_derive;
|
2024-01-06 20:52:12 +00:00
|
|
|
#[allow(unused_imports)]
|
2023-12-30 23:55:05 +00:00
|
|
|
use enum_derive::*;
|
|
|
|
|
|
|
|
mod struct_derive;
|
2024-01-06 20:52:12 +00:00
|
|
|
#[allow(unused_imports)]
|
2023-12-30 23:55:05 +00:00
|
|
|
use struct_derive::*;
|
|
|
|
|
2024-01-06 20:52:12 +00:00
|
|
|
#[allow(dead_code)]
|
2023-12-30 23:55:05 +00:00
|
|
|
pub(crate) struct ReflectDef {
|
2024-01-09 01:25:20 +00:00
|
|
|
//pub ident: Ident,
|
2023-12-30 23:55:05 +00:00
|
|
|
pub type_path: Path,
|
|
|
|
pub generics: Generics,
|
|
|
|
pub attributes: Vec<Attribute>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl syn::parse::Parse for ReflectDef {
|
|
|
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
|
|
|
let attributes = input.call(Attribute::parse_outer)?;
|
|
|
|
let type_path = Path::parse_mod_style(input)?;
|
2024-01-09 01:25:20 +00:00
|
|
|
//let ident = type_path. //type_path.require_ident()?;
|
2023-12-30 23:55:05 +00:00
|
|
|
let mut generics = input.parse::<Generics>()?;
|
|
|
|
generics.where_clause = input.parse()?;
|
|
|
|
|
|
|
|
Ok(Self {
|
2024-01-09 01:25:20 +00:00
|
|
|
//ident: ident.clone(),
|
2023-12-30 23:55:05 +00:00
|
|
|
type_path,
|
|
|
|
generics,
|
|
|
|
attributes,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[proc_macro_derive(Reflect)]
|
|
|
|
pub fn derive_reflect(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
|
|
|
|
|
|
let stream = match &input.data {
|
|
|
|
syn::Data::Enum(e) => {
|
|
|
|
enum_derive::derive_reflect_enum(&input, e)
|
|
|
|
},
|
|
|
|
syn::Data::Struct(s) => {
|
|
|
|
struct_derive::derive_reflect_struct(&input, s)
|
|
|
|
},
|
|
|
|
//syn::Data::Union(_) => todo!(),
|
|
|
|
_ => todo!()
|
|
|
|
};
|
|
|
|
|
|
|
|
proc_macro::TokenStream::from(stream)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Implements `Reflect` for Values. `ReflectRef` and `ReflectMut` will be the `Value`
|
|
|
|
/// variants, its used for simple types and primitives.
|
|
|
|
#[proc_macro]
|
|
|
|
pub fn impl_reflect_trait_value(input: TokenStream) -> TokenStream {
|
|
|
|
let reflect = syn::parse_macro_input!(input as ReflectDef);
|
|
|
|
|
2024-01-09 01:25:20 +00:00
|
|
|
let type_path = reflect.type_path;
|
|
|
|
// convert the type path to a string. This would not create a leading separator
|
|
|
|
let type_path_str = {
|
|
|
|
let idents: Vec<String> = type_path.segments.iter()
|
|
|
|
.map(|segment| segment.ident.to_string())
|
|
|
|
.collect();
|
|
|
|
idents.join("::")
|
|
|
|
};
|
2023-12-30 23:55:05 +00:00
|
|
|
|
|
|
|
let (impl_generics, ty_generics, where_clause) = reflect.generics.split_for_impl();
|
|
|
|
|
|
|
|
TokenStream::from(quote! {
|
|
|
|
impl #impl_generics lyra_engine::reflect::Reflect for #type_path #ty_generics #where_clause {
|
|
|
|
fn name(&self) -> ::std::string::String {
|
2024-01-09 01:25:20 +00:00
|
|
|
#type_path_str.to_string()
|
2023-12-30 23:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn type_id(&self) -> std::any::TypeId {
|
|
|
|
std::any::TypeId::of::<#type_path #ty_generics>()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn as_any(&self) -> &dyn std::any::Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) {
|
|
|
|
let val = val.as_any().downcast_ref::<Self>()
|
|
|
|
.expect("The type of `val` is not the same as `self`");
|
|
|
|
*self = val.clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clone_inner(&self) -> Box<dyn lyra_engine::reflect::Reflect> {
|
|
|
|
Box::new(self.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_ref(&self) -> lyra_engine::reflect::ReflectRef {
|
|
|
|
lyra_engine::reflect::ReflectRef::Value(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_mut(&mut self) -> lyra_engine::reflect::ReflectMut {
|
|
|
|
lyra_engine::reflect::ReflectMut::Value(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_val(&self) -> &dyn lyra_engine::reflect::Reflect {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_val_mut(&mut self) -> &mut dyn lyra_engine::reflect::Reflect {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn add_trait_bounds(mut generics: Generics, add_bounds: Vec<TypeParamBound>) -> Generics {
|
|
|
|
for param in &mut generics.params {
|
|
|
|
if let GenericParam::Type(ref mut type_param) = *param {
|
|
|
|
for bound in add_bounds.iter() {
|
|
|
|
type_param.bounds.push(bound.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
generics
|
|
|
|
}
|