delfi_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3
4#[proc_macro_derive(Datapoint)]
5pub fn derive_datapoint(input: TokenStream) -> TokenStream {
6    let ast = syn::parse_macro_input!(input as syn::DeriveInput);
7    // println!("{:#?}", ast);
8    let name = &ast.ident;
9
10    let expanded = match &ast.data {
11        syn::Data::Struct(s) => {
12            match &s.fields {
13                syn::Fields::Named(fields) => {
14                    let list = &fields.named;
15                    let cols: usize = list.len();
16                    let names: Vec<_> = list.iter().map(|e| e.ident.clone().unwrap()).collect();
17
18                    quote! {
19                        impl delfi::Datapoint<#cols> for #name {
20                            fn record(&self) -> [String; #cols] {
21                                [#(self.#names.to_string()),*]
22                            }
23                        }
24                    }
25                }
26                syn::Fields::Unnamed(fields) => {
27                    let list = &fields.unnamed;
28                    let cols: usize = list.len();
29                    let numbers: Vec<_> = list.iter().enumerate().map(|(i, _)| syn::Index::from(i)).collect();
30
31                    quote! {
32                        impl delfi::Datapoint<#cols> for #name {
33                            fn record(&self) -> [String; #cols] {
34                                [#(self.#numbers.to_string()),*]
35                            }
36                        }
37                    }
38                }
39
40                syn::Fields::Unit => panic!("Cannot derive Datapoint for unit struct"),
41            }
42        }
43        _ => unimplemented!(),
44    };
45
46    TokenStream::from(expanded)
47}