diff options
Diffstat (limited to 'ecs-macros/src')
-rw-r--r-- | ecs-macros/src/lib.rs | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs index 6fe343f..8e801f9 100644 --- a/ecs-macros/src/lib.rs +++ b/ecs-macros/src/lib.rs @@ -1,18 +1,26 @@ use proc_macro::TokenStream; use quote::{quote, ToTokens}; use syn::spanned::Spanned; -use syn::{parse, Ident, Item, ItemEnum, ItemStruct, ItemUnion}; +use syn::{parse, Attribute, Ident, Item, ItemEnum, ItemStruct, ItemUnion}; -#[proc_macro_derive(Component)] +#[proc_macro_derive(Component, attributes(component))] pub fn component_derive(input: TokenStream) -> TokenStream { let item: TypeItem = parse::<Item>(input).unwrap().try_into().unwrap(); let item_ident = item.ident(); + let component_attr = item.component_attribute().unwrap_or_default(); + + let drop_last = component_attr.drop_last; + quote! { impl ecs::component::Component for #item_ident { + fn drop_last(&self) -> bool { + #drop_last + } + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self @@ -54,6 +62,29 @@ impl TypeItem Self::Union(union_item) => &union_item.ident, } } + + fn component_attribute(&self) -> Option<ComponentAttribute> + { + let item_attrs = match &self { + Self::Struct(struct_item) => &struct_item.attrs, + &Self::Enum(enum_item) => &enum_item.attrs, + &Self::Union(union_item) => &union_item.attrs, + }; + + let mut component_attr: Option<&Attribute> = None; + + for item_attr in item_attrs { + if component_attr.is_some() { + panic!("Expected only one component attribute"); + } + + if item_attr.path().get_ident()? == "component" { + component_attr = Some(item_attr); + } + } + + Some(ComponentAttribute::from_attribute(component_attr?).unwrap()) + } } impl TryFrom<Item> for TypeItem @@ -85,3 +116,33 @@ impl ToTokens for TypeItem } } } + +#[derive(Debug, Default)] +struct ComponentAttribute +{ + drop_last: bool, +} + +impl ComponentAttribute +{ + fn from_attribute(attribute: &Attribute) -> Result<Self, syn::Error> + { + let mut drop_last = false; + + attribute.parse_nested_meta(|meta| { + if meta + .path + .get_ident() + .is_some_and(|flag| flag == "drop_last") + { + drop_last = true; + + return Ok(()); + } + + Err(meta.error("Unrecognized token")) + })?; + + Ok(Self { drop_last }) + } +} |