1use proc_macro::TokenStream;
2use quote::{quote, ToTokens};
3use syn::{parse_quote, TypePath};
4
5#[proc_macro_derive(Dependencies)]
42pub fn derive_dependencies(input: TokenStream) -> TokenStream {
43 let derive_input: syn::DeriveInput = syn::parse(input).unwrap();
44 let stru = match &derive_input.data {
45 syn::Data::Struct(s) => s,
46 _ => panic!("Only derive Dependencies on structs"),
47 };
48 let stru_ident = derive_input.ident;
49 let mut field_type_paths: Vec<&TypePath> = vec![];
53
54 for e in stru.fields.iter() {
55 let path = match &e.ty {
56 syn::Type::Path(path) => path,
57 _ => panic!(
58 "field {:?} is not a Handle! ",
59 e.to_token_stream().to_string()
60 ),
61 };
62 field_type_paths.push(path);
63 }
64
65 let extend_ids = field_type_paths
66 .iter()
67 .map(|path| quote!(ids.extend(<#path as Dependencies>::type_ids());))
68 .collect::<Vec<proc_macro2::TokenStream>>();
69
70 let declare_element_ranges = field_type_paths
71 .iter()
72 .enumerate()
73 .map(|(i, path)| {
74 let range_i: syn::Ident = syn::parse_str(&format!("range_{i}")).unwrap();
75
76 let declare_offset_if_first = if i == 0 {
77 Some(quote!(let mut offset: usize = 0;))
78 } else {
79 None
80 };
81 quote!(
82 #declare_offset_if_first
83
84 let ids = <#path as Dependencies>::type_ids();
85 let #range_i = offset..(offset + ids.len());
86 offset += ids.len();
87
88 )
89 })
90 .collect::<Vec<proc_macro2::TokenStream>>();
91
92 let self_construction_from_ranges = match &stru.fields {
93 syn::Fields::Unit => quote!(Self),
94 syn::Fields::Named(named_fields) => {
95 assert_eq!(field_type_paths.len(), named_fields.named.len());
96 let set_fields = named_fields
97 .named
98 .iter()
99 .zip(field_type_paths.iter())
100 .enumerate()
101 .map(|(i, (field, path))| {
102 let range_i: syn::Ident = syn::parse_str(&format!("range_{i}")).unwrap();
103 let field_ident = field.ident.as_ref().unwrap();
104 quote!(#field_ident: <#path as Dependencies>::from_untyped_handles(&ptrs[#range_i]))
105 });
106
107 quote!(
108 Self {
109 #( #set_fields ),*
110 }
111 )
112 }
113 syn::Fields::Unnamed(unnamed_fields) => {
114 assert_eq!(field_type_paths.len(), unnamed_fields.unnamed.len());
115
116 let set_fields = field_type_paths.iter().enumerate().map(|(i, path)| {
117 let range_i: syn::Ident = syn::parse_str(&format!("range_{i}")).unwrap();
118 quote!(<#path as Dependencies>::from_untyped_handles(&ptrs[#range_i]))
119 });
120
121 quote!(
122 Self (
123 #( #set_fields ),*
124 )
125 )
126 }
127 };
128
129 let trait_impl: proc_macro2::TokenStream = quote!(
130 impl Dependencies for #stru_ident {
131 fn type_ids() -> Vec<crate::app::ModuleId> {
132 let mut ids = vec![];
133 #( #extend_ids )*
134 ids
135 }
136
137 fn from_untyped_handles(ptrs: &[crate::app::UntypedHandle]) -> Self {
138 #( #declare_element_ranges)*
139
140 #self_construction_from_ranges
141 }
142 }
143 );
144
145 trait_impl.into()
146}
147
148#[proc_macro_derive(Lerp)]
174pub fn derive_lerp(input: TokenStream) -> TokenStream {
175 let derive_input: syn::DeriveInput = syn::parse(input).unwrap();
176 let stru = match &derive_input.data {
177 syn::Data::Struct(s) => s,
178 _ => panic!("Only derive Dependencies on structs"),
179 };
180 let stru_ident = derive_input.ident;
181 let lerp_impl_body = match &stru.fields {
185 syn::Fields::Named(_) => {
186 let field_iter = stru.fields.iter().map(|field| {
187 let ident = field.ident.as_ref().unwrap();
188 quote!(#ident : self.#ident.lerp(&other.#ident, factor))
189 });
190 quote!(#stru_ident{#(#field_iter),*})
191 }
192 syn::Fields::Unnamed(_) => {
193 let field_iter = stru
194 .fields
195 .iter()
196 .enumerate()
197 .map(|(i, _)| quote!(self.#i.lerp(&other.#i, factor)));
198 quote!(#stru_ident(#(#field_iter),*))
199 }
200 syn::Fields::Unit => {
201 quote!(#stru_ident)
202 }
203 };
204
205 quote!(
206 impl Lerp for #stru_ident {
207 fn lerp(&self, other: &Self, factor: f32) -> Self {
208 #lerp_impl_body
209 }
210 }
211 )
212 .into()
213}