diff options
author | HampusM <hampus@hampusmat.com> | 2024-04-11 19:03:11 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-04-11 19:07:12 +0200 |
commit | f2120591b0051d4239de73960709248456e884e7 (patch) | |
tree | 199bb429e5b64b7362b7cf9c8afcedfba42282f8 /ecs-macros | |
parent | d435d9b80c46f995d56d385bc8a0de29e6d865cb (diff) |
feat(ecs-macros): add drop_last attribute to Sole derive macro
Diffstat (limited to 'ecs-macros')
-rw-r--r-- | ecs-macros/src/lib.rs | 69 |
1 files changed, 58 insertions, 11 deletions
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::<ComponentAttribute>("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::<Item>(input).unwrap().try_into().unwrap(); let item_ident = item.ident(); + let sole_attr = item.attribute::<SoleAttribute>("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<Self, syn::Error>; +} + enum TypeItem { Struct(ItemStruct), @@ -126,7 +143,7 @@ impl TypeItem } } - fn component_attribute(&self) -> Option<ComponentAttribute> + fn attribute<Attr: FromAttribute>(&self, attr_ident: &str) -> Option<Attr> { 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<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 }) + } +} + +#[derive(Debug, Default)] +struct SoleAttribute +{ + drop_last: bool, +} + +impl FromAttribute for SoleAttribute { fn from_attribute(attribute: &Attribute) -> Result<Self, syn::Error> { |