summaryrefslogtreecommitdiff
path: root/ecs-macros/src/lib.rs
blob: e37d6a45351044ec1f662c49ba3e86ea7be9f43c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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),
        }
    }
}