1#![recursion_limit = "1024"]
2extern crate rlua;
3extern crate syn;
4#[macro_use] extern crate quote;
5
6extern crate proc_macro;
7
8use proc_macro::{TokenStream};
9use syn::{VariantData,Ident};
10
11trait FromLuaTable {
12 fn from_table(table: &rlua::Table) -> Self;
13}
14
15#[proc_macro_derive(FromLuaTable)]
16pub fn from_lua_table(input: TokenStream) -> TokenStream {
17 let source = input.to_string();
18 let ast = syn::parse_macro_input(&source).unwrap();
19
20 let idents: Vec<Ident> = match ast.body {
21 syn::Body::Struct(vdata) => {
22 match vdata {
23 VariantData::Struct(fields) => {
24 let mut idents = Vec::new();
25 for ref field in fields.iter() {
26 match &field.ident {
27 &Some(ref ident) => {
28 idents.push(ident.clone());
29 },
30 &None => panic!("The structure is missing a field identity"),
31 }
32 }
33 idents
34 },
35 VariantData::Tuple(_) | VariantData::Unit => {
36 panic!("This can only be derived for structs");
37 },
38 }
39 },
40 syn::Body::Enum(_) => panic!("This is only defined for structs"),
41 };
42
43 let mut keys = Vec::new();
46 for ident in idents.iter() {
47 keys.push(String::from(ident.as_ref()));
48 }
49
50
51 let name = &ast.ident;
52 #[allow(unused)]
53 let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
54
55 let tokens = quote! {
56 impl #impl_generics FromLuaTable for #name #ty_generics #where_clause {
57 #[allow(unused)]
58 fn from_lua_table(table: &rlua::Table) -> Self {
59 #[allow(unused_mut)]
60 let mut ret = #name::default();
61
62 #(
63 if let Ok(val) = table.get(#keys) {
64 ret.#idents = val;
65 }
66 )*
67 ret
68 }
69 }
70 };
71 tokens.parse().unwrap()
72}
73
74#[cfg(test)]
75mod tests {
76 }
83
84