extargsparse_codegen/
lib.rs

1//!  
2//!  This crate is plugin for extargsparse it should be used
3//!  directly with extargsparse_worker 
4//!  ```rust
5//!  use extargsparse_codegen::{ArgSet,extargs_load_commandline,extargs_map_function};
6//!  use extargsparse_worker::argset::{ArgSetImpl};
7//!  use extargsparse_worker::{extargs_error_class,extargs_new_error};
8//!  use extargsparse_worker::namespace::NameSpaceEx;
9//!  use extargsparse_worker::funccall::ExtArgsParseFunc;
10//!  use extargsparse_worker::parser::ExtArgsParser;
11//!  use extargsparse_worker::key::{ExtKeyParse,KEYWORD_LIST};
12//!  
13//!  
14//!  use std::error::Error;
15//!  use lazy_static::lazy_static;
16//!  use regex::Regex;
17//!  use std::sync::Arc;
18//!  use std::cell::RefCell;
19//!  use std::any::Any;
20//!  use std::collections::HashMap;
21//!  use serde_json::Value;
22//!  
23//!  
24//!  extargs_error_class!{TestCaseError}
25//!  
26//!  #[derive(ArgSet)]
27//!  struct DepSt {
28//!  	subnargs :Vec<String>,
29//!  	string : String,
30//!  	list :Vec<String>,
31//!  }
32//!  
33//!  #[derive(ArgSet)]
34//!  struct RdepSt {
35//!  	string :String,
36//!  	subnargs : Vec<String>,
37//!  	list :Vec<String>,
38//!  }
39//!  
40//!  #[derive(ArgSet)]
41//!  struct ImpArg {
42//!  	verbose :i32,
43//!  	port :i32,
44//!  	dep :DepSt,
45//!  	rdep :RdepSt,
46//!  	ccval :Vec<String>,
47//!  	args :Vec<String>,
48//!  }
49//!  
50//!  fn dep_handler(_ns :NameSpaceEx, _args :Option<Arc<RefCell<dyn ArgSetImpl>>>, _ctx : Option<Arc<RefCell<dyn Any>>>) -> Result<(),Box<dyn Error>> {
51//!  	println!("call dep_handler");
52//!  	Ok(())
53//!  }
54//!  
55//!  fn rdep_handler(_ns :NameSpaceEx, _args :Option<Arc<RefCell<dyn ArgSetImpl>>>, _ctx : Option<Arc<RefCell<dyn Any>>>) -> Result<(),Box<dyn Error>> {
56//!  	println!("call rdep_handler");
57//!  	Ok(())
58//!  }
59//!  
60//!  fn debug_upper_jsonfunc(ns :NameSpaceEx, keycls :ExtKeyParse, value :Value) -> Result<(),Box<dyn Error>> {
61//!      let mut setval :Vec<String> = Vec::new();
62//!  
63//!      if !keycls.is_flag() || keycls.type_name() != KEYWORD_LIST {
64//!          extargs_new_error!{TestCaseError,"keycls [{}] not string type", keycls.string()}
65//!      }
66//!  
67//!      match value {
68//!          Value::Null => {
69//!          },
70//!          Value::Array(_v) => {
71//!          	let mut _idx :i32 = 0;
72//!              for cv in _v.iter() {
73//!              	match cv {
74//!              		Value::String(_a) => {
75//!              			setval.push(format!("{}",_a).to_uppercase());
76//!              		},
77//!              		_ => {
78//!              			extargs_new_error!{TestCaseError,"[{}] not string type",_idx}
79//!              		}
80//!              	}
81//!              	_idx += 1;
82//!              }
83//!          },
84//!          _ => { extargs_new_error!{TestCaseError,"value [{:?}] not valid" , value } }
85//!      }
86//!  
87//!      return ns.set_array(&keycls.opt_dest(), setval);
88//!  }
89//!  
90//!  fn debug_opthelp_set(keycls :&ExtKeyParse) -> String {
91//!      let mut cs :String = "".to_string();
92//!      let mut idx :i32 = 0;
93//!      match keycls.value() {
94//!          Value::Array(_a) => {
95//!              cs.push_str("[");
96//!              for curv in _a {
97//!                  match curv {
98//!                      Value::String(v) => {
99//!                          if idx > 0 {
100//!                              cs.push_str(",");
101//!                          }
102//!                          cs.push_str(&(v.to_string()));
103//!                          idx += 1;
104//!                      },
105//!                      _ => {}
106//!                  }
107//!              }
108//!              cs.push_str("]");
109//!          },
110//!          _ => {}
111//!      }
112//!      return format!("opthelp function set [{}] default value ({})", keycls.opt_dest(), cs);
113//!  }
114//!  
115//!  fn debug_set_2_args(ns :NameSpaceEx, validx :i32, keycls :ExtKeyParse, params :Vec<String>) -> Result<i32,Box<dyn Error>> {
116//!      let mut sarr :Vec<String>;
117//!      println!("validx [{}]",validx);
118//!      if (validx + 2) > params.len() as i32 {
119//!          extargs_new_error!{TestCaseError,"[{}+2] > len({}) {:?}",validx,params.len(),params}
120//!      }
121//!  
122//!      sarr = ns.get_array(&keycls.opt_dest());
123//!      sarr.push(format!("{}",params[validx as usize]));
124//!      sarr.push(format!("{}",params[(validx + 1) as usize]));
125//!      println!("set [{}] value {:?}", keycls.opt_dest(),sarr);
126//!      ns.set_array(&keycls.opt_dest(),sarr)?;
127//!      println!("{}={:?}", keycls.opt_dest(), ns.get_array(&keycls.opt_dest()));
128//!      return Ok(2);
129//!  }
130//!  
131//!  
132//!  #[extargs_map_function(dep_handler,rdep_handler,jsonfunc=debug_upper_jsonfunc,opthelp=debug_opthelp_set,optparse=debug_set_2_args)]
133//!  fn main() -> Result<(),Box<dyn Error>> {
134//!      let cmdline = r#"{
135//!      	"verbose|v" : "+",
136//!      	"port|p" : 3000,
137//!      	"ccval|C!jsonfunc=debug_upper_jsonfunc;opthelp=debug_opthelp_set;optparse=debug_set_2_args!" : [],
138//!      	"dep<dep_handler>" : {
139//!      		"list|l" : [],
140//!      		"string|s" : "s_var",
141//!      		"$" : "+"
142//!      	},
143//!      	"rdep<rdep_handler>" : {
144//!      		"list|L" : [],
145//!      		"string|S" : "s_rdep",
146//!      		"$" : 2
147//!      	}
148//!      }"#;
149//!      let parser :ExtArgsParser = ExtArgsParser::new(None,None)?;
150//!      extargs_load_commandline!(parser,cmdline)?;
151//!      let v :ImpArg = ImpArg::new();
152//!      let argv :Arc<RefCell<ImpArg>> = Arc::new(RefCell::new(v));
153//!      let ns :NameSpaceEx = parser.parse_commandline_ex(None,None,Some(argv.clone()),None)?;
154//!      println!("ns.verbose {}", ns.get_int("verbose"));
155//!      println!("ns.port {}",ns.get_int("port") );
156//!      println!("subcommand {}",ns.get_string("subcommand"));
157//!      println!("rdep_list {:?}", ns.get_array("rdep_list"));
158//!      println!("rdep_string {:?}", ns.get_array("rdep_string"));
159//!      println!("subnargs {:?}", ns.get_array("subnargs"));
160//!      println!("argv.verbose {}", argv.borrow().verbose);
161//!      println!("argv.port {}",argv.borrow().port);
162//!      println!("argv.args {:?}",argv.borrow().args);
163//!      println!("argv.rdep.subnargs {:?}", argv.borrow().rdep.subnargs);
164//!      println!("argv.rdep.list {:?}", argv.borrow().rdep.list);
165//!      println!("argv.rdep.string {:?}", argv.borrow().rdep.string);
166//!      println!("argv.ccval {:?}",argv.borrow().ccval );
167//!      println!("ccval {:?}", ns.get_array("ccval"));
168//!  
169//!      Ok(())
170//!  }
171//!  /*
172//!  command:
173//!  cargo run --release -- -h
174//!  output:
175//!  multifunc.exe  [OPTIONS] [SUBCOMMANDS] [args...]
176//!  
177//!   [OPTIONS]
178//!      --json        json     json input file to get the value set            
179//!      --help|-h              to display this help information                
180//!      --ccval|-C    ccval    opthelp function set [ccval] default value ([]) 
181//!      --port|-p     port     port set default 3000                           
182//!      --verbose|-v  verbose  count set default 0                             
183//!  
184//!  [SUBCOMMANDS]
185//!      [dep]   dep handler  
186//!      [rdep]  rdep handler 
187//!  notice:
188//!  --ccval|-C    ccval    opthelp function set [ccval] default value ([]) 
189//!  line is formatted by debug_opthelp_set
190//!  
191//!  command:
192//!  cargo run --release -- -C bbs wwww depargs dep
193//!  output:
194//!  validx [1]
195//!  set [ccval] value ["bbs", "wwww"]
196//!  ccval=["bbs", "wwww"]
197//!  call dep_handler
198//!  ns.verbose 0
199//!  ns.port 3000
200//!  subcommand dep
201//!  rdep_list []
202//!  rdep_string []
203//!  subnargs ["depargs"]
204//!  argv.verbose 0
205//!  argv.port 3000
206//!  argv.args []
207//!  argv.rdep.subnargs []
208//!  argv.rdep.list []
209//!  argv.rdep.string "s_rdep"
210//!  argv.ccval ["bbs", "wwww"]
211//!  ccval ["bbs", "wwww"]
212//!  notice:
213//!  -C bbs wwww will give two args format debug_set_2_args
214//!  
215//!  file c.json:
216//!  {
217//!  	"ccval" : ["bb","aa"]
218//!  }
219//!  
220//!  command:
221//!  cargo run --release -- --json .\c.json depargs dep
222//!  
223//!  output:
224//!  call dep_handler
225//!  ns.verbose 0
226//!  ns.port 3000
227//!  subcommand dep
228//!  rdep_list []
229//!  rdep_string []
230//!  subnargs ["depargs"]
231//!  argv.verbose 0
232//!  argv.port 3000
233//!  argv.args []
234//!  argv.rdep.subnargs []
235//!  argv.rdep.list []
236//!  argv.rdep.string "s_rdep"
237//!  argv.ccval ["BB", "AA"]
238//!  ccval ["BB", "AA"]
239//!  
240//!  notice:
241//!  call json function debug_upper_jsonfunc to uppercase
242//!  
243//!  */
244//!  ```
245//!  
246
247
248use proc_macro::TokenStream;
249//use proc_macro2::Span;
250use syn;
251use std::sync::{Mutex,Arc};
252use lazy_static::lazy_static;
253use std::collections::HashMap;
254use regex::Regex;
255//use std::cmp::Ordering;
256
257use rand::Rng;
258use bytes::{BytesMut,BufMut};
259
260
261use std::fmt::{Debug};
262use std::fmt;
263use std::error::Error;
264use std::boxed::Box;
265
266mod consts;
267#[macro_use]
268mod errors;
269#[macro_use]
270mod logger;
271mod util;
272
273use consts::*;
274use logger::{em_debug_out,em_log_get_timestamp};
275use util::{check_in_array};
276
277
278//use std::cell::RefCell;
279//use std::rc::Rc;
280
281
282
283const RAND_NAME_STRING :[u8; 62]= *b"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
284
285
286
287
288lazy_static! {
289	static ref LINK_NAMES :Arc<Mutex<HashMap<String,String>>> = Arc::new(Mutex::new(HashMap::new()));
290	static ref EXTARGS_FUNC_MAP_NAME : Arc<Mutex<String>> = Arc::new(Mutex::new(String::from("")));
291
292	static ref ARGSET_KEYWORDS :Vec<String> = {
293		let mut retv :Vec<String> = Vec::new();
294		retv.push(format!("{}",KEYWORD_U64));
295		retv.push(format!("{}",KEYWORD_I64));
296		retv.push(format!("{}",KEYWORD_F64));
297		retv.push(format!("{}",KEYWORD_U32));
298		retv.push(format!("{}",KEYWORD_I32));
299		retv.push(format!("{}",KEYWORD_F32));
300		retv.push(format!("{}",KEYWORD_TYPE_STRING));
301		retv.push(format!("{}",KEYWORD_TYPE_BOOL));
302		retv.push(format!("{}",KEYWORD_VEC_STRING));
303		retv
304	};
305}
306
307
308fn get_random_bytes(num :u32, basevec :&[u8]) -> String {
309	let mut retm = BytesMut::with_capacity(num as usize);
310	let mut rng = rand::thread_rng();
311	let mut curi :usize;
312
313	for _i in 0..num {
314		curi = rng.gen_range(0..basevec.len());
315		retm.put_u8(basevec[curi]);
316	}
317	let a = retm.freeze();
318	String::from_utf8_lossy(&a).to_string()
319}
320
321
322#[derive(Debug,Clone)]
323struct FuncAttrs {
324	helpfuncs :Vec<String>,
325	jsonfuncs :Vec<String>,
326	optparsefuncs : Vec<String>,
327	callbackfuncs : Vec<String>,
328}
329
330impl FuncAttrs {
331	fn set_funcnames(&mut self,k :&str, v :&str, input : syn::parse::ParseStream) -> Result<(),syn::Error> {
332		if k.len() == 0 && v.len() == 0 {
333			return Ok(());
334		} else if v.len() == 0 {
335			self.callbackfuncs.push(format!("{}",k));
336		} else {
337			if k == FUNC_CALLBACK {
338				self.callbackfuncs.push(format!("{}",v));
339			} else if k == FUNC_OPTHELP {
340				self.helpfuncs.push(format!("{}",v));
341			} else if k == FUNC_JSONFUNC {
342				self.jsonfuncs.push(format!("{}",v));
343			} else if k == FUNC_ACTFUNC {
344				self.optparsefuncs.push(format!("{}",v));
345			} else {
346				let c = format!("we not accept [{}] keyword only accept {}|{}|{}|{}", k,
347					FUNC_ACTFUNC,FUNC_OPTHELP,FUNC_JSONFUNC,FUNC_CALLBACK);
348				return Err(syn::Error::new(input.span(),&c));
349			}
350		}
351		return Ok(());
352	}	
353	fn format_code(&self) -> String {
354		let mut rets :String = "".to_string();
355		let mut fname :String = "st_functions".to_string();
356
357		fname.push_str("_");
358		fname.push_str(&(get_random_bytes(15,&RAND_NAME_STRING)));
359		fname = fname.to_uppercase();
360		rets.push_str("lazy_static ! {\n");
361		rets.push_str(&format_tab_space(1));
362		rets.push_str(&format!("static ref {} :HashMap<String,ExtArgsParseFunc> = {{\n",fname));
363		rets.push_str(&format_tab_space(2));
364		if self.helpfuncs.len() > 0 || self.jsonfuncs.len() > 0 || self.optparsefuncs.len() > 0 || self.callbackfuncs.len() > 0 {
365			rets.push_str(&format!("let mut retv :HashMap<String,ExtArgsParseFunc> = HashMap::new();\n"));	
366		} else {
367			rets.push_str(&format!("let retv :HashMap<String,ExtArgsParseFunc> = HashMap::new();\n"));
368		}
369		
370		if self.jsonfuncs.len() > 0 {
371			for f in self.jsonfuncs.iter() {
372				rets.push_str(&format_tab_space(2));
373				rets.push_str(&format!("retv.insert(format!(\"{}\"), ExtArgsParseFunc::JsonFunc({}));\n",f,f));
374			}
375		}
376
377		if self.optparsefuncs.len() > 0 {
378			for f in self.optparsefuncs.iter() {
379				rets.push_str(&format_tab_space(2));
380				rets.push_str(&format!("retv.insert(format!(\"{}\"), ExtArgsParseFunc::ActionFunc({}));\n",f,f));
381			}
382		}
383
384		if self.helpfuncs.len() > 0 {
385			for f in self.helpfuncs.iter() {
386				rets.push_str(&format_tab_space(2));
387				rets.push_str(&format!("retv.insert(format!(\"{}\"), ExtArgsParseFunc::HelpFunc({}));\n",f,f));
388			}
389		}
390
391		if self.callbackfuncs.len() > 0 {
392			for f in self.callbackfuncs.iter() {
393				rets.push_str(&format_tab_space(2));
394				rets.push_str(&format!("retv.insert(format!(\"{}\"), ExtArgsParseFunc::CallbackFunc({}));\n",f,f));
395			}
396		}
397
398		rets.push_str(&format_tab_space(2));
399		rets.push_str(&format!("retv\n"));
400
401		rets.push_str(&format_tab_space(1));
402		rets.push_str("};\n");
403
404		rets.push_str("}\n");
405		{
406			let mut scb = EXTARGS_FUNC_MAP_NAME.lock().unwrap();
407			if self.helpfuncs.len() > 0 || self.jsonfuncs.len() > 0 || self.optparsefuncs.len() > 0 || self.callbackfuncs.len() > 0 {
408				*scb = format!("{}",fname);	
409			} else {
410				*scb = format!("");
411			}
412			em_log_trace!("EXTARGS_FUNC_MAP_NAME [{}]",scb);
413		}
414
415		em_log_trace!("rets\n{}",rets);
416		return rets;
417	}
418}
419
420impl syn::parse::Parse for FuncAttrs {
421	#[allow(unused_assignments)]
422	fn parse(input : syn::parse::ParseStream) -> syn::parse::Result<Self> {
423		let mut retv :FuncAttrs = FuncAttrs {
424			helpfuncs : Vec::new(),
425			jsonfuncs : Vec::new(),
426			optparsefuncs : Vec::new(),
427			callbackfuncs : Vec::new(),
428		};
429		let mut k :String = "".to_string();
430		let mut v :String = "".to_string();
431		loop {
432			if input.peek(syn::Ident) {
433				let c : syn::Ident = input.parse()?;
434				em_log_trace!("ident [{}]", c);
435				if k.len() == 0 {
436					k = format!("{}", c);
437				} else if v.len() == 0 {
438					v = format!("{}", c);
439				} else {
440					let c = format!("we acept  xx=xx or xx format");
441					return Err(syn::Error::new(input.span(),&c));					
442				}
443			} else if input.peek(syn::Token![=]) {
444				let _c : syn::token::Eq = input.parse()?;
445				em_log_trace!("=");
446			} else if input.peek(syn::Token![,]) {
447				let _c : syn::token::Comma = input.parse()?;
448				em_log_trace!(",");
449				retv.set_funcnames(&k,&v,input.clone())?;
450				k = "".to_string();
451				v = "".to_string();
452			} else {
453				if input.is_empty() {
454					break;
455				}
456				let c = format!("not valid token [{}]",input.to_string());
457				return Err(syn::Error::new(input.span(),&c));
458			}			
459		}
460		retv.set_funcnames(&k,&v,input.clone())?;
461		k = "".to_string();
462		v = "".to_string();
463		return Ok(retv);
464	}
465}
466
467fn format_tab_space(isize :usize) -> String {
468	let mut rets :String = "".to_string();
469	while rets.len() < (isize * 4) {
470		rets.push_str("    ");
471	}
472	return rets;
473}
474
475macro_rules! syn_error_fmt {
476	($($a:expr),*) => {
477		let cerr = format!($($a),*);
478		eprintln!("{}",cerr);
479		em_log_error!("{}",cerr);
480		return cerr.parse().unwrap();
481		//return syn::Error::new(
482        //            Span::call_site(),
483        //            $cerr,
484        //        ).to_compile_error().to_string().parse().unwrap();
485    }
486}
487
488
489///   this is function of functions map expand
490#[proc_macro_attribute]
491pub fn extargs_map_function(_args :TokenStream , input :TokenStream) -> TokenStream {
492	let mut code :String = "".to_string();
493	let nargs = _args.clone();
494	let attrs  = syn::parse_macro_input!(nargs as FuncAttrs);
495	em_log_trace!("attrs [{:?}]",attrs);
496
497	/**/
498	code.push_str(&attrs.format_code());
499	code.push_str(&(input.to_string()));
500	em_log_trace!("code \n{}",code);	
501	code.parse().unwrap()
502}
503
504
505extargs_error_class!{TypeError}
506
507fn get_name_type(n : syn::Field) -> Result<(String,String), Box<dyn Error>> {
508	let name :String ;
509	let mut typename :String = "".to_string();
510	match n.ident {
511		Some(ref _i) => {
512			name = format!("{}",_i);
513		},
514		None => {
515			extargs_new_error!{TypeError,"can not get"}
516		}
517	}
518
519	match n.ty {
520		syn::Type::Path(ref _p) => {
521			let mut pidx :i32 = 0;
522			if _p.path.leading_colon.is_some() {
523				typename.push_str("::");
524			}
525			for _s in _p.path.segments.iter() {
526				if pidx > 0 {
527					typename.push_str("::");
528				}
529				typename.push_str(&(format!("{}",_s.ident)));
530				//em_log_trace!("f [{}]",typename);
531				match _s.arguments {
532					syn::PathArguments::None => {},
533					syn::PathArguments::AngleBracketed(ref _an) => {
534						typename.push_str("<");
535						let mut idx :i32 = 0;
536						for _ii in _an.args.iter() {
537							match _ii {
538								syn::GenericArgument::Type(ref _pi) => {
539									match _pi {
540										syn::Type::Path(ref _pt) => {
541											let mut jdx : i32 = 0;
542											if idx > 0 {
543												typename.push_str(",");
544											}
545											for _tt in _pt.path.segments.iter() {
546												if jdx > 0 {
547													typename.push_str("::");
548												}
549												typename.push_str(&(format!("{}", _tt.ident)));
550												jdx += 1;
551											}
552										},
553										_ => { extargs_new_error!{TypeError, "not "}}
554									}
555								},
556								_ => {
557									extargs_new_error!{TypeError,"no args type"}
558								}
559							}
560							idx += 1;
561						}
562						typename.push_str(">");
563					},
564					syn::PathArguments::Parenthesized(ref _pn) => {
565						extargs_new_error!{TypeError,"Parenthesized"}
566					}
567				}
568				pidx += 1;
569			}
570		},
571		_ => {
572			extargs_new_error!{TypeError,"ty not support for"}
573		}
574	}
575	em_log_trace!("name [{}] typename [{}]",name,typename);
576	Ok((name,typename))
577}
578
579fn format_code(ident :&str,names :HashMap<String,String>, structnames :Vec<String>) -> String {
580	let mut rets :String = "".to_string();
581	let mut typeerrname :String = format!("{}_typeerror",ident);
582	if structnames.len() > 0 {
583		for i in structnames.clone() {
584			/*to make the type check for ArgSetImpl*/
585			rets.push_str(&format!("const _ :fn() = || {{\n"));
586			rets.push_str(&(format_tab_space(1)));
587			rets.push_str(&format!("fn assert_impl_all<T : ?Sized + ArgSetImpl>() {{}}\n"));
588			rets.push_str(&(format_tab_space(1)));
589			rets.push_str(&format!("assert_impl_all::<{}>();\n", i));
590			rets.push_str(&format!("}};\n"));
591		}
592	}
593
594	typeerrname.push_str("_");
595	typeerrname.push_str(&(get_random_bytes(15,&RAND_NAME_STRING)));
596
597
598
599	rets.push_str(&format!("extargs_error_class!{{{}}}\n",typeerrname));
600
601	rets.push_str(&format!("impl ArgSetImpl for {} {{\n",ident));
602	rets.push_str(&(format_tab_space(1)));
603	rets.push_str(&format!("fn new() -> Self {{\n"));
604	rets.push_str(&(format_tab_space(2)));
605	rets.push_str(&format!("{} {{\n",ident));
606	for (k,v) in names.clone().iter() {
607		rets.push_str(&format_tab_space(3));
608		if v == KEYWORD_TYPE_STRING {
609			rets.push_str(&format!("{} : \"\".to_string(),\n", k));
610		} else if v == KEYWORD_U32 || v == KEYWORD_I32 || v == KEYWORD_U64 || v == KEYWORD_I64 {
611			rets.push_str(&format!("{} : 0,\n",k));
612		} else if v == KEYWORD_F32  || v == KEYWORD_F64 {
613			rets.push_str(&format!("{} : 0.0,\n",k));
614		} else if v == KEYWORD_VEC_STRING {
615			rets.push_str(&format!("{} : Vec::new(),\n",k));
616		} else if v == KEYWORD_TYPE_BOOL {
617			rets.push_str(&format!("{} : false,\n",k));
618		}else  {
619			/*to make new type*/
620			rets.push_str(&format!("{} : {}::new(),\n",k,v));
621		}
622	}
623	rets.push_str(&format_tab_space(2));
624	rets.push_str(&format!("}}\n"));
625	rets.push_str(&format_tab_space(1));
626	rets.push_str(&format!("}}\n"));
627
628
629	rets.push_str(&format_tab_space(1));
630	rets.push_str(&format!("\n"));
631
632	rets.push_str(&format_tab_space(1));
633	rets.push_str(&format!("fn set_value(&mut self, prefix :&str,k :&str, nsname :&str, ns :NameSpaceEx) -> Result<(),Box<dyn Error>> {{\n"));
634	rets.push_str(&format_tab_space(2));
635	rets.push_str(&format!("let mut extk :String = \"\".to_string();\n"));
636	let mut i :i32 = 0;
637	for (k,v) in names.clone().iter() {
638		if !check_in_array(ARGSET_KEYWORDS.clone(), v) {
639			continue;
640		}
641
642
643		rets.push_str(&format_tab_space(2));
644		if i > 0 {
645			rets.push_str(&format!("}} else if "));
646		} else {
647			rets.push_str(&format!("if "));
648		}
649		rets.push_str(&format!("k == \"{}\" {{\n", k));
650		rets.push_str(&format_tab_space(3));
651		rets.push_str(&(format!("extk = \"\".to_string();\n")));
652		rets.push_str(&format_tab_space(3));
653		rets.push_str(&(format!("extk.push_str(prefix);\n")));
654		rets.push_str(&format_tab_space(3));
655		rets.push_str(&(format!("if extk.len() > 0 {{\n")));
656		rets.push_str(&format_tab_space(4));
657		rets.push_str(&(format!("extk.push_str(\"_\");\n")));
658		rets.push_str(&format_tab_space(3));
659		rets.push_str(&(format!("}}\n")));
660		rets.push_str(&format_tab_space(3));
661		rets.push_str(&(format!("extk.push_str(\"{}\");\n",k)));
662		//rets.push_str(&format_tab_space(3));
663		//rets.push_str(&(format!("println!(\"will get [{{}}]\", nsname);\n")));
664		rets.push_str(&format_tab_space(3));
665		if v == KEYWORD_TYPE_STRING {
666			rets.push_str(&format!("self.{} = ns.get_string(nsname);\n", k));
667		} else if v == KEYWORD_I32 {
668			rets.push_str(&format!("self.{} = ns.get_int(nsname) as i32;\n",k));
669		} else if v == KEYWORD_U32 {
670			rets.push_str(&format!("self.{} = ns.get_int(nsname) as u32;\n",k));
671		} else if v == KEYWORD_F32 {
672			rets.push_str(&format!("self.{} = ns.get_float(nsname) as f32;\n",k));
673		} else if v == KEYWORD_I64 {
674			rets.push_str(&format!("self.{} = ns.get_int(nsname);\n",k));
675		} else if v == KEYWORD_U64 {
676			rets.push_str(&format!("self.{} = ns.get_int(nsname) as u64;\n",k));
677		} else if v == KEYWORD_F64 {
678			rets.push_str(&format!("self.{} = ns.get_float(nsname);\n",k));
679		} else if v == KEYWORD_TYPE_BOOL {
680			rets.push_str(&format!("self.{} = ns.get_bool(nsname);\n",k));
681		} else if v == KEYWORD_VEC_STRING {
682			let mut bsubnargs : bool= false;
683			let resubnargs;
684			match Regex::new(".*_subnargs$") {
685				Ok(v) => {
686					resubnargs = v;
687					bsubnargs = resubnargs.is_match(k);
688					em_log_trace!("match [{}] [{:?}]",k,bsubnargs);
689				},
690				_ => {}
691			}
692			em_log_trace!("match [{}] [{:?}]",k,bsubnargs);
693
694			if k == KEYWORD_SUBNARGS || k == KEYWORD_ARGS  {
695				//rets.push_str(&(format!("println!(\"will get args[{}]\");\n",k)));
696				//rets.push_str(&format_tab_space(3));				
697				rets.push_str(&format!("self.{} = ns.get_array(nsname);\n",k));
698			} else if  bsubnargs {
699				//rets.push_str(&(format!("println!(\"will get args[{}] [{{}}]\",nsname);\n",k)));
700				//rets.push_str(&format_tab_space(3));
701				rets.push_str(&format!("self.{} = ns.get_array(nsname);\n",k));
702			} else {
703				rets.push_str(&format!("self.{} = ns.get_array(nsname);\n",k));
704			}
705		} 
706		i += 1;
707	}
708
709	if structnames.len() > 0 {
710		for s in structnames.clone() {
711			for (k,v) in names.clone().iter() {
712				if s.eq(v) {
713					rets.push_str(&format_tab_space(2));
714					if i > 0 {
715						rets.push_str(&format!("}} else if "));
716					} else {
717						rets.push_str(&format!("if "));
718					}
719					rets.push_str(&format!("k.starts_with(&format!(\"{}_\")) {{\n",k));
720					rets.push_str(&format_tab_space(3));
721					rets.push_str(&format!("let nk = format!(\"{{}}\",k);\n"));
722					rets.push_str(&format_tab_space(3));
723					rets.push_str(&format!("let re = Regex::new(r\"^{}_\").unwrap();\n",k));
724					rets.push_str(&format_tab_space(3));
725					rets.push_str(&format!("let kn = re.replace_all(&nk,\"\").to_string();\n"));
726					rets.push_str(&format_tab_space(3));
727					rets.push_str(&(format!("extk = \"\".to_string();\n")));
728					rets.push_str(&format_tab_space(3));
729					rets.push_str(&(format!("extk.push_str(prefix);\n")));
730					rets.push_str(&format_tab_space(3));
731					rets.push_str(&(format!("if extk.len() > 0 {{\n")));
732					rets.push_str(&format_tab_space(4));
733					rets.push_str(&(format!("extk.push_str(\"_\");\n")));
734					rets.push_str(&format_tab_space(3));
735					rets.push_str(&(format!("}}\n")));
736					rets.push_str(&format_tab_space(3));
737					rets.push_str(&(format!("extk.push_str(\"{}\");\n",k)));
738					rets.push_str(&format_tab_space(3));
739					//rets.push_str(&(format!("println!(\"will down [{{}}]{{}}\",extk,kn);\n")));
740					//rets.push_str(&format_tab_space(3));
741					rets.push_str(&format!("self.{}.set_value(&extk,&kn,nsname,ns.clone())?;\n",k));
742					/*no break just for next search*/
743				}
744			}
745			i += 1;
746		}
747	}
748
749
750	if i > 0 {
751		rets.push_str(&format_tab_space(2));
752
753		rets.push_str(&format!("}} else {{\n"));
754		rets.push_str(&format_tab_space(3));
755
756		rets.push_str(&format!("extargs_new_error!{{ {},\"[{{}}].{{}} not valid\" , prefix , k}}\n", typeerrname));
757		rets.push_str(&format_tab_space(2));
758
759		rets.push_str(&format!("}}\n"));
760	}
761	rets.push_str(&format_tab_space(2));
762	rets.push_str(&format!("Ok(())\n"));
763	rets.push_str(&format_tab_space(1));
764	rets.push_str(&format!("}}\n"));
765	rets.push_str(&format!("}}\n"));
766
767	rets
768}
769
770
771#[proc_macro_derive(ArgSet)]
772pub fn argset_impl(item :TokenStream) -> TokenStream {
773	em_log_trace!("item\n{}",item.to_string());
774	let co :syn::DeriveInput;
775	let sname :String;
776	let mut names :HashMap<String,String> = HashMap::new();
777	let mut structnames :Vec<String> = Vec::new();
778
779	match syn::parse::<syn::DeriveInput>(item.clone()) {
780		Ok(v) => {
781			co = v.clone();
782		},
783		Err(_e) => {
784			syn_error_fmt!("not parse \n{}",item.to_string());
785          	//return syn::Error::new(
786            //        Span::call_site(),
787            //        &format!(
788            //            "not parse \n{}",
789            //            item.to_string()
790            //        ),
791            //    ).to_compile_error().to_string().parse().unwrap();
792
793        }
794    }
795
796    sname = format!("{}",co.ident);
797    em_log_trace!("sname [{}]",sname);
798
799
800    match co.data {
801    	syn::Data::Struct(ref _vv) => {
802    		match _vv.fields {
803    			syn::Fields::Named(ref _n) => {
804    				for _v in _n.named.iter() {
805    					let res = get_name_type(_v.clone());
806    					if res.is_err() {
807    						syn_error_fmt!("{:?}",res.err().unwrap());
808    					}
809    					let (n,tn) = res.unwrap();
810    					if tn.contains(KEYWORD_LEFT_ARROW) && tn != KEYWORD_VEC_STRING {
811    						syn_error_fmt!("tn [{}] not valid",tn);
812    					}
813    					if names.get(&n).is_some() {
814    						syn_error_fmt!("n [{}] has already in",n);
815    					}
816
817    					if !check_in_array(ARGSET_KEYWORDS.clone(),&tn) {
818    						if !check_in_array(structnames.clone(), &tn) {
819	    						em_log_trace!("input typename [{}]",tn);
820	    						structnames.push(format!("{}",tn));    							
821    						}
822    					}
823
824    					names.insert(format!("{}",n),format!("{}",tn));
825    				}
826    			},
827    			_ => {
828    				syn_error_fmt!("not Named structure\n{}",item.to_string());
829    			}
830    		}
831    	},
832    	_ => {
833    		syn_error_fmt!("not struct format\n{}",item.to_string());
834    	}
835    }
836
837    /*now to compile ok*/
838    let cc = format_code(&sname,names.clone(),structnames.clone());
839    em_log_trace!("cc\n{}",cc);
840
841    cc.parse().unwrap()
842}
843
844#[allow(dead_code)]
845#[derive(Clone,Debug)]
846struct LoadParserAttr {
847	parserident :String,
848	strident :String,
849}
850
851#[allow(dead_code)]
852impl LoadParserAttr {
853	fn format_code(&self) -> String {
854		let mut rets :String = "".to_string();
855		{
856			let c = EXTARGS_FUNC_MAP_NAME.clone();
857			let sb = c.lock().unwrap();
858			if sb.len() > 0 {
859				rets.push_str(&format!("{}.load_commandline_string({},Some({}.clone()))\n",self.parserident,self.strident,sb));	
860			} else {
861				rets.push_str(&format!("{}.load_commandline_string({},None)\n",self.parserident,self.strident));
862			}
863			
864		}
865
866		em_log_trace!("rets [{}]", rets);		
867		return rets;
868	}
869}
870
871impl syn::parse::Parse for LoadParserAttr {
872	#[allow(unused_assignments)]
873	fn parse(input : syn::parse::ParseStream) -> syn::parse::Result<Self> {
874		let mut retv = LoadParserAttr{
875			parserident : "".to_string(),
876			strident : "".to_string(),
877		};
878
879		let mut k :String = "".to_string();
880		loop {
881			if input.is_empty() {
882				break;
883			}
884			if input.peek(syn::Ident) {
885				let c :syn::Ident = input.parse()?;
886				k.push_str(&format!("{}",c));
887			} else if input.peek(syn::token::And) {
888				let _c :syn::token::And = input.parse()?;
889				k.push_str("&");
890			} else if input.peek(syn::token::Paren) {
891				let con ;
892				{
893					em_log_trace!("start parenthesized");
894					let _c = syn::parenthesized!(con in input);
895					em_log_trace!("end parenthesized [{}]", con.to_string());
896					k.push_str(&format!("({})",con.to_string()));
897					let _fields :Box<syn::Expr> = con.parse()?;
898				}
899			} else if input.peek(syn::token::Comma) {
900				let _c : syn::token::Comma = input.parse()?;
901				if retv.parserident.len() == 0 {
902					retv.parserident = format!("{}",k);
903				} else if retv.strident.len() == 0 {
904					retv.strident = format!("{}",k);
905				} else {
906					let c = format!("we only accept two params");
907					return Err(syn::Error::new(input.span(),&c));					
908				}
909				k = "".to_string();
910			} else {
911				let c = format!("not valid macro expand parameters\n{}",input.to_string());
912				return Err(syn::Error::new(input.span(),&c));					
913			}
914		}
915
916		if k.len() > 0 {
917			if retv.parserident.len() == 0 {
918				retv.parserident = format!("{}",k);
919			} else if retv.strident.len() == 0 {
920				retv.strident = format!("{}",k);
921			} else {
922				let c = format!("we only accept two params");
923				return Err(syn::Error::new(input.span(),&c));					
924			}
925			k = "".to_string();
926		}
927
928		if retv.parserident.len() == 0 || retv.strident.len() == 0 {
929			let c = format!("need two params\n{}",input.to_string());
930			return Err(syn::Error::new(input.span(),&c));
931		}
932
933
934		em_log_trace!("{:?}",retv);
935		return Ok(retv);
936	}
937}
938
939/// expand extargs_map_function random make functions name
940/// to make this function to expand  
941/// ```
942/// extargs_load_commandline!(parser,loads)?;
943/// ```
944/// to expand
945/// ```
946/// parser.load_command_line(loads,st_functions_xxww222)?;
947/// ```
948/// which st_functions_xxww222 is generated by extargs_map_function macros
949
950#[proc_macro]
951pub fn extargs_load_commandline(input :TokenStream) -> TokenStream {
952	let mut code :String = "".to_string();
953	em_log_trace!("input \n{}",input.to_string());
954	let nargs = input.clone();
955	let pattr :LoadParserAttr = syn::parse_macro_input!(nargs as LoadParserAttr);
956	code.push_str(&pattr.format_code());
957	em_log_trace!("code \n{}",code);
958	return code.parse().unwrap();
959}