1
1
use proc_macro2:: { Span , TokenStream } ;
2
- use quote:: { quote, ToTokens } ;
2
+ use quote:: quote;
3
3
use std:: collections:: hash_map:: DefaultHasher ;
4
4
use std:: env;
5
5
use std:: hash:: { Hash , Hasher } ;
6
6
use std:: path:: { Path , PathBuf } ;
7
- use syn:: parse:: { Parse , ParseStream , Result as ParseResult } ;
7
+ use syn:: parse:: { ParseStream , Parser , Result as ParseResult } ;
8
8
use syn:: punctuated:: Punctuated ;
9
9
use syn:: { Fields , Ident , ItemStruct , LitBool , LitChar , LitStr , Token } ;
10
10
@@ -15,88 +15,61 @@ use crate::error::*;
15
15
// options for `template` attributes
16
16
#[ derive( Default ) ]
17
17
struct DeriveTemplateOptions {
18
+ found_keys : Vec < Ident > ,
18
19
path : Option < LitStr > ,
19
20
delimiter : Option < LitChar > ,
20
21
escape : Option < LitBool > ,
21
22
rm_whitespace : Option < LitBool > ,
22
23
type_ : Option < LitStr > ,
23
24
}
24
25
25
- impl Parse for DeriveTemplateOptions {
26
- fn parse ( outer : ParseStream ) -> ParseResult < Self > {
27
- let s;
28
- syn:: parenthesized!( s in outer) ;
29
-
30
- let mut options = Self :: default ( ) ;
31
- let mut found_keys = Vec :: new ( ) ;
32
-
33
- while !s. is_empty ( ) {
34
- let key = s. parse :: < Ident > ( ) ?;
35
- s. parse :: < Token ! [ =] > ( ) ?;
36
-
37
- // check if argument is repeated
38
- if found_keys. iter ( ) . any ( |e| * e == key) {
39
- return Err ( syn:: Error :: new (
40
- key. span ( ) ,
41
- format ! ( "Argument `{}` was repeated." , key) ,
42
- ) ) ;
43
- }
44
-
45
- if key == "path" {
46
- options. path = Some ( s. parse :: < LitStr > ( ) ?) ;
47
- } else if key == "delimiter" {
48
- options. delimiter = Some ( s. parse :: < LitChar > ( ) ?) ;
49
- } else if key == "escape" {
50
- options. escape = Some ( s. parse :: < LitBool > ( ) ?) ;
51
- } else if key == "rm_whitespace" {
52
- options. rm_whitespace = Some ( s. parse :: < LitBool > ( ) ?) ;
53
- } else if key == "type" {
54
- options. type_ = Some ( s. parse :: < LitStr > ( ) ?) ;
55
- } else {
56
- return Err ( syn:: Error :: new (
57
- key. span ( ) ,
58
- format ! ( "Unknown option: `{}`" , key) ,
59
- ) ) ;
60
- }
61
-
62
- found_keys. push ( key) ;
26
+ impl DeriveTemplateOptions {
27
+ fn parser < ' s > ( & ' s mut self ) -> impl Parser + ' s {
28
+ move |outer : ParseStream | -> ParseResult < ( ) > {
29
+ let s;
30
+ syn:: parenthesized!( s in outer) ;
31
+
32
+ while !s. is_empty ( ) {
33
+ let key = s. parse :: < Ident > ( ) ?;
34
+ s. parse :: < Token ! [ =] > ( ) ?;
35
+
36
+ // check if argument is repeated
37
+ if self . found_keys . iter ( ) . any ( |e| * e == key) {
38
+ return Err ( syn:: Error :: new (
39
+ key. span ( ) ,
40
+ format ! ( "Argument `{}` was repeated." , key) ,
41
+ ) ) ;
42
+ }
63
43
64
- // consume comma token
65
- if s. is_empty ( ) {
66
- break ;
67
- } else {
68
- s. parse :: < Token ! [ , ] > ( ) ?;
69
- }
70
- }
44
+ if key == "path" {
45
+ self . path = Some ( s. parse :: < LitStr > ( ) ?) ;
46
+ } else if key == "delimiter" {
47
+ self . delimiter = Some ( s. parse :: < LitChar > ( ) ?) ;
48
+ } else if key == "escape" {
49
+ self . escape = Some ( s. parse :: < LitBool > ( ) ?) ;
50
+ } else if key == "rm_whitespace" {
51
+ self . rm_whitespace = Some ( s. parse :: < LitBool > ( ) ?) ;
52
+ } else if key == "type" {
53
+ self . type_ = Some ( s. parse :: < LitStr > ( ) ?) ;
54
+ } else {
55
+ return Err ( syn:: Error :: new (
56
+ key. span ( ) ,
57
+ format ! ( "Unknown option: `{}`" , key) ,
58
+ ) ) ;
59
+ }
71
60
72
- Ok ( options)
73
- }
74
- }
61
+ self . found_keys . push ( key) ;
75
62
76
- impl DeriveTemplateOptions {
77
- fn merge ( & mut self , other : DeriveTemplateOptions ) -> Result < ( ) , syn:: Error > {
78
- fn merge_single < T : ToTokens > (
79
- lhs : & mut Option < T > ,
80
- rhs : Option < T > ,
81
- ) -> Result < ( ) , syn:: Error > {
82
- if lhs. is_some ( ) {
83
- if let Some ( rhs) = rhs {
84
- Err ( syn:: Error :: new_spanned ( rhs, "keyword argument repeated." ) )
63
+ // consume comma token
64
+ if s. is_empty ( ) {
65
+ break ;
85
66
} else {
86
- Ok ( ( ) )
67
+ s . parse :: < Token ! [ , ] > ( ) ? ;
87
68
}
88
- } else {
89
- * lhs = rhs;
90
- Ok ( ( ) )
91
69
}
92
- }
93
70
94
- merge_single ( & mut self . path , other. path ) ?;
95
- merge_single ( & mut self . delimiter , other. delimiter ) ?;
96
- merge_single ( & mut self . escape , other. escape ) ?;
97
- merge_single ( & mut self . rm_whitespace , other. rm_whitespace ) ?;
98
- merge_single ( & mut self . type_ , other. type_ ) ?;
99
- Ok ( ( ) )
71
+ Ok ( ( ) )
72
+ }
100
73
}
101
74
}
102
75
@@ -170,8 +143,7 @@ fn derive_template_impl(tokens: TokenStream) -> Result<TokenStream, syn::Error>
170
143
let mut all_options = DeriveTemplateOptions :: default ( ) ;
171
144
for attr in strct. attrs {
172
145
if attr. path . is_ident ( "template" ) {
173
- let opt = syn:: parse2 :: < DeriveTemplateOptions > ( attr. tokens ) ?;
174
- all_options. merge ( opt) ?;
146
+ syn:: parse:: Parser :: parse2 ( all_options. parser ( ) , attr. tokens ) ?;
175
147
}
176
148
}
177
149
0 commit comments