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 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}