@@ -4,6 +4,7 @@ use std::collections::HashSet;
44
55use proc_macro2:: TokenStream ;
66use quote:: { ToTokens , format_ident, quote, quote_spanned} ;
7+ use syn:: Ident ;
78use syn:: ext:: IdentExt ;
89use syn:: {
910 Data , DataStruct , DeriveInput , Expr , ExprLit , Fields , FieldsNamed , Lit , LitStr ,
@@ -42,26 +43,38 @@ pub fn try_run(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
4243 ..
4344 } ) => {
4445 let args = collect_args_meta ( fields) ?;
45- let init = build_args_init ( & args) ?;
46+ let init = build_args_init ( & args, format_ident ! ( "args" ) ) ?;
4647
4748 let ( ids_ty, ids) = parse_and_build_arg_ids ( & args) ?;
4849
4950 let attrs = Attr :: parse_all ( & input. attrs ) ?;
50- let limit = get_noshell_attr_limit_arg_value ( & attrs) ?. unwrap_or ( PARSER_ARG_COUNT_MAX ) ;
51+ let size = get_noshell_attr_limit_arg_value ( & attrs) ?. unwrap_or ( PARSER_ARG_COUNT_MAX ) ;
5152
5253 Ok ( quote ! {
5354 impl #ident {
54- pub fn parse<' a>( __argv: & ' a [ & ' a str ] ) -> Result <Self , noshell:: Error > {
55+ pub fn try_parse_from<' a, IterTy >( input: IterTy ) -> Result <Self , noshell:: Error >
56+ where
57+ IterTy : Iterator <Item = & ' a str > + Clone ,
58+ {
5559 use noshell:: parser:: ParsedArgs ;
5660
57- let __ids = Self :: ids( ) ;
58- let __tokens = noshell:: parser:: Tokens :: new( __argv) ;
59- let __args: ParsedArgs <' _, #limit> = noshell:: parser:: ParsedArgs :: parse( __tokens, __ids) ;
61+ let flags = Self :: parsed_flag_ids( ) ;
62+ let args = ParsedArgs :: <' _, _, #size>:: try_parse_from( input, flags. iter( ) ) ?;
6063
6164 Ok ( #ident #init)
6265 }
6366
64- pub fn ids( ) -> & ' static [ ( noshell:: parser:: lexer:: Flag <' static >, & ' static str ) ] {
67+ pub fn parse_from<' a, IterTy >( iter: IterTy ) -> Self
68+ where
69+ IterTy : Iterator <Item = & ' a str > + Clone ,
70+ {
71+ Self :: try_parse_from( iter) . expect( "should parse arguments from iterator" )
72+ }
73+
74+ pub fn parsed_flag_ids( ) -> & ' static [
75+ ( noshell:: parser:: lexer:: Flag <' static >, & ' static str )
76+ ]
77+ {
6578 static IDS : #ids_ty = #ids;
6679 & IDS
6780 }
@@ -91,10 +104,10 @@ fn collect_args_meta(fields: &FieldsNamed) -> Result<Vec<MetaArg>, syn::Error> {
91104 Ok ( meta)
92105}
93106
94- fn build_args_init ( fields : & [ MetaArg ] ) -> Result < TokenStream , syn:: Error > {
107+ fn build_args_init ( fields : & [ MetaArg ] , ident : Ident ) -> Result < TokenStream , syn:: Error > {
95108 let args = fields
96109 . iter ( )
97- . map ( build_arg_parser)
110+ . map ( |x| build_arg_parser ( x , ident . clone ( ) ) )
98111 . collect :: < Result < Vec < _ > , syn:: Error > > ( ) ?;
99112
100113 Ok ( quote ! { {
@@ -104,23 +117,22 @@ fn build_args_init(fields: &[MetaArg]) -> Result<TokenStream, syn::Error> {
104117 } } )
105118}
106119
107- fn build_arg_parser ( arg : & MetaArg ) -> Result < TokenStream , syn:: Error > {
120+ fn build_arg_parser ( arg : & MetaArg , args_ident : Ident ) -> Result < TokenStream , syn:: Error > {
108121 let ty = & arg. ty ;
109122 let inner_ty = get_inner_ty ( ty) ;
110123
111- let args = format_ident ! ( "__args" ) ;
112124 let try_get_one = quote_spanned ! ( inner_ty. span( ) => try_get_one:: <#inner_ty>) ;
113125 let try_get_many = quote_spanned ! ( inner_ty. span( ) => try_get_many:: <_, #inner_ty>) ;
114126
115- let ident = arg. id . unraw ( ) ;
116- let id = ident . to_string ( ) ;
127+ let arg_ident = arg. id . unraw ( ) ;
128+ let arg_id = arg_ident . to_string ( ) ;
117129
118130 let value = match Ty :: from_syn_ty ( ty) {
119131 // Optional argument with required value.
120132 Ty :: Option => quote_spanned ! { ty. span( ) =>
121- if #args . contains( #id ) {
133+ if #args_ident . contains( #arg_id ) {
122134 Some (
123- #args . #try_get_one( #id )
135+ #args_ident . #try_get_one( #arg_id )
124136 . map( Option :: unwrap)
125137 . and_then( noshell:: parser:: utils:: check_value_is_missing)
126138 . map( Option :: unwrap) ?
@@ -132,9 +144,9 @@ fn build_arg_parser(arg: &MetaArg) -> Result<TokenStream, syn::Error> {
132144
133145 // Optional argument with optional value.
134146 Ty :: OptionOption => quote_spanned ! { ty. span( ) =>
135- if #args . contains( #id ) {
147+ if #args_ident . contains( #arg_id ) {
136148 Some (
137- #args . #try_get_one( #id ) . map( Option :: flatten) ?
149+ #args_ident . #try_get_one( #arg_id ) . map( Option :: flatten) ?
138150 )
139151 } else {
140152 None
@@ -143,9 +155,9 @@ fn build_arg_parser(arg: &MetaArg) -> Result<TokenStream, syn::Error> {
143155
144156 // Optional argument with required non-empty sequence of values.
145157 Ty :: OptionVec => quote_spanned ! { ty. span( ) =>
146- if #args . contains( #id ) {
158+ if #args_ident . contains( #arg_id ) {
147159 Some (
148- #args . #try_get_many( #id )
160+ #args_ident . #try_get_many( #arg_id )
149161 . map( Option :: unwrap)
150162 . and_then( noshell:: parser:: utils:: check_vec_is_missing) ?
151163 )
@@ -156,15 +168,15 @@ fn build_arg_parser(arg: &MetaArg) -> Result<TokenStream, syn::Error> {
156168
157169 // Required argument with required non-empty sequence of values.
158170 Ty :: Vec => quote_spanned ! { ty. span( ) =>
159- #args . #try_get_many( #id )
171+ #args_ident . #try_get_many( #arg_id )
160172 . and_then( noshell:: parser:: utils:: check_arg_is_missing)
161173 . map( Option :: unwrap)
162174 . and_then( noshell:: parser:: utils:: check_vec_is_missing) ?
163175 } ,
164176
165177 // Required argument with required value.
166178 Ty :: Simple => quote_spanned ! { ty. span( ) =>
167- #args . #try_get_one( #id )
179+ #args_ident . #try_get_one( #arg_id )
168180 . and_then( noshell:: parser:: utils:: check_arg_is_missing)
169181 . map( Option :: unwrap)
170182 . and_then( noshell:: parser:: utils:: check_value_is_missing)
@@ -173,7 +185,7 @@ fn build_arg_parser(arg: &MetaArg) -> Result<TokenStream, syn::Error> {
173185 } ;
174186
175187 Ok ( quote_spanned ! { arg. span=>
176- #ident : #value
188+ #arg_ident : #value
177189 } )
178190}
179191
@@ -388,6 +400,8 @@ fn parse_and_build_arg_ids(args: &[MetaArg]) -> Result<(TokenStream, TokenStream
388400mod tests {
389401 use syn:: Field ;
390402
403+ use crate :: tests:: utils:: format_rust_token_stream;
404+
391405 use super :: * ;
392406
393407 #[ test]
@@ -536,7 +550,7 @@ mod tests {
536550
537551 let attrs = Attr :: parse_all ( & field. attrs ) ?;
538552 let meta = MetaArg :: new ( & field, attrs) ;
539- let given = build_arg_parser ( & meta) ?;
553+ let given = build_arg_parser ( & meta, format_ident ! ( "__args" ) ) ?;
540554
541555 let expected = quote ! (
542556 value: __args. try_get_one:: <u32 >( "value" )
@@ -557,7 +571,7 @@ mod tests {
557571
558572 let attrs = Attr :: parse_all ( & field. attrs ) ?;
559573 let meta = MetaArg :: new ( & field, attrs) ;
560- let given = build_arg_parser ( & meta) ?;
574+ let given = build_arg_parser ( & meta, format_ident ! ( "__args" ) ) ?;
561575
562576 let expected = quote ! (
563577 value: if __args. contains( "value" ) {
@@ -583,7 +597,7 @@ mod tests {
583597
584598 let attrs = Attr :: parse_all ( & field. attrs ) ?;
585599 let meta = MetaArg :: new ( & field, attrs) ;
586- let given = build_arg_parser ( & meta) ?;
600+ let given = build_arg_parser ( & meta, format_ident ! ( "__args" ) ) ?;
587601
588602 let expected = quote ! ( value:
589603 if __args. contains( "value" ) {
@@ -606,7 +620,7 @@ mod tests {
606620
607621 let attrs = Attr :: parse_all ( & field. attrs ) ?;
608622 let meta = MetaArg :: new ( & field, attrs) ;
609- let given = build_arg_parser ( & meta) ?;
623+ let given = build_arg_parser ( & meta, format_ident ! ( "__args" ) ) ?;
610624
611625 let expected = quote ! ( value:
612626 if __args. contains( "value" ) {
@@ -631,7 +645,7 @@ mod tests {
631645
632646 let attrs = Attr :: parse_all ( & field. attrs ) ?;
633647 let meta = MetaArg :: new ( & field, attrs) ;
634- let given = build_arg_parser ( & meta) ?;
648+ let given = build_arg_parser ( & meta, format_ident ! ( "__args" ) ) ?;
635649
636650 let expected = quote ! (
637651 value: __args. try_get_many:: <_, u32 >( "value" )
@@ -654,43 +668,8 @@ mod tests {
654668 }
655669 } ;
656670
657- let given = try_run ( & derive) ?;
658-
659- let expected = quote ! {
660- impl MyArgs {
661- pub fn parse<' a>( __argv: & ' a [ & ' a str ] ) -> Result <Self , noshell:: Error > {
662- use noshell:: parser:: ParsedArgs ;
663-
664- let __ids = Self :: ids( ) ;
665- let __tokens = noshell:: parser:: Tokens :: new( __argv) ;
666- let __args: ParsedArgs <' _, 16usize > = noshell:: parser:: ParsedArgs :: parse( __tokens, __ids) ;
667-
668- Ok ( MyArgs {
669- value1: __args. try_get_one:: <u32 >( "value1" )
670- . and_then( noshell:: parser:: utils:: check_arg_is_missing)
671- . map( Option :: unwrap)
672- . and_then( noshell:: parser:: utils:: check_value_is_missing)
673- . map( Option :: unwrap) ?,
674-
675- value2: __args. try_get_one:: <u32 >( "value2" )
676- . and_then( noshell:: parser:: utils:: check_arg_is_missing)
677- . map( Option :: unwrap)
678- . and_then( noshell:: parser:: utils:: check_value_is_missing)
679- . map( Option :: unwrap) ?
680- } )
681- }
682-
683- pub fn ids( ) -> & ' static [ ( noshell:: parser:: lexer:: Flag <' static >, & ' static str ) ] {
684- static IDS : [ ( noshell:: parser:: lexer:: Flag <' static >, & ' static str ) ; 2usize ] = [
685- ( noshell:: parser:: lexer:: Flag :: Long ( "value1" ) , "value1" ) ,
686- ( noshell:: parser:: lexer:: Flag :: Long ( "value2" ) , "value2" ) ,
687- ] ;
688- & IDS
689- }
690- }
691- } ;
692-
693- assert_eq ! ( expected. to_string( ) , given. to_string( ) ) ;
671+ let output = format_rust_token_stream ( try_run ( & derive) ?) ;
672+ insta:: assert_snapshot!( output) ;
694673
695674 Ok ( ( ) )
696675 }
0 commit comments