11use proc_macro2:: { Span , TokenStream } ;
2- use quote:: { quote, ToTokens } ;
2+ use quote:: quote;
33use std:: collections:: hash_map:: DefaultHasher ;
44use std:: env;
55use std:: hash:: { Hash , Hasher } ;
66use std:: path:: { Path , PathBuf } ;
7- use syn:: parse:: { Parse , ParseStream , Result as ParseResult } ;
7+ use syn:: parse:: { ParseStream , Parser , Result as ParseResult } ;
88use syn:: punctuated:: Punctuated ;
99use syn:: { Fields , Ident , ItemStruct , LitBool , LitChar , LitStr , Token } ;
1010
@@ -15,88 +15,61 @@ use crate::error::*;
1515// options for `template` attributes
1616#[ derive( Default ) ]
1717struct DeriveTemplateOptions {
18+ found_keys : Vec < Ident > ,
1819 path : Option < LitStr > ,
1920 delimiter : Option < LitChar > ,
2021 escape : Option < LitBool > ,
2122 rm_whitespace : Option < LitBool > ,
2223 type_ : Option < LitStr > ,
2324}
2425
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+ }
6343
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+ }
7160
72- Ok ( options)
73- }
74- }
61+ self . found_keys . push ( key) ;
7562
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 ;
8566 } else {
86- Ok ( ( ) )
67+ s . parse :: < Token ! [ , ] > ( ) ? ;
8768 }
88- } else {
89- * lhs = rhs;
90- Ok ( ( ) )
9169 }
92- }
9370
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+ }
10073 }
10174}
10275
@@ -170,8 +143,7 @@ fn derive_template_impl(tokens: TokenStream) -> Result<TokenStream, syn::Error>
170143 let mut all_options = DeriveTemplateOptions :: default ( ) ;
171144 for attr in strct. attrs {
172145 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 ) ?;
175147 }
176148 }
177149
0 commit comments