summaryrefslogtreecommitdiff
path: root/ecs-macros/src/lib.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-04-11 17:50:34 +0200
committerHampusM <hampus@hampusmat.com>2024-04-11 17:50:54 +0200
commitf18f020d38ab3d0ab6b290159dff34f7431d2fd2 (patch)
treecc47d578f1c4db869d38f8f84ff885a6d263d55d /ecs-macros/src/lib.rs
parente028d89e15fd219854cbd7122d63ebd2fa37d390 (diff)
fix(ecs-macros): allow for using derive macros via the engine crate
Diffstat (limited to 'ecs-macros/src/lib.rs')
-rw-r--r--ecs-macros/src/lib.rs66
1 files changed, 60 insertions, 6 deletions
diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs
index 17a9be6..73709e4 100644
--- a/ecs-macros/src/lib.rs
+++ b/ecs-macros/src/lib.rs
@@ -1,7 +1,34 @@
+use std::path::PathBuf as FsPathBuf;
+
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::spanned::Spanned;
-use syn::{parse, Attribute, Ident, Item, ItemEnum, ItemStruct, ItemUnion};
+use syn::{parse, Attribute, Ident, Item, ItemEnum, ItemStruct, ItemUnion, Path};
+use toml::value::{Table as TomlTable, Value as TomlValue};
+
+macro_rules! syn_path {
+ ($first_segment: ident $(::$segment: ident)*) => {
+ ::syn::Path {
+ leading_colon: None,
+ segments: ::syn::punctuated::Punctuated::from_iter([
+ syn_path_segment!($first_segment),
+ $(syn_path_segment!($segment),)*
+ ])
+ }
+ };
+}
+
+macro_rules! syn_path_segment {
+ ($segment: ident) => {
+ ::syn::PathSegment {
+ ident: ::proc_macro2::Ident::new(
+ stringify!($segment),
+ ::proc_macro2::Span::call_site(),
+ ),
+ arguments: ::syn::PathArguments::None,
+ }
+ };
+}
#[proc_macro_derive(Component, attributes(component))]
pub fn component_derive(input: TokenStream) -> TokenStream
@@ -14,8 +41,10 @@ pub fn component_derive(input: TokenStream) -> TokenStream
let drop_last = component_attr.drop_last;
+ let ecs_path = find_engine_ecs_crate_path().unwrap_or_else(|| syn_path!(ecs));
+
quote! {
- impl ecs::component::Component for #item_ident
+ impl #ecs_path::component::Component for #item_ident
{
fn drop_last(&self) -> bool {
#drop_last
@@ -32,9 +61,9 @@ pub fn component_derive(input: TokenStream) -> TokenStream
}
}
- impl ecs::system::Input for #item_ident {}
+ impl #ecs_path::system::Input for #item_ident {}
- impl ecs::type_name::TypeName for #item_ident
+ impl #ecs_path::type_name::TypeName for #item_ident
{
fn type_name(&self) -> &'static str
{
@@ -52,8 +81,10 @@ pub fn sole_derive(input: TokenStream) -> TokenStream
let item_ident = item.ident();
+ let ecs_path = find_engine_ecs_crate_path().unwrap_or_else(|| syn_path!(ecs));
+
quote! {
- impl ecs::sole::Sole for #item_ident
+ impl #ecs_path::sole::Sole for #item_ident
{
fn as_any_mut(&mut self) -> &mut dyn std::any::Any
{
@@ -66,7 +97,7 @@ pub fn sole_derive(input: TokenStream) -> TokenStream
}
}
- impl ecs::type_name::TypeName for #item_ident
+ impl #ecs_path::type_name::TypeName for #item_ident
{
fn type_name(&self) -> &'static str
{
@@ -178,3 +209,26 @@ impl ComponentAttribute
Ok(Self { drop_last })
}
}
+
+fn find_engine_ecs_crate_path() -> Option<Path>
+{
+ let cargo_manifest_dir = FsPathBuf::from(std::env::var("CARGO_MANIFEST_DIR").ok()?);
+
+ let crate_manifest = std::fs::read_to_string(cargo_manifest_dir.join("Cargo.toml"))
+ .ok()?
+ .parse::<TomlTable>()
+ .expect("Failed to parse crate manifest file");
+
+ let crate_dependencies = match crate_manifest.get("dependencies")? {
+ TomlValue::Table(dependencies) => Some(dependencies),
+ _ => None,
+ }?;
+
+ crate_dependencies.iter().find_map(|(crate_dep_name, _)| {
+ if crate_dep_name == "engine" {
+ return Some(syn_path!(engine::ecs));
+ }
+
+ None
+ })
+}