1mod token;
2
3use proc_macro::TokenStream;
4use syn::{parse_macro_input, DeriveInput};
5use quote::quote;
6use token::{extract_unfield, set_methods_unnamed, get_methods_unnamed, enum_variants, from_trait, get_methods_mut, incdec_methods, incdec_methods_unnamed};
7use crate::token::{new_args, tup_args, set_val, set_methods, get_methods, info, root_extract, get_vis_pub, unamed_field, is_enum_field_unit};
8
9#[proc_macro_derive(BasicMethod, attributes(only,exclude))]
10pub fn basic_method_derive(input: TokenStream) -> TokenStream {
11 let dinput = parse_macro_input!(input as DeriveInput);
12 let (attrs, _vis, ident, data) = root_extract(dinput);
13
14 let vispub = get_vis_pub();
15
16 match data {
17 syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Named(fname), .. }) => {
18 let syn::FieldsNamed{ named, .. } = fname;
19
20 let new_args = new_args(&named);
21 let tuple_args = tup_args(&named);
22 let new_setval = set_val(&named);
23
24 let set_methods = set_methods(&named, vispub.clone());
25 let get_methods = get_methods(&named, vispub.clone());
26 let get_methods_mut = get_methods_mut(&named, vispub.clone());
27 let incdec_methods = incdec_methods(&named, vispub.clone());
28 let info = info(&attrs, vispub.clone());
29
30 return quote!{
31 impl #ident {
32 #vispub fn new(#(#new_args),*) -> Self {
33 Self { #(#new_setval),* }
34 }
35 #info
36 #vispub fn fields() -> ::std::vec::Vec<(&'static str, &'static str)> {
37 let mut v = vec![];
38 #(v.push(#tuple_args));*;
39 v
40 }
41 #(#set_methods)*
42 #(#get_methods)*
43 #(#get_methods_mut)*
44 #(#incdec_methods)*
45 }
46 }.into()
47 }
48 syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Unit, .. }) => {
49 let info = info(&attrs, vispub.clone());
50
51 return quote!{
52 impl #ident {
53 #info
54 }
55 }.into()
56 }
57 syn::Data::Struct(syn::DataStruct { fields: syn::Fields::Unnamed(unfield), .. }) => {
58 let punc = extract_unfield(unfield);
59 let fields = unamed_field(&punc, vispub.clone());
60 let set_methods = set_methods_unnamed(&punc, vispub.clone());
61 let get_methods = get_methods_unnamed(&punc, vispub.clone());
62 let get_methods_mut = get_methods_mut(&punc, vispub.clone());
63 let incdec_methods = incdec_methods_unnamed(&punc, vispub.clone());
64 let info = info(&attrs, vispub.clone());
65
66 return quote!{
67 impl #ident {
68 #info
69 #vispub fn fields() -> ::std::vec::Vec<(&'static str)> {
70 let mut v = vec![];
71 #(v.push(#fields));*;
72 v
73 }
74 #(#set_methods)*
75 #(#get_methods)*
76 #(#get_methods_mut)*
77 #(#incdec_methods)*
78 }
79 }.into()
80 }
81 syn::Data::Enum(dataenum) => {
82 let variants = enum_variants(&dataenum.variants);
83 let from_trait = from_trait(&dataenum.variants);
84 let is_unit = is_enum_field_unit(&dataenum.variants);
85 if is_unit {
86 return quote!{
87 impl #ident {
88 #vispub fn variants() -> ::std::collections::HashSet<&'static str> {
90 let mut v = ::std::collections::HashSet::new();
91 #(v.insert(#variants));*;
92 v
93 }
94 }
95 impl ::std::convert::From<&str> for #ident {
96 fn from(value: &str) -> Self {
97 match value {
98 #(#from_trait),*,
99 _ => panic!("Can not create '{}' from '{}'", stringify!(#ident), value)
100 }
101 }
102 }
103 }.into();
104 } else {
105 return quote!{
106 impl #ident {
107 #vispub fn variants() -> ::std::vec::Vec<&'static str> {
108 let mut v = vec![];
109 #(v.push(#variants));*;
110 v
111 }
112 }
113 }.into()
114 }
115 },
116 syn::Data::Union(_) => panic!("Union is not supported. Only struct allowed!"),
117 }
118}
119