extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
use syn::Meta::{List};
use proc_macro::TokenStream;
fn impl_viadmacro(ast: &syn::DeriveInput) -> quote::Tokens {
let name = ast.ident;
let mut qname: syn::Ident = syn::Ident::from("nothing");
let mut tname: syn::Ident = syn::Ident::from("temp");
for attr in ast.attrs.iter() {
if let Some(List(list)) = attr.interpret_meta() {
for tpl in list.nested.iter(){
match tpl {
&syn::NestedMeta::Meta(syn::Meta::Word(ins)) => {tname = ins;},
_ => ()
};
}
}
let &syn::Path{ref segments, ..} = &attr.path;
{
for tpl in segments.iter(){
let &syn::PathSegment{ref ident, ..} = tpl;
if ident.to_string() == "via"{
qname = tname.to_owned();
}
}
}
}
let impl_block = quote! {
impl ViaDeserialize for #name { };
};
let impl_block_2 = quote! {
impl<'de> serde::Deserialize<'de> for #name
{
fn deserialize<D>(deserializer: D) -> Result<#name, D::Error>
where
D: _serde::Deserializer<'de>
{
match #qname::deserialize(deserializer) {
Ok(x) => Ok(#name::from(x)),
Err(r) => Err(r),
}
}
};
};
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _WAHT: () = {
extern crate serde as _serde;
#impl_block_2
#impl_block
};
}
}
fn impl_viasmacro(ast: &syn::DeriveInput) -> quote::Tokens {
let name = ast.ident;
let mut qname: syn::Ident = syn::Ident::from("nothing");
let mut tname: syn::Ident = syn::Ident::from("temp");
for attr in ast.attrs.iter() {
if let Some(List(list)) = attr.interpret_meta() {
for tpl in list.nested.iter(){
match tpl {
&syn::NestedMeta::Meta(syn::Meta::Word(ins)) => {tname = ins;},
_ => ()
};
}
}
let &syn::Path{ref segments, ..} = &attr.path;
{
for tpl in segments.iter(){
let &syn::PathSegment{ref ident, ..} = tpl;
if ident.to_string() == "via"{
qname = tname.to_owned();
}
}
}
}
let impl_block = quote! {
impl ViaSerialize for #name { };
};
let where_clause = quote!{
where #qname: _serde::Serialize,
#name: Into<#qname>,
#name: Clone
};
let impl_block_2 = quote! {
impl _serde::Serialize for #name
#where_clause
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: _serde::Serializer,
{
let n:#name = self.clone();
let dn:#qname = n.into();
dn.serialize(serializer)
}
}
};
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _SERIALISE: () = {
extern crate serde as _serde;
#impl_block_2
#impl_block
};
}
}
#[proc_macro_derive(ViaDeserialize, attributes(via))]
pub fn viad_macro(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
let gen = impl_viadmacro(&ast);
gen.into()
}
#[proc_macro_derive(ViaSerialize, attributes(via))]
pub fn vias_macro(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
let gen = impl_viasmacro(&ast);
gen.into()
}