summaryrefslogtreecommitdiff
path: root/ecs-macros
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-02-26 20:05:27 +0100
committerHampusM <hampus@hampusmat.com>2024-02-26 20:16:27 +0100
commit815d04da602c58ed8b13eeb612fe73180204039d (patch)
treec3703e598656c070edbc271ccaa9117e071d6d4f /ecs-macros
parent1019924a29527eba2c8ec8bd976ece6ed76075b0 (diff)
fix(ecs): make Component trait not automatic & add derive macro
Diffstat (limited to 'ecs-macros')
-rw-r--r--ecs-macros/Cargo.toml13
-rw-r--r--ecs-macros/src/lib.rs79
2 files changed, 92 insertions, 0 deletions
diff --git a/ecs-macros/Cargo.toml b/ecs-macros/Cargo.toml
new file mode 100644
index 0000000..792ca34
--- /dev/null
+++ b/ecs-macros/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "ecs-macros"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+quote = "1.0.35"
+syn = { version = "2.0.51", features = ["full"] }
+proc-macro2 = "1.0.78"
+
diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs
new file mode 100644
index 0000000..e37d6a4
--- /dev/null
+++ b/ecs-macros/src/lib.rs
@@ -0,0 +1,79 @@
+use proc_macro::TokenStream;
+use quote::{quote, ToTokens};
+use syn::spanned::Spanned;
+use syn::{parse, Ident, Item, ItemEnum, ItemStruct, ItemUnion};
+
+#[proc_macro_derive(Component)]
+pub fn component_derive(input: TokenStream) -> TokenStream
+{
+ let item: TypeItem = parse::<Item>(input).unwrap().try_into().unwrap();
+
+ let item_ident = item.ident();
+
+ quote! {
+ impl ecs::component::Component for #item_ident
+ {
+ fn as_any_mut(&mut self) -> &mut dyn std::any::Any
+ {
+ self
+ }
+
+ fn as_any(&self) -> &dyn std::any::Any
+ {
+ self
+ }
+ }
+
+ impl ecs::system::Input for #item_ident {}
+ }
+ .into()
+}
+
+enum TypeItem
+{
+ Struct(ItemStruct),
+ Enum(ItemEnum),
+ Union(ItemUnion),
+}
+
+impl TypeItem
+{
+ fn ident(&self) -> &Ident
+ {
+ match self {
+ Self::Struct(struct_item) => &struct_item.ident,
+ Self::Enum(enum_item) => &enum_item.ident,
+ Self::Union(union_item) => &union_item.ident,
+ }
+ }
+}
+
+impl TryFrom<Item> for TypeItem
+{
+ type Error = syn::Error;
+
+ fn try_from(item: Item) -> Result<Self, Self::Error>
+ {
+ match item {
+ Item::Struct(struct_item) => Ok(Self::Struct(struct_item)),
+ Item::Enum(enum_item) => Ok(Self::Enum(enum_item)),
+ Item::Union(union_item) => Ok(Self::Union(union_item)),
+ _ => Err(syn::Error::new(
+ item.span(),
+ "Expected a struct, a enum or a union",
+ )),
+ }
+ }
+}
+
+impl ToTokens for TypeItem
+{
+ fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream)
+ {
+ match self {
+ Self::Struct(struct_item) => struct_item.to_tokens(tokens),
+ Self::Enum(enum_item) => enum_item.to_tokens(tokens),
+ Self::Union(union_item) => union_item.to_tokens(tokens),
+ }
+ }
+}