summaryrefslogtreecommitdiff
path: root/ecs-macros
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-05-21 17:55:20 +0200
committerHampusM <hampus@hampusmat.com>2026-05-21 17:55:20 +0200
commit8022e8998290b067b8aa0cb9cba8ba410826bdab (patch)
tree7171e79ce530e03079046ee8fd12167160c45480 /ecs-macros
parent412cee02c252f91bcf0b70a3f5cc5fca6d2b4c62 (diff)
chore: rename ecs* crates to engine-ecs*
Diffstat (limited to 'ecs-macros')
-rw-r--r--ecs-macros/Cargo.toml14
-rw-r--r--ecs-macros/src/lib.rs316
2 files changed, 0 insertions, 330 deletions
diff --git a/ecs-macros/Cargo.toml b/ecs-macros/Cargo.toml
deleted file mode 100644
index cf323fc..0000000
--- a/ecs-macros/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[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"
-toml = "0.8.12"
-
diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs
deleted file mode 100644
index 7d00736..0000000
--- a/ecs-macros/src/lib.rs
+++ /dev/null
@@ -1,316 +0,0 @@
-#![deny(clippy::all, clippy::pedantic)]
-use std::path::PathBuf as FsPathBuf;
-
-use proc_macro::TokenStream;
-use quote::{format_ident, quote, ToTokens};
-use syn::spanned::Spanned;
-use syn::{
- parse,
- Attribute,
- Generics,
- 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,
- }
- };
-}
-
-/// Generates a `Component` implementation.
-///
-/// # Panics
-/// Will panic if:
-/// - Not attributed to a type item
-/// - The attributed-to type item is generic
-/// - If parsing the user crate's `Cargo.toml` file fails.
-#[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();
-
- let (impl_generics, type_generics, where_clause) = item.generics().split_for_impl();
-
- let ecs_path = find_engine_ecs_crate_path().unwrap_or_else(|| syn_path!(ecs));
-
- assert!(
- item.generics().params.is_empty(),
- "Generic types are not supported as components"
- );
-
- let id_var_ident = format_ident!("{}_ID", item_ident.to_string().to_uppercase());
-
- let id_var = quote! {
- static #id_var_ident: LazyLock<Uid> = LazyLock::new(|| {
- Uid::new_unique(UidKind::Component)
- });
- };
-
- let mod_ident = format_ident!(
- "__ecs_priv_component_impl_{}",
- item_ident.to_string().to_lowercase()
- );
-
- quote! {
- mod #mod_ident {
- use ::std::any::{Any, TypeId};
- use ::std::sync::{LazyLock, Mutex};
-
- use #ecs_path::component::Component;
- use #ecs_path::uid::{Uid, Kind as UidKind};
- use #ecs_path::system::Input as SystemInput;
-
- use super::*;
-
- #id_var
-
- impl #impl_generics Component for #item_ident #type_generics
- #where_clause
- {
- fn id() -> Uid
- {
- *#id_var_ident
- }
-
- fn name(&self) -> &'static str
- {
- std::any::type_name::<Self>()
- }
- }
-
- impl #impl_generics SystemInput for #item_ident #type_generics
- #where_clause
- {
- }
- }
- }
- .into()
-}
-
-/// Generates a `Sole` implementation.
-///
-/// # Panics
-/// Will panic if not attributed to a type item or if parsing the user crate's
-/// `Cargo.toml` file fails.
-#[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 (impl_generics, type_generics, where_clause) = item.generics().split_for_impl();
-
- let ecs_path = find_engine_ecs_crate_path().unwrap_or_else(|| syn_path!(ecs));
-
- quote! {
- impl #impl_generics #ecs_path::sole::Sole for #item_ident #type_generics
- #where_clause
- {
- fn drop_last(&self) -> bool
- {
- #drop_last
- }
-
- fn as_any_mut(&mut self) -> &mut dyn std::any::Any
- {
- self
- }
-
- fn as_any(&self) -> &dyn std::any::Any
- {
- self
- }
- }
- }
- .into()
-}
-
-trait FromAttribute: Sized
-{
- fn from_attribute(attribute: &Attribute) -> Result<Self, syn::Error>;
-}
-
-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,
- }
- }
-
- fn attribute<Attr: FromAttribute>(&self, attr_ident: &str) -> Option<Attr>
- {
- 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 attr: Option<&Attribute> = None;
-
- for item_attr in item_attrs {
- assert!(attr.is_none(), "Expected only one {attr_ident} attribute");
-
- if item_attr.path().get_ident()? == attr_ident {
- attr = Some(item_attr);
- }
- }
-
- Some(Attr::from_attribute(attr?).unwrap())
- }
-
- fn generics(&self) -> &Generics
- {
- match self {
- Self::Struct(struct_item) => &struct_item.generics,
- Self::Enum(enum_item) => &enum_item.generics,
- Self::Union(union_item) => &union_item.generics,
- }
- }
-}
-
-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),
- }
- }
-}
-
-#[derive(Debug, Default)]
-struct SoleAttribute
-{
- drop_last: bool,
-}
-
-impl FromAttribute for SoleAttribute
-{
- 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 })
- }
-}
-
-fn find_engine_ecs_crate_path() -> Option<Path>
-{
- let cargo_manifest_dir = FsPathBuf::from(std::env::var("CARGO_MANIFEST_DIR").ok()?);
-
- let cargo_crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
- let cargo_pkg_name = std::env::var("CARGO_PKG_NAME").ok()?;
-
- if cargo_pkg_name == "ecs" && cargo_crate_name != "ecs" {
- // Macro is used by a ecs crate example/test/benchmark
- return Some(syn_path!(ecs));
- }
-
- 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 package = match crate_manifest.get("package")? {
- TomlValue::Table(package) => Some(package),
- _ => None,
- }?;
-
- let package_name = match package.get("name")? {
- TomlValue::String(package_name) => Some(package_name),
- _ => None,
- }?;
-
- if package_name == "ecs" {
- return Some(syn_path!(crate));
- }
-
- 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
- })
-}