From f2120591b0051d4239de73960709248456e884e7 Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 11 Apr 2024 19:03:11 +0200 Subject: feat(ecs-macros): add drop_last attribute to Sole derive macro --- ecs-macros/src/lib.rs | 69 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 11 deletions(-) (limited to 'ecs-macros') diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs index 73709e4..dcc6d99 100644 --- a/ecs-macros/src/lib.rs +++ b/ecs-macros/src/lib.rs @@ -37,7 +37,9 @@ pub fn component_derive(input: TokenStream) -> TokenStream let item_ident = item.ident(); - let component_attr = item.component_attribute().unwrap_or_default(); + let component_attr = item + .attribute::("component") + .unwrap_or_default(); let drop_last = component_attr.drop_last; @@ -46,7 +48,8 @@ pub fn component_derive(input: TokenStream) -> TokenStream quote! { impl #ecs_path::component::Component for #item_ident { - fn drop_last(&self) -> bool { + fn drop_last(&self) -> bool + { #drop_last } @@ -74,18 +77,27 @@ pub fn component_derive(input: TokenStream) -> TokenStream .into() } -#[proc_macro_derive(Sole)] +#[proc_macro_derive(Sole, attributes(sole))] pub fn sole_derive(input: TokenStream) -> TokenStream { let item: TypeItem = parse::(input).unwrap().try_into().unwrap(); let item_ident = item.ident(); + let sole_attr = item.attribute::("sole").unwrap_or_default(); + + let drop_last = sole_attr.drop_last; + let ecs_path = find_engine_ecs_crate_path().unwrap_or_else(|| syn_path!(ecs)); quote! { impl #ecs_path::sole::Sole for #item_ident { + fn drop_last(&self) -> bool + { + #drop_last + } + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self @@ -108,6 +120,11 @@ pub fn sole_derive(input: TokenStream) -> TokenStream .into() } +trait FromAttribute: Sized +{ + fn from_attribute(attribute: &Attribute) -> Result; +} + enum TypeItem { Struct(ItemStruct), @@ -126,7 +143,7 @@ impl TypeItem } } - fn component_attribute(&self) -> Option + fn attribute(&self, attr_ident: &str) -> Option { let item_attrs = match &self { Self::Struct(struct_item) => &struct_item.attrs, @@ -134,19 +151,19 @@ impl TypeItem &Self::Union(union_item) => &union_item.attrs, }; - let mut component_attr: Option<&Attribute> = None; + let mut attr: Option<&Attribute> = None; for item_attr in item_attrs { - if component_attr.is_some() { - panic!("Expected only one component attribute"); + if attr.is_some() { + panic!("Expected only one {} attribute", attr_ident); } - if item_attr.path().get_ident()? == "component" { - component_attr = Some(item_attr); + if item_attr.path().get_ident()? == attr_ident { + attr = Some(item_attr); } } - Some(ComponentAttribute::from_attribute(component_attr?).unwrap()) + Some(Attr::from_attribute(attr?).unwrap()) } } @@ -186,7 +203,37 @@ struct ComponentAttribute drop_last: bool, } -impl ComponentAttribute +impl FromAttribute for ComponentAttribute +{ + fn from_attribute(attribute: &Attribute) -> Result + { + 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 }) + } +} + +#[derive(Debug, Default)] +struct SoleAttribute +{ + drop_last: bool, +} + +impl FromAttribute for SoleAttribute { fn from_attribute(attribute: &Attribute) -> Result { -- cgit v1.2.3-18-g5258