1#![crate_type = "proc-macro"]
2
3#[macro_use]
4extern crate proc_macro_hack;
5
6#[macro_use]
7extern crate quote;
8
9extern crate syn;
10extern crate proc_macro;
11
12use syn::Item;
13use syn::ItemKind::Trait;
14use quote::Tokens;
15use quote::ToTokens;
16
17proc_macro_item_impl! {
18 pub fn generate_auto_impl_impl(input: &str) -> String {
25 let item = syn::parse_item(input).unwrap();
26
27 let name = &item.ident;
28 match item.node {
29 Trait(_, _, _, _) => {},
30 _ => panic!("Cannot expand type {} since it's not a trait!", name)
31 }
32
33 let mut expanded = expand_trait(&item);
34 expanded.append(expand_impl(&item).as_str());
35
36 expanded.parse().unwrap()
38 }
39}
40
41fn expand_trait(ast: &Item) -> Tokens {
43 let mut tokens = Tokens::new();
44 ast.to_tokens(&mut tokens);
45 tokens
46}
47
48fn expand_impl(ast: &Item) -> Tokens {
51 let name = &ast.ident;
53
54 match ast.node {
55 Trait(_, ref generics, _, _) => {
56 let (impl_generics, _, where_clause) = generics.split_for_impl();
57
58 if generics.ty_params.is_empty() {
59 panic!("Cannot auto-implement {} since it does not have any type parameters!",
60 name)
61 }
62
63 quote! {
64 impl #impl_generics #name #impl_generics for T #where_clause {}
65 }
66 }
67 _ => {
68 panic!("Cannot expand type {} implementation since it's not a trait!",
69 name)
70 }
71 }
72}