summaryrefslogtreecommitdiff
path: root/ecs-macros
diff options
context:
space:
mode:
Diffstat (limited to 'ecs-macros')
-rw-r--r--ecs-macros/src/lib.rs65
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 })
+ }
+}