1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; use syn; #[proc_macro_derive(DynamoMapper)] pub fn dynamo_mapper_macro_derive(input: TokenStream) -> TokenStream { let ast: syn::DeriveInput = syn::parse(input).unwrap(); return implem_dynamo_mapper_macro(&ast); } fn implem_dynamo_mapper_macro(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; if let syn::Data::Struct(data) = &ast.data { let mut to_dynamo_lines = Vec::new(); let mut from_dynamo_lines = Vec::new(); for field in data.fields.iter() { if let Some(field_name) = &field.ident { let to_line = quote! { if let Some(value) = self.#field_name.to_dynamo() { item.insert(String::from(stringify!(#field_name)), value); } }; to_dynamo_lines.push(to_line); if let syn::Type::Path(type_path) = &field.ty { from_dynamo_lines.push(quote! { if let Some(field_value) = <#type_path>::from_dynamo(&item, String::from(stringify!(#field_name))) { result.#field_name = field_value; } }); } else { panic!("Unknown type"); }; } } let gen = quote! { impl DynamoMapper for #name { fn to_dynamo(&self) -> DynamoItem { let mut item = DynamoItem::new(); #(#to_dynamo_lines)* return item; } fn from_dynamo(item: &DynamoItem) -> #name { let mut result = #name {..Default::default()}; #(#from_dynamo_lines)* return result; } } }; gen.into() } else { panic!("Should only be used on struct"); } }