Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.79 KB | None | 0 0
  1. extern crate proc_macro;
  2.  
  3. use proc_macro2::TokenStream;
  4. use syn::{parse_macro_input, DeriveInput, Ident, Data, Field};
  5. use quote::{quote, quote_spanned};
  6.  
  7. #[proc_macro_derive(Builder)]
  8. pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
  9. let input = parse_macro_input!(input as DeriveInput);
  10.  
  11. let typ = input.ident;
  12. let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
  13. let visibility = input.vis;
  14. let builder_typ = Ident::new(&format!("{}Builder", typ), typ.span());
  15. let builder_data = create_builder_data(&input.data);
  16.  
  17. let expanded = quote! {
  18. impl #impl_generics #typ #ty_generics #where_clause {
  19. pub fn builder() {}
  20. }
  21.  
  22. #visibility struct #builder_typ {
  23. #builder_data
  24. }
  25. };
  26.  
  27. proc_macro::TokenStream::from(expanded)
  28. }
  29.  
  30. fn create_builder_data(data: &Data) -> TokenStream {
  31. //Wrap each of the fields in an Option type
  32. let mut func = Box::new(|f: &Field| {
  33. let name = &f.ident;
  34. let typ = &f.ty;
  35. quote!{
  36. #name: Option<#typ>
  37. }
  38. });
  39.  
  40. map_on_fields(data, &func)
  41. }
  42.  
  43. fn map_on_fields(data: &Data, func: &Box<FnMut(Field) -> TokenStream>) -> TokenStream {
  44. use syn::Fields;
  45. match *data {
  46. Data::Struct(ref data) => {
  47. match data.fields {
  48. Fields::Named(ref fields) => {
  49. let recurse = fields.named.iter().map(*func);
  50. quote!{
  51. #(#recurse,)*
  52. }
  53. },
  54. _ => unimplemented!(),// only create builder if fields are named
  55. }
  56. },
  57. _ => unimplemented!(),// only create builder if it's a struct
  58. }
  59. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement