struct_to_json_db_macro/
lib.rs

1extern crate proc_macro;
2use std::vec;
3use proc_macro::TokenStream;
4use quote::quote;
5use regex::Regex;
6use syn::{parse_macro_input, DeriveInput, Fields};
7use proc_macro2::{Ident, Span};
8#[proc_macro_attribute]
9pub fn auto_json_db(_attr: TokenStream, item: TokenStream) -> TokenStream {
10    let input = parse_macro_input!(item as DeriveInput);
11    
12    let name = &input.ident;
13    let name_behalf = Ident::new(&format!("{}_behalf", name), Span::call_site());
14     
15    let fields = match &input.data {
16        syn::Data::Struct(syn::DataStruct { fields: Fields::Named(fields), .. }) => fields,
17        _ => panic!("auto_id macro can only be used on structs with named fields"),
18    };
19    let field_names: Vec<_> = fields.named.iter().map(|f| &f.ident).collect();
20    let field_types: Vec<_> = fields.named.iter().map(|f| &f.ty).collect();
21     
22    let binding = _attr.to_string();
23    let attribute_hm = parse_string_to_hashmap(&binding);
24    let encript_name = attribute_hm.get("encript").unwrap_or(&"".to_owned()).to_owned();
25 
26    let mut unique_field_len = 0;
27    let mut unique_field: Vec<_> = vec![];
28    let mut unique_field_types: Vec<_> = vec![];
29    if let Some(unique_field_string) = attribute_hm.get("unique"){
30        unique_field = unique_field_string.split("|").map(|s| {
31            if !s.trim().is_empty() {
32                Some(Ident::new(s.trim(), Span::call_site()))
33            }else{
34                None
35            }        
36        }  ).collect();
37        unique_field_len = unique_field.len();
38        unique_field.iter().for_each(|f| {
39            if let Some(field_name) = f {
40                if let Some(index) = field_names.iter().position(|&r| r.clone().unwrap().to_string() == field_name.to_string() ) {
41                    unique_field_types.push(field_types[index].clone());
42                }
43            }
44        });
45    }
46   
47    let mut is_complex = false;
48    if attribute_hm.get("bigsize").is_some(){
49        is_complex = true;
50    }
51    let mut is_singleton = false;
52    if attribute_hm.get("singleton").is_some(){
53        is_singleton = true;
54    }
55    let singleton_struct_expand: proc_macro2::TokenStream = quote! {
56        #[derive(Serialize,Deserialize,Clone,Debug)]
57        pub struct #name {
58            pub last_modify:u64,
59            #(
60                pub #field_names: #field_types,
61            )*
62        }
63        impl #name{
64            pub fn new(  #( #field_names: #field_types ),*) -> Self {
65                let now_idx = struct_to_json_db::unique_id(); 
66                Self {
67                    last_modify: now_idx.1,
68                    #( #field_names, )*
69                }
70            }
71            pub fn get_path()->String{
72                struct_to_json_db::get_struct_json_path()+stringify!(#name)+".json"
73            }
74          
75            pub fn save(&mut self){
76                let file_path = Self::get_path();
77                let now_idx = struct_to_json_db::unique_id(); 
78                self.last_modify = now_idx.1;
79                Self::set_data_string(&file_path, serde_json::to_string(self).unwrap());
80            }
81            pub fn load()->Self{
82                let file_path = Self::get_path();
83                let db_string = Self::get_data_string(&file_path);
84                if let Some(data) = serde_json::from_str(&db_string).ok() {
85                    return data;
86                }else{
87                    return Self::default();
88                }
89            }
90            pub fn set_data_string(file_path:&str,db_string:String){
91                if #encript_name != ""{
92                    match std::env::var(#encript_name) {
93                        Ok(encript) => {
94                            struct_to_json_db::write_string_to_txt_encript(file_path, db_string,&encript);
95                        }
96                        Err(e) => {
97                            struct_to_json_db::write_string_to_txt(file_path, db_string);
98                        }
99                    }
100                }else{
101                    struct_to_json_db::write_string_to_txt(file_path, db_string);
102                }
103            }
104            pub fn get_data_string(file_path:&str)->String{
105                if #encript_name != ""{
106                    match std::env::var(#encript_name) {
107                        Ok(encript) => {
108                            struct_to_json_db::read_string_from_txt_encript(&file_path,&encript)
109                        }
110                        Err(e) => {
111                            struct_to_json_db::read_string_from_txt(&file_path)
112                        }
113                    }
114                }else{
115                    struct_to_json_db::read_string_from_txt(&file_path)
116                }
117            }
118        }
119    };
120    let complex_struct_expand: proc_macro2::TokenStream = quote! {
121        #[derive(Serialize,Deserialize,Clone,Debug)]
122        pub struct #name_behalf{
123            pub idx: u64, 
124            #(
125                pub #unique_field: #unique_field_types,
126            )*
127        }
128        impl #name_behalf{
129            pub fn new( idx:u64, #( #unique_field: #unique_field_types ),*) -> Self {
130                //let now_idx = struct_to_json_db::unique_id();
131                Self {
132                    idx: idx,
133                    #( #unique_field,)*
134                }
135            }
136            pub fn idx(&self)->u64{
137                self.idx
138            }
139            pub fn get_path()->String{
140                struct_to_json_db::get_struct_json_path()+stringify!(#name)+".json"
141            }
142            pub fn get_unique_hash(&self) -> String {
143                if #unique_field_len > 0 {
144                    let mut ukey = String::new();
145                    #( ukey += &self.#unique_field.to_string(); )*
146                    struct_to_json_db::string_to_unique_id(&ukey)
147                } else {
148                    self.idx.to_string()
149                }
150            }
151            pub fn get_by_id(id: u64) -> Option<Self> {
152                let db = Self::get_all(); 
153                db.get(&id).cloned()
154            }
155            pub fn get_by_ids(ids: &Vec<u64>) -> Vec<Self> {
156                let db = Self::get_all(); 
157                ids.iter().filter_map(|id| db.get(&id).cloned()).collect()
158            }
159            pub fn remove_by_id(id: u64){
160                let file_path = Self::get_path();
161                let mut db = Self::get_all(); 
162                db.remove(&id);
163                let db_string = serde_json::to_string(&db).unwrap();
164                Self::set_data_string(&file_path, db_string);
165            }
166            pub fn remove_by_ids(ids: &Vec<u64>){
167                let file_path = Self::get_path();
168                let mut db = Self::get_all(); 
169                for id in ids{
170                    db.remove(&id);
171                }
172                let db_string = serde_json::to_string(&db).unwrap();
173                Self::set_data_string(&file_path, db_string);
174            }
175            pub fn get_all()->std::collections::HashMap<u64,Self>{
176                let file_path = Self::get_path();
177                let db_string = Self::get_data_string(&file_path);
178                let db:std::collections::HashMap<u64,Self> = serde_json::from_str(&db_string).unwrap_or_default();
179                db
180            }
181            pub fn load(&self)->Option< #name >{
182                #name ::get_by_id(self.idx) 
183            }
184            pub fn clear(){
185                let file_path = Self::get_path();
186                struct_to_json_db::write_string_to_txt(&file_path, "".to_owned());
187            }
188            pub fn save(&self){
189                let mut db = Self::get_all();
190                db.insert(self.idx, self.clone());
191                Self::save_all(&db);
192            }
193           
194            pub fn save_vec(v:Vec<Self>){
195                let file_path = Self::get_path();
196                let mut db = Self::get_all();
197                for i in v{
198                    db.insert(i.idx, i);
199                }
200                let db_string = serde_json::to_string(&db).unwrap();
201                Self::set_data_string(&file_path, db_string);
202            }
203            pub fn save_all(db:&std::collections::HashMap<u64,Self>){
204                let file_path = Self::get_path();
205                let db_string = serde_json::to_string(db).unwrap();
206                Self::set_data_string(&file_path, db_string);
207            }
208            pub fn remove(&self){
209                Self::remove_by_id(self.idx);
210            }
211            pub fn set_data_string(file_path:&str,db_string:String){
212                if #encript_name != ""{
213                    match std::env::var(#encript_name) {
214                        Ok(encript) => {
215                            struct_to_json_db::write_string_to_txt_encript(file_path, db_string,&encript);
216                        }
217                        Err(e) => {
218                            struct_to_json_db::write_string_to_txt(file_path, db_string);
219                        }
220                    }
221                }else{
222                    struct_to_json_db::write_string_to_txt(file_path, db_string);
223                }
224            }
225            pub fn get_data_string(file_path:&str)->String{
226                if #encript_name != ""{
227                    match std::env::var(#encript_name) {
228                        Ok(encript) => {
229                            struct_to_json_db::read_string_from_txt_encript(&file_path,&encript)
230                        }
231                        Err(e) => {
232                            struct_to_json_db::read_string_from_txt(&file_path)
233                        }
234                    }
235                }else{
236                    struct_to_json_db::read_string_from_txt(&file_path)
237                }
238            }
239        }
240        
241        #[derive(Serialize,Deserialize,Clone,Debug)]
242        pub struct #name {
243            pub idx: u64, 
244            pub created_at:u64,
245            #(
246                pub #field_names: #field_types,
247            )*
248        }
249        impl #name {
250            pub fn new(  #( #field_names: #field_types ),*) -> Self {
251                let now_idx = struct_to_json_db::unique_id(); 
252                Self {
253                    idx: now_idx.0^now_idx.1,
254                    created_at: now_idx.1,
255                    #( #field_names, )*
256                }
257            }
258            pub fn idx(&self)->u64{
259                self.idx
260            }
261            pub fn get_path()->String{
262                struct_to_json_db::get_struct_json_path()+stringify!(#name)
263            }
264            pub fn get_unique_hash(&self) -> String {
265                if #unique_field_len > 0 {
266                    let mut ukey = String::new();
267                    #( ukey += &self.#unique_field.to_string(); )*
268                    struct_to_json_db::string_to_unique_id(&ukey)
269                } else {
270                    self.idx.to_string()
271                }
272            }
273            pub fn get_by_id(id: u64) -> Option<Self> {
274                let file_path = format!("{}/{}.json",Self::get_path(),id.to_string());
275                let db_string = Self::get_data_string(&file_path);
276                serde_json::from_str(&db_string).ok()
277            }
278            pub fn get_by_ids(ids: &Vec<u64>) -> Vec<Self> {
279                ids.iter().filter_map(|id| Self::get_by_id(id.clone())).collect()
280            }
281            pub fn remove_by_id(id: u64){
282                let file_path = format!("{}/{}.json",Self::get_path(),id.to_string());
283                struct_to_json_db::remove_file_by_path(&file_path);
284                #name_behalf::remove_by_id(id);
285            }
286            pub fn remove_by_ids(ids: &Vec<u64>){
287                ids.iter().for_each(|id|{
288                    Self::remove_by_id(id.clone());
289                });
290            }
291            pub fn get_all()->std::collections::HashMap<u64,#name_behalf>{
292                let db = #name_behalf::get_all();
293                db
294            }
295        
296            pub fn clear(){
297                let file_path = Self::get_path()+".json";
298                struct_to_json_db::write_string_to_txt(&file_path, "".to_owned());
299                struct_to_json_db::remove_all_files_by_path(&Self::get_path());
300            }
301            pub fn update(&mut self){
302                let mut exist_item:Vec<u64> = vec![];
303                let db = #name_behalf::get_all();
304                if #unique_field_len > 0 {
305                    exist_item = db.values().filter(|item| {
306                        #( self. #unique_field == item. #unique_field && )* true 
307                    }).map(|item| item.idx).collect(); 
308                }
309                if exist_item.len() > 0{
310                    self.idx = exist_item[0];
311                    let file_path = format!("{}/{}.json",Self::get_path(),exist_item[0].to_string()); 
312                    Self::set_data_string(&file_path, serde_json::to_string(self).unwrap());
313                } 
314            }
315            pub fn save_or_update(&mut self){
316                let idx = self.save();
317                if idx.is_none(){
318                    self.update();
319                }
320            }
321            pub fn save(&self)->Option<u64>{
322                let item = Self::get_by_id(self.idx);
323                let bh = self.behalf();
324                let folder_path = Self::get_path();
325                struct_to_json_db::make_folder_if_not_exist(&folder_path);
326                
327                if item.is_none() {
328                    let mut exists = false;
329                    let mut db = #name_behalf::get_all();
330                    if #unique_field_len > 0 {
331                        exists = db.values().any(|item| {
332                            #( self. #unique_field == item. #unique_field && )* true 
333                        }); 
334                    }
335                    if exists{
336                        return None;
337                    }else{
338                        let file_path = format!("{}/{}.json",Self::get_path(),self.idx.to_string());  
339                        Self::set_data_string(&file_path, serde_json::to_string(self).unwrap());
340                        bh.save(); 
341                        return Some(self.idx);
342                    }
343                }else{ 
344                    let file_path = format!("{}/{}.json",Self::get_path(),self.idx.to_string());   
345                    Self::set_data_string(&file_path, serde_json::to_string(self).unwrap());
346                    bh.save();
347                    return Some(self.idx);
348                }
349            }
350            #(
351                pub fn #unique_field(value: &#unique_field_types)-> Option<Self>{
352                    let db = #name::get_all();
353                    let rel:Vec<Self> = db.values().filter(|item| &item. #unique_field == value).map(|item| Self::get_by_id(item.idx).unwrap()).collect();
354                    if rel.len()>0{
355                        return Some(rel[0].clone()); 
356                    }
357                    None
358                }
359            )*
360            pub fn behalf(&self)->#name_behalf{
361                #name_behalf::new(self.idx  #(, self. #unique_field .clone() )*)
362            }
363            pub fn save_vec(v:Vec<Self>){
364                v.into_iter().for_each(|item|{
365                    item.save();
366                });
367            }
368            pub fn save_all(db:&std::collections::HashMap<u64,Self>){
369                db.iter().for_each(|(idx, item)| {
370                    item.save();
371                });
372            }
373            pub fn remove(&self){
374                Self::remove_by_id(self.idx);
375            }
376            pub fn set_data_string(file_path:&str,db_string:String){
377                if #encript_name != ""{
378                    match std::env::var(#encript_name) {
379                        Ok(encript) => {
380                            struct_to_json_db::write_string_to_txt_encript(file_path, db_string,&encript);
381                        }
382                        Err(e) => {
383                            struct_to_json_db::write_string_to_txt(file_path, db_string);
384                        }
385                    }
386                }else{
387                    struct_to_json_db::write_string_to_txt(file_path, db_string);
388                }
389            }
390            pub fn get_data_string(file_path:&str)->String{
391                if #encript_name != ""{
392                    match std::env::var(#encript_name) {
393                        Ok(encript) => {
394                            struct_to_json_db::read_string_from_txt_encript(&file_path,&encript)
395                        }
396                        Err(e) => {
397                            struct_to_json_db::read_string_from_txt(&file_path)
398                        }
399                    }
400                }else{
401                    struct_to_json_db::read_string_from_txt(&file_path)
402                }
403            }
404        }
405       
406    };
407    
408    let default_struct_expand: proc_macro2::TokenStream = quote! {
409        #[derive(Serialize,Deserialize,Clone,Debug)]
410        pub struct #name {
411            pub idx: u64, 
412            pub created_at:u64,
413            #(
414                pub #field_names: #field_types,
415            )*
416        }
417        impl #name {
418            pub fn new(  #( #field_names: #field_types ),*) -> Self {
419                let now_idx = struct_to_json_db::unique_id(); 
420                Self {
421                    idx: now_idx.0^now_idx.1,
422                    created_at: now_idx.1,
423                    #( #field_names, )*
424                }
425            }
426            pub fn idx(&self)->u64{
427                self.idx
428            }
429            pub fn get_path()->String{
430                struct_to_json_db::get_struct_json_path()+stringify!(#name)+".json"
431            }
432            pub fn get_unique_hash(&self) -> String {
433                if #unique_field_len > 0 {
434                    let mut ukey = String::new();
435                    #( ukey += &self.#unique_field.to_string(); )*
436                    struct_to_json_db::string_to_unique_id(&ukey)
437                } else {
438                    self.idx.to_string()
439                }
440            }
441            pub fn get_by_id(id: u64) -> Option<Self> {
442                let db = Self::get_all(); 
443                db.get(&id).cloned()
444            }
445            pub fn get_by_ids(ids: &Vec<u64>) -> Vec<Self> {
446                let db = Self::get_all(); 
447                ids.iter().filter_map(|id| db.get(&id).cloned()).collect()
448            }
449            pub fn remove_by_id(id: u64){
450                let file_path = Self::get_path();
451                let mut db = Self::get_all(); 
452                db.remove(&id);
453                let db_string = serde_json::to_string(&db).unwrap();
454                Self::set_data_string(&file_path, db_string);
455            }
456            pub fn remove_by_ids(ids: &Vec<u64>){
457                let file_path = Self::get_path();
458                let mut db = Self::get_all(); 
459                for id in ids{
460                    db.remove(&id);
461                }
462                let db_string = serde_json::to_string(&db).unwrap();
463                Self::set_data_string(&file_path, db_string);
464            }
465            pub fn get_all()->std::collections::HashMap<u64,Self>{
466                let file_path = Self::get_path();
467                let db_string = Self::get_data_string(&file_path);
468                let db:std::collections::HashMap<u64,Self> = serde_json::from_str(&db_string).unwrap_or_default();
469                db
470            }
471            #(
472                pub fn #unique_field(value: &#unique_field_types)-> Option<Self>{
473                    let db = #name::get_all();
474                    let rel:Vec<Self> = db.values().filter(|item| &item. #unique_field == value).map(|item| Self::get_by_id(item.idx).unwrap()).collect();
475                    if rel.len()>0{
476                        return Some(rel[0].clone()); 
477                    }
478                    None
479                }
480            )*
481            pub fn clear(){
482                let file_path = Self::get_path();
483                struct_to_json_db::write_string_to_txt(&file_path, "".to_owned());
484            }
485            pub fn update(&mut self){
486                let mut exist_item:Vec<u64> = vec![];
487                let mut db = Self::get_all();
488                if #unique_field_len > 0 {
489                    exist_item = db.values().filter(|item| {
490                        #( self. #unique_field == item. #unique_field && )* true 
491                    }).map(|item| item.idx).collect(); 
492                }
493                if exist_item.len() > 0{
494                    self.idx = exist_item[0];
495                    db.insert(self.idx, self.clone());
496                    Self::save_all(&db);
497                } 
498            }
499            pub fn save_or_update(&mut self){
500                let idx = self.save();
501                if idx.is_none(){
502                    self.update();
503                }
504            }
505            pub fn save(&self)->Option<u64>{
506                let mut db = Self::get_all();
507                let idx = self.idx;
508                let item_idx:u64 = db.get(&idx).map(|item|item.idx).unwrap_or(0);
509                let mut exists = false;
510                if idx == item_idx{
511                    //update struct
512                    db.insert(self.idx, self.clone());
513                    Self::save_all(&db);
514                    Some(idx)
515                }else{
516                    //insert struct
517                    if #unique_field_len > 0 {
518                        exists = db.values().any(|item| {
519                            #( self. #unique_field == item. #unique_field && )* true 
520                        }); 
521                    }
522                    if exists{
523                        None
524                    }else{
525                        db.insert(self.idx, self.clone());
526                        Self::save_all(&db);
527                        Some(idx)
528                    }
529                }
530            }
531            pub fn save_vec(v:Vec<Self>){
532                let file_path = Self::get_path();
533                let mut db = Self::get_all();
534                for i in v{
535                    db.insert(i.idx, i);
536                }
537                let db_string = serde_json::to_string(&db).unwrap();
538                Self::set_data_string(&file_path, db_string);
539            }
540            pub fn save_all(db:&std::collections::HashMap<u64,Self>){
541                let file_path = Self::get_path();
542                let db_string = serde_json::to_string(db).unwrap();
543                Self::set_data_string(&file_path, db_string);
544            }
545            pub fn remove(&self){
546                Self::remove_by_id(self.idx);
547            }
548            pub fn set_data_string(file_path:&str,db_string:String){
549                if #encript_name != ""{
550                    match std::env::var(#encript_name) {
551                        Ok(encript) => {
552                            struct_to_json_db::write_string_to_txt_encript(file_path, db_string,&encript);
553                        }
554                        Err(e) => {
555                            struct_to_json_db::write_string_to_txt(file_path, db_string);
556                        }
557                    }
558                }else{
559                    struct_to_json_db::write_string_to_txt(file_path, db_string);
560                }
561            }
562            pub fn get_data_string(file_path:&str)->String{
563                if #encript_name != ""{
564                    match std::env::var(#encript_name) {
565                        Ok(encript) => {
566                            struct_to_json_db::read_string_from_txt_encript(&file_path,&encript)
567                        }
568                        Err(e) => {
569                            struct_to_json_db::read_string_from_txt(&file_path)
570                        }
571                    }
572                }else{
573                    struct_to_json_db::read_string_from_txt(&file_path)
574                }
575            }
576        }
577       
578    };
579    if is_singleton{
580        return TokenStream::from(singleton_struct_expand);
581    }
582    if is_complex {
583        return TokenStream::from(complex_struct_expand);
584    }
585    return TokenStream::from(default_struct_expand);
586    
587}
588fn parse_string_to_hashmap(input: &str) -> std::collections::HashMap<String, String> {
589    // Regex pattern to match key-value pairs
590    let re = Regex::new(r#"\s*(\w+)(?:\s*=\s*"([^"]*)")?\s*(?:,|$)"#).unwrap();
591    let mut map = std::collections::HashMap::new();
592    for cap in re.captures_iter(input) {
593        let key = cap[1].to_string();
594        let value = if let Some(value_match) = cap.get(2) {
595            value_match.as_str().to_string()
596        } else {
597            "true".to_string()
598        };
599        map.insert(key, value);
600    }
601    map
602} 
603