1extern crate proc_macro;
8extern crate syn;
9#[macro_use]
10extern crate quote;
11
12use syn::Meta::{List};
13
14use proc_macro::TokenStream;
15
16
17
18fn impl_viadmacro(ast: &syn::DeriveInput) -> quote::Tokens {
19 let name = ast.ident;
20
21 let mut qname: syn::Ident = syn::Ident::from("nothing");
22 let mut tname: syn::Ident = syn::Ident::from("temp");
23
24 for attr in ast.attrs.iter() {
25 if let Some(List(list)) = attr.interpret_meta() {
26 for tpl in list.nested.iter(){
27 match tpl {
28 &syn::NestedMeta::Meta(syn::Meta::Word(ins)) => {tname = ins;},
29 _ => ()
30 };
31 }
32 }
33
34
35 let &syn::Path{ref segments, ..} = &attr.path;
36 {
37 for tpl in segments.iter(){
38 let &syn::PathSegment{ref ident, ..} = tpl;
39 if ident.to_string() == "via"{
40 qname = tname.to_owned();
41 }
42 }
43 }
44
45
46
47 }
48
49 let impl_block = quote! {
50 impl ViaDeserialize for #name { };
51 };
52
53
54 let impl_block_2 = quote! {
55 impl<'de> serde::Deserialize<'de> for #name
56 {
60 fn deserialize<D>(deserializer: D) -> Result<#name, D::Error>
61 where
62 D: _serde::Deserializer<'de>
63 {
64 match #qname::deserialize(deserializer) {
65 Ok(x) => Ok(#name::from(x)),
66 Err(r) => Err(r),
67 }
68 }
69 };
70
71 };
72
73
74 quote! {
75 #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
76 const _WAHT: () = {
77 extern crate serde as _serde;
78 #impl_block_2
79 #impl_block
80 };
81 }
82
83}
84
85
86fn impl_viasmacro(ast: &syn::DeriveInput) -> quote::Tokens {
87 let name = ast.ident;
88
89 let mut qname: syn::Ident = syn::Ident::from("nothing");
90 let mut tname: syn::Ident = syn::Ident::from("temp");
91
92 for attr in ast.attrs.iter() {
93 if let Some(List(list)) = attr.interpret_meta() {
94 for tpl in list.nested.iter(){
95 match tpl {
96 &syn::NestedMeta::Meta(syn::Meta::Word(ins)) => {tname = ins;},
97 _ => ()
98 };
99 }
100 }
101
102
103 let &syn::Path{ref segments, ..} = &attr.path;
104 {
105 for tpl in segments.iter(){
106 let &syn::PathSegment{ref ident, ..} = tpl;
107 if ident.to_string() == "via"{
108 qname = tname.to_owned();
109 }
110 }
111 }
112
113
114
115 }
116
117 let impl_block = quote! {
118 impl ViaSerialize for #name { };
119 };
120
121
122 let where_clause = quote!{
123 where #qname: _serde::Serialize,
124 #name: Into<#qname>,
125 #name: Clone
126 };
127
128
129 let impl_block_2 = quote! {
133
134 impl _serde::Serialize for #name
135 #where_clause
136 {
137 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
138 where
139 S: _serde::Serializer,
140 {
141 let n:#name = self.clone();
142 let dn:#qname = n.into();
143 dn.serialize(serializer)
144 }
145 }
146
147
148
149 };
150
151
152 quote! {
153 #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
154 const _SERIALISE: () = {
155 extern crate serde as _serde;
156 #impl_block_2
157 #impl_block
158 };
159 }
160
161}
162
163#[proc_macro_derive(ViaDeserialize, attributes(via))]
167pub fn viad_macro(input: TokenStream) -> TokenStream {
168 let ast = syn::parse(input).unwrap();
169 let gen = impl_viadmacro(&ast);
170 gen.into()
171}
172
173
174#[proc_macro_derive(ViaSerialize, attributes(via))]
178pub fn vias_macro(input: TokenStream) -> TokenStream {
179 let ast = syn::parse(input).unwrap();
180 let gen = impl_viasmacro(&ast);
181 gen.into()
182}