mydb_macros/derives/
utils.rs

1use proc_macro2::{TokenTree, Ident, Span, TokenStream};
2use syn::{
3  Attribute, Data, Fields, Field, GenericArgument, Meta, PathArguments, Type, TypePath
4};
5use quote::quote;
6
7use crate::derives::entity::{ TableField, MyField };
8
9pub fn get_table_list(data: Data) -> Vec<TableField> {
10  let mut table_list: Vec<TableField> = vec![];
11  match data {
12    Data::Struct(data_struct) => {
13      match data_struct.fields {
14        Fields::Named(fields) => {
15          for field in fields.named {
16            let name = get_field_name(&field);
17            let mut field_type = TokenStream::new();
18            let mut field_span = "".to_string();
19            let mut my_field: MyField = MyField::new();
20            let mut exist = true;
21
22            field.attrs.iter()
23            .filter(| attr | attr.path().is_ident("table_field"))
24            .for_each(|attr| {
25
26              if let Meta::List(lits) = &attr.meta {
27                let mut table_field_content = format!("");
28                let _ = &lits.tokens.clone().into_iter().for_each(| ts | {
29                  table_field_content += &ts.span().source_text().unwrap_or(format!(""));
30                });
31                table_field_content = table_field_content.replace(" ", "");
32                let exist_vec: &Vec<&str> = &table_field_content.split(',').collect();
33                if exist_vec.contains(&"exist=false") {
34                  exist = false;
35                }
36              }
37            });
38
39            if let Type::Path(_ty) = &field.ty {
40              my_field = recursive_print_ident(_ty);
41              field_type = my_field_ts(my_field.clone());
42              field_span = my_field_span(my_field.clone());
43            }
44            table_list.push( TableField {
45              name,
46              field_type,
47              exist,
48              my_field,
49              field_span,
50            })
51          }
52        },
53        _ => ()
54      }
55    },
56    _ => ()
57  }
58  table_list
59}
60
61pub fn get_field_name(field: &Field) -> String {
62  if let Some(ident) = &field.ident {
63    if let Some(text) = ident.span().source_text() {
64      return text;
65    }
66  }
67  format!("")
68}
69
70pub fn get_table_name(attrs: Vec<Attribute>) -> String {
71  let mut table_name = format!("");
72  attrs
73  .iter()
74  .filter(|attr| attr.path().is_ident("mydb"))
75  .into_iter()
76  .for_each(| attr | {
77    if let Meta::List(lits) = &attr.meta {
78      let _ = &lits.tokens.clone().into_iter().for_each(| ts | {
79        if let TokenTree::Literal(l_name) = ts {
80          if l_name.to_string().len() > 0 {
81            table_name = l_name.to_string().replace('"', "");
82          } else {
83            eprintln!("no setting table_name")
84          }
85        }
86      });
87    }
88  });
89  table_name
90}
91
92pub fn set_ident(name: &String) -> Ident {
93  Ident::new(&name, Span::call_site())
94}
95
96pub fn recursive_print_ident(type_path: &TypePath) -> MyField {
97  let mut my_field: MyField = MyField::new();
98  for segment in &type_path.path.segments {
99    my_field.field_type = Some(segment.ident.clone());
100    match &segment.arguments {
101        PathArguments::AngleBracketed(args) => {
102          my_field.lt = Some("<".to_string());
103            for arg in &args.args {
104                if let GenericArgument::Type(ty) = arg {
105                    if let Type::Path(inner_path) = ty {
106                      my_field.children = Some(Box::new(recursive_print_ident(inner_path)));
107                    }
108                }
109            }
110            my_field.gt = Some(">".to_string());
111        }
112        _ => {}
113    }
114  }
115  my_field
116}
117
118pub fn my_field_ts(my_field: MyField) -> TokenStream {
119  let mut ts: Vec<TokenStream> = Vec::new();
120
121  match my_field.field_type {
122    Some(_field_type) => ts.push(quote!(#_field_type)),
123    None => (),
124  };
125
126  match my_field.lt {
127    Some(_) => ts.push(quote!(<)),
128    None => (),
129  };
130
131  match my_field.children {
132    Some(children) => {
133      let text = my_field_ts(*children);
134      ts.push(text)
135    },
136    None => (),
137  };
138
139  match my_field.gt {
140    Some(_)  => ts.push(quote!(>)),
141    None => (),
142  };
143
144  quote!{ #(#ts)* }
145}
146
147
148pub fn my_field_span(my_field: MyField) -> String {
149  let mut s = "".to_string();
150
151  match my_field.field_type {
152    Some(field_type) => s += &field_type.to_string(),
153    None => (),
154  };
155
156  match my_field.lt {
157    Some(_) => s += "<",
158    None => (),
159  };
160
161  match my_field.children {
162    Some(children) => {
163      s += &my_field_span(*children);
164    },
165    None => (),
166  };
167
168
169  match my_field.gt {
170    Some(_)  => s += ">",
171    None => (),
172  };
173
174  s
175}