dessert_derive/
lib.rs

1//! # Dessert-Derive
2//! 
3//! Provide derive macros for the `desert` crate, which provide a simpler interface to implement
4//! custom SerDe `Serialize` and `Deserialize` traits.
5//!
6
7extern 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            //where
57            //    #qname: Into<#name>,
58            //    #qname: _serde::Deserialize<'de>,
59            {
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    // quote does not seem to like where clauses for whaever reason.
130    //println!("WHERE CLAUSE {:?} ", where_clause);
131
132    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/// This function is responsible for taking a TokenStream 
164/// and generate the appropriate code to derive `ViaDeserialize`.
165/// use the `#[derive(ViaDeserialize)]`
166#[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/// This function is responsible for taking a TokenStream 
175/// and generate the appropriate code to derive `ViaSerialize`.
176/// use the `#[derive(ViaSerialize)]`
177#[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}