187 lines
5.8 KiB
Rust
187 lines
5.8 KiB
Rust
use proc_macro::TokenStream;
|
|
use proc_macro2::Ident;
|
|
use quote::quote;
|
|
use syn::{parse_macro_input, Attribute, DeriveInput, GenericParam, Generics, Path, TypeParamBound};
|
|
|
|
mod enum_derive;
|
|
#[allow(unused_imports)]
|
|
use enum_derive::*;
|
|
|
|
mod struct_derive;
|
|
#[allow(unused_imports)]
|
|
use struct_derive::*;
|
|
|
|
mod struct_macro;
|
|
|
|
/* #[proc_macro_attribute(attributes(reflect))]
|
|
pub fn reflect(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
item
|
|
} */
|
|
|
|
pub(crate) struct FieldAttributes(Vec<ReflectAttribute>);
|
|
|
|
impl FieldAttributes {
|
|
/// Searches for a usage of the 'reflect' attribute and returns a list of the
|
|
/// things used in the usage.
|
|
pub fn from_vec(v: &Vec<syn::Attribute>) -> Result<Self, syn::Error> {
|
|
let s: Result<Vec<ReflectAttribute>, _> = v.iter().filter_map(|att| match &att.meta {
|
|
syn::Meta::Path(_) => None,
|
|
syn::Meta::List(l) => {
|
|
Some(syn::parse::<ReflectAttribute>(l.tokens.clone().into()))
|
|
}
|
|
syn::Meta::NameValue(_) => None
|
|
}).collect();
|
|
|
|
Ok(Self(s?))
|
|
}
|
|
|
|
pub fn has_skip(&self) -> bool {
|
|
self.0.iter().any(|a| *a == ReflectAttribute::Skip)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub(crate) enum ReflectAttribute {
|
|
Skip
|
|
}
|
|
|
|
impl syn::parse::Parse for ReflectAttribute {
|
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
|
let ident: Ident = input.parse()?;
|
|
let ident_str = ident.to_string().to_lowercase();
|
|
|
|
match ident_str.as_str() {
|
|
"skip" => Ok(Self::Skip),
|
|
_ => Err(syn::Error::new(ident.span(), "Unknown reflect attribute flag"))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub(crate) struct ReflectDef {
|
|
//pub ident: Ident,
|
|
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)?;
|
|
//let ident = type_path. //type_path.require_ident()?;
|
|
let mut generics = input.parse::<Generics>()?;
|
|
/* let f: Punctuated<GenericParam, Token![,]> = input.parse_terminated(GenericParam::parse, Token![,])?;
|
|
generics.params = f; */
|
|
generics.where_clause = input.parse()?;
|
|
|
|
Ok(Self {
|
|
//ident: ident.clone(),
|
|
type_path,
|
|
generics,
|
|
attributes,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[proc_macro_derive(Reflect, attributes(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);
|
|
|
|
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("::")
|
|
};
|
|
|
|
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 {
|
|
#type_path_str.to_string()
|
|
}
|
|
|
|
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 as_boxed_any(self: Box<Self>) -> Box<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
|
|
}
|
|
|
|
#[proc_macro]
|
|
pub fn impl_reflect_simple_struct(input: TokenStream) -> TokenStream {
|
|
struct_macro::impl_reflect_simple_struct(input)
|
|
} |