entity_data_macros/
lib.rs1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput};
4
5#[proc_macro_derive(Archetype)]
7pub fn derive_archetype_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
8 let main_crate = quote!(::entity_data);
9
10 let DeriveInput {
11 ident,
12 data,
13 generics,
14 ..
15 } = parse_macro_input!(input as DeriveInput);
16
17 let where_clause = &generics.where_clause;
18
19 let fields = if let syn::Data::Struct(data) = data {
20 data.fields
21 } else {
22 panic!("Not a structure!");
23 };
24
25 let types: Vec<_> = fields
26 .iter()
27 .map(|field| {
28 let field_ty = &field.ty;
29 quote! {
30 ::std::any::TypeId::of::<#field_ty>(),
31 }
32 })
33 .collect();
34
35 let field_impls: Vec<_> = fields
36 .into_iter().enumerate()
37 .map(|(i, field)| {
38 let field_ty = field.ty;
39
40 let offset = if let Some(field_ident) = &field.ident {
41 quote! {
42 #main_crate::private::offset_of!(Self, #field_ident)
43 }
44 } else {
45 let i = syn::Index::from(i);
46 quote! {
47 #main_crate::private::offset_of!(Self, #i)
48 }
49 };
50
51 quote! {
52 #main_crate::private::ComponentInfo {
53 type_id: ::std::any::TypeId::of::<#field_ty>(),
54 range: {
55 let offset = #offset;
56 let size = ::std::mem::size_of::<#field_ty>();
57 offset..(offset + size)
58 },
59 },
60 }
61 })
62 .collect();
63
64 let fields_len = field_impls.len();
65
66 {
68 let mut field_names: Vec<_> = types.iter().map(|v| v.to_string()).collect();
69 field_names.sort();
70 let initial_len = field_names.len();
71
72 field_names.dedup();
73 let deduped_len = field_names.len();
74
75 if initial_len != deduped_len {
76 panic!("Archetype contains multiple components of the same type.");
77 }
78 }
79
80 let mut field_types = TokenStream::new();
81 field_types.extend(types.into_iter());
82
83 let mut fields = TokenStream::new();
84 fields.extend(field_impls.into_iter());
85
86 quote! {
87 impl #generics #main_crate::StaticArchetype for #ident #generics #where_clause {
88 const N_COMPONENTS: usize = #fields_len;
89
90 fn metadata() -> #main_crate::private::ArchetypeMetadata {
91 #main_crate::private::ArchetypeMetadata {
92 type_id: ::std::any::TypeId::of::<Self>(),
93 component_type_ids: || #main_crate::private::smallvec![#field_types],
94 component_infos: || #main_crate::private::smallvec![#fields],
95 size: ::std::mem::size_of::<Self>(),
96 needs_drop: ::std::mem::needs_drop::<Self>(),
97 drop_fn: |p: *mut u8| unsafe { ::std::ptr::drop_in_place(p as *mut Self) },
98 }
99 }
100 }
101
102 impl #generics #main_crate::ArchetypeState for #ident #generics #where_clause {
103 fn ty(&self) -> ::std::any::TypeId {
104 ::std::any::TypeId::of::<Self>()
105 }
106
107 fn as_ptr(&self) -> *const u8 {
108 self as *const _ as *const u8
109 }
110
111 fn forget(self) {
112 ::std::mem::forget(self);
113 }
114
115 fn metadata(&self) -> #main_crate::private::ArchetypeMetadata {
116 <Self as #main_crate::StaticArchetype>::metadata()
117 }
118
119 fn num_components(&self) -> usize {
120 #fields_len
121 }
122
123 fn as_any(&self) -> &dyn ::std::any::Any {
124 self
125 }
126
127 fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
128 self
129 }
130 }
131 }
132 .into()
133}