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()
37 .enumerate()
38 .map(|(i, field)| {
39 let field_ty = field.ty;
40
41 let offset = if let Some(field_ident) = &field.ident {
42 quote! {
43 #main_crate::private::offset_of!(Self, #field_ident)
44 }
45 } else {
46 let i = syn::Index::from(i);
47 quote! {
48 #main_crate::private::offset_of!(Self, #i)
49 }
50 };
51
52 quote! {
53 #main_crate::private::ComponentInfo {
54 type_id: ::std::any::TypeId::of::<#field_ty>(),
55 range: {
56 let offset = #offset;
57 let size = ::std::mem::size_of::<#field_ty>();
58 offset..(offset + size)
59 },
60 },
61 }
62 })
63 .collect();
64
65 let fields_len = field_impls.len();
66
67 {
69 let mut field_names: Vec<_> = types.iter().map(|v| v.to_string()).collect();
70 field_names.sort();
71 let initial_len = field_names.len();
72
73 field_names.dedup();
74 let deduped_len = field_names.len();
75
76 if initial_len != deduped_len {
77 panic!("Archetype contains multiple components of the same type.");
78 }
79 }
80
81 let mut field_types = TokenStream::new();
82 field_types.extend(types.into_iter());
83
84 let mut fields = TokenStream::new();
85 fields.extend(field_impls.into_iter());
86
87 quote! {
88 impl #generics #main_crate::StaticArchetype for #ident #generics #where_clause {
89 const N_COMPONENTS: usize = #fields_len;
90
91 fn metadata() -> #main_crate::private::ArchetypeMetadata {
92 #main_crate::private::ArchetypeMetadata {
93 type_id: ::std::any::TypeId::of::<Self>(),
94 component_type_ids: || #main_crate::private::smallvec![#field_types],
95 component_infos: || #main_crate::private::smallvec![#fields],
96 size: ::std::mem::size_of::<Self>(),
97 needs_drop: ::std::mem::needs_drop::<Self>(),
98 drop_fn: |p: *mut u8| unsafe { ::std::ptr::drop_in_place(p as *mut Self) },
99 }
100 }
101 }
102
103 impl #generics #main_crate::ArchetypeState for #ident #generics #where_clause {
104 fn ty(&self) -> ::std::any::TypeId {
105 ::std::any::TypeId::of::<Self>()
106 }
107
108 fn as_ptr(&self) -> *const u8 {
109 self as *const _ as *const u8
110 }
111
112 fn forget(self) {
113 ::std::mem::forget(self);
114 }
115
116 fn metadata(&self) -> #main_crate::private::ArchetypeMetadata {
117 <Self as #main_crate::StaticArchetype>::metadata()
118 }
119
120 fn num_components(&self) -> usize {
121 #fields_len
122 }
123
124 fn as_any(&self) -> &dyn ::std::any::Any {
125 self
126 }
127
128 fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
129 self
130 }
131 }
132 }
133 .into()
134}