atomecs_derive/
lib.rs

1extern crate proc_macro;
2extern crate quote;
3extern crate syn;
4
5use proc_macro::TokenStream;
6use quote::quote;
7
8/// Auto-generated implementation for Lerp trait.
9///
10/// Note that this macro assumes:
11///  * The struct implements Clone.
12///  * The struct only contains fields implementing Multiply and Add.
13#[proc_macro_derive(Lerp)]
14pub fn lerp_macro_derive(input: TokenStream) -> TokenStream {
15    let ast = syn::parse(input).unwrap();
16    impl_lerp_macro(&ast)
17}
18
19fn impl_lerp_macro(ast: &syn::DeriveInput) -> TokenStream {
20    use syn::Fields;
21
22    let name = &ast.ident;
23    let data: &syn::Data = &ast.data;
24    match data {
25        syn::Data::Struct(struct_data) => {
26            let mut field_assignment_tokens = quote!();
27            match &struct_data.fields {
28                Fields::Named(named) => {
29                    for field in named.named.iter() {
30                        let field_name = field.ident.as_ref();
31                        field_assignment_tokens.extend(
32                            quote!(output.#field_name = self.#field_name * (1.0 - amount) + amount * other.#field_name;)
33                            );
34                    }
35                }
36                _ => unimplemented!(),
37            }
38
39            let tokens = quote! {
40                impl Lerp<#name> for #name {
41                fn lerp(&self, other: &Self, amount: f64) -> Self {
42                    let mut output = self.clone();
43                    // assign field values for lerpable fields.
44                    #field_assignment_tokens
45                    return output;
46                    }
47                }
48            };
49            tokens.into()
50        }
51
52        _ => unimplemented!(),
53    }
54}