diff options
Diffstat (limited to 'ecs-macros/src')
-rw-r--r-- | ecs-macros/src/lib.rs | 66 |
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 + }) +} |