1use proc_macro::TokenStream;
249use syn;
251use std::sync::{Mutex,Arc};
252use lazy_static::lazy_static;
253use std::collections::HashMap;
254use regex::Regex;
255use 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
278const 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 }
486}
487
488
489#[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 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 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 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 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));
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!("self.{} = ns.get_array(nsname);\n",k));
698 } else if bsubnargs {
699 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!("self.{}.set_value(&extk,&kn,nsname,ns.clone())?;\n",k));
742 }
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 }
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 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#[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}