1
- use std:: iter:: FromIterator ;
2
-
3
- use proc_macro2:: Span ;
4
- use syn:: spanned:: Spanned ;
5
-
6
- use super :: Direction ;
1
+ macro_rules! impl_options {
2
+ {
3
+ self : $self: ident,
4
+ match $ident: ident . as_str( ) {
5
+ $( $name: ident, ) *
6
+ $( $alias: literal => $name_aliased: ident, ) *
7
+ }
8
+ } => (
9
+ match $ident. as_str( ) {
10
+ $(
11
+ stringify!( $name) => {
12
+ $self. $name = true ;
13
+ return Ok ( ( ) ) ;
14
+ } ,
15
+ ) *
16
+ $(
17
+ $alias => {
18
+ $self. $name_aliased = true ;
19
+ return Ok ( ( ) ) ;
20
+ } ,
21
+ ) *
22
+ _ => { } ,
23
+ }
24
+ ) ;
25
+ {
26
+ self : $self: ident,
27
+ match $ident: ident . as_str( ) = $lit: ident {
28
+ $( $name: ident: $ty: ty, ) *
29
+ $( $alias: literal => $name_aliased: ident: $ty_aliased: ty, ) *
30
+ }
31
+ } => (
32
+ match $ident. as_str( ) {
33
+ $(
34
+ stringify!( $name) => {
35
+ let val = match $lit {
36
+ syn:: Lit :: Str ( lit_str) => lit_str. parse:: <$ty>( ) ?,
37
+ _ => return Err ( syn:: Error :: new( $lit. span( ) , "expected string literal" ) ) ,
38
+ } ;
39
+
40
+ if $self. $name. replace( val) . is_some( ) {
41
+ return Err ( syn:: Error :: new( $lit. span( ) , format!(
42
+ "the argument {} is already set" ,
43
+ stringify!( $name) ,
44
+ ) ) ) ;
45
+ }
7
46
8
- #[ derive( Clone , Eq , PartialEq , Debug ) ]
9
- pub struct Attr {
10
- pub skip_to_variant : bool ,
11
- pub skip_from_variant : bool ,
12
- pub to_variant_with : Option < syn:: Path > ,
13
- pub from_variant_with : Option < syn:: Path > ,
14
- }
47
+ return Ok ( ( ) ) ;
48
+ } ,
49
+ ) *
50
+ $(
51
+ $alias => {
52
+ let val = match $lit {
53
+ syn:: Lit :: Str ( lit_str) => lit_str. parse:: <$ty_aliased>( ) ?,
54
+ _ => return Err ( syn:: Error :: new( $lit. span( ) , "expected string literal" ) ) ,
55
+ } ;
56
+
57
+ if $self. $name_aliased. replace( val) . is_some( ) {
58
+ return Err ( syn:: Error :: new( $lit. span( ) , format!(
59
+ "the argument {} is already set" ,
60
+ $alias,
61
+ ) ) ) ;
62
+ }
15
63
16
- impl Attr {
17
- pub ( crate ) fn skip_bounds ( & self , dir : Direction ) -> bool {
18
- match dir {
19
- Direction :: To => self . skip_to_variant ,
20
- Direction :: From => self . skip_from_variant ,
64
+ return Ok ( ( ) ) ;
65
+ } ,
66
+ ) *
67
+ _ => { } ,
21
68
}
22
- }
23
- }
24
-
25
- #[ derive( Debug , Default ) ]
26
- pub struct AttrBuilder {
27
- skip_to_variant : bool ,
28
- skip_from_variant : bool ,
29
- to_variant_with : Option < syn:: Path > ,
30
- from_variant_with : Option < syn:: Path > ,
31
- errors : Vec < syn:: Error > ,
69
+ )
32
70
}
33
71
34
- fn generate_error_with_docs ( span : Span , message : & str ) -> syn:: Error {
72
+ fn generate_error_with_docs ( span : proc_macro2 :: Span , message : & str ) -> syn:: Error {
35
73
syn:: Error :: new (
36
74
span,
37
75
format ! (
@@ -41,224 +79,13 @@ fn generate_error_with_docs(span: Span, message: &str) -> syn::Error {
41
79
)
42
80
}
43
81
44
- impl AttrBuilder {
45
- fn extend_meta ( & mut self , meta : & syn:: Meta ) {
46
- match meta {
47
- syn:: Meta :: Path ( flag) => self . set_flag ( flag) ,
48
- syn:: Meta :: NameValue ( pair) => self . set_pair ( pair) ,
49
- syn:: Meta :: List ( list) => {
50
- for nested in list. nested . iter ( ) {
51
- match nested {
52
- syn:: NestedMeta :: Meta ( meta) => self . extend_meta ( meta) ,
53
- _ => {
54
- self . errors
55
- . push ( syn:: Error :: new ( nested. span ( ) , "unexpected nested meta" ) ) ;
56
- }
57
- }
58
- }
59
- }
60
- }
61
- }
62
-
63
- fn set_flag ( & mut self , flag : & syn:: Path ) {
64
- let err = self . try_set_flag ( flag) . err ( ) ;
65
- self . errors . extend ( err) ;
66
- }
67
-
68
- fn try_set_flag ( & mut self , flag : & syn:: Path ) -> Result < ( ) , syn:: Error > {
69
- let name = flag
70
- . get_ident ( )
71
- . ok_or_else ( || generate_error_with_docs ( flag. span ( ) , "Invalid syntax" ) ) ?
72
- . to_string ( ) ;
73
-
74
- macro_rules! impl_options {
75
- {
76
- match $ident: ident . as_str( ) {
77
- $( $name: ident, ) *
78
- }
79
- } => (
80
- match $ident. as_str( ) {
81
- $(
82
- stringify!( $name) => {
83
- self . $name = true ;
84
- return Ok ( ( ) ) ;
85
- } ,
86
- ) *
87
- _ => { } ,
88
- }
89
- )
90
- }
91
-
92
- impl_options ! {
93
- match name. as_str( ) {
94
- skip_to_variant,
95
- skip_from_variant,
96
- }
97
- }
98
-
99
- #[ allow( clippy:: single_match) ]
100
- match name. as_str ( ) {
101
- "skip" => {
102
- self . skip_to_variant = true ;
103
- self . skip_from_variant = true ;
104
- return Ok ( ( ) ) ;
105
- }
106
- _ => { }
107
- }
108
-
109
- Err ( generate_error_with_docs (
110
- flag. span ( ) ,
111
- "Missing macro arguments" ,
112
- ) )
113
- }
114
-
115
- fn set_pair ( & mut self , pair : & syn:: MetaNameValue ) {
116
- let err = self . try_set_pair ( pair) . err ( ) ;
117
- self . errors . extend ( err) ;
118
- }
119
-
120
- #[ allow( clippy:: single_match) ]
121
- fn try_set_pair ( & mut self , pair : & syn:: MetaNameValue ) -> Result < ( ) , syn:: Error > {
122
- let syn:: MetaNameValue { path, lit, .. } = pair;
123
-
124
- const VALID_KEYS : & str =
125
- "to_variant_with, from_variant_with, with, skip_to_variant, skip_from_variant, skip" ;
126
-
127
- let name = path
128
- . get_ident ( )
129
- . ok_or_else ( || {
130
- let path_token = path. segments . iter ( ) . enumerate ( ) . fold (
131
- String :: new ( ) ,
132
- |mut paths, ( index, segment) | {
133
- if index > 0 {
134
- paths. push_str ( "::" ) ;
135
- }
136
- paths. push_str ( & segment. ident . to_string ( ) ) ;
137
- paths
138
- } ,
139
- ) ;
140
- syn:: Error :: new (
141
- path. span ( ) ,
142
- & format ! ( "Found {}, expected one of:\n \t {}" , path_token, VALID_KEYS ) ,
143
- )
144
- } ) ?
145
- . to_string ( ) ;
146
-
147
- macro_rules! impl_options {
148
- {
149
- match $ident: ident . as_str( ) = $lit: ident {
150
- $( $name: ident: $ty: ty, ) *
151
- }
152
- } => (
153
- match $ident. as_str( ) {
154
- $(
155
- stringify!( $name) => {
156
- let val = match $lit {
157
- syn:: Lit :: Str ( lit_str) => lit_str. parse:: <$ty>( ) ?,
158
- _ => return Err ( syn:: Error :: new( $lit. span( ) , "expected string literal" ) ) ,
159
- } ;
160
-
161
- if self . $name. replace( val) . is_some( ) {
162
- return Err ( syn:: Error :: new( $lit. span( ) , format!(
163
- "the argument {} is already set" ,
164
- stringify!( $name) ,
165
- ) ) ) ;
166
- }
167
-
168
- return Ok ( ( ) ) ;
169
- } ,
170
- ) *
171
- _ => { } ,
172
- }
173
- )
174
- }
175
-
176
- impl_options ! {
177
- match name. as_str( ) = lit {
178
- to_variant_with: syn:: Path ,
179
- from_variant_with: syn:: Path ,
180
- }
181
- }
182
-
183
- match name. as_str ( ) {
184
- "with" => {
185
- let path = match lit {
186
- syn:: Lit :: Str ( lit_str) => lit_str. parse :: < syn:: Path > ( ) ?,
187
- _ => {
188
- return Err ( syn:: Error :: new (
189
- lit. span ( ) ,
190
- "expecting a path to a module in double quotes: #[variant(with = \" path::to::mod\" )]" ,
191
- ) )
192
- }
193
- } ;
194
-
195
- if self
196
- . to_variant_with
197
- . replace ( parse_quote ! ( #path:: to_variant) )
198
- . is_some ( )
199
- {
200
- return Err ( syn:: Error :: new (
201
- lit. span ( ) ,
202
- "the argument to_variant_with is already set" ,
203
- ) ) ;
204
- }
205
-
206
- if self
207
- . from_variant_with
208
- . replace ( parse_quote ! ( #path:: from_variant) )
209
- . is_some ( )
210
- {
211
- return Err ( syn:: Error :: new (
212
- lit. span ( ) ,
213
- "the argument from_variant_with is already set" ,
214
- ) ) ;
215
- }
216
-
217
- return Ok ( ( ) ) ;
218
- }
219
- _ => { }
220
- }
221
-
222
- Err ( syn:: Error :: new (
223
- path. span ( ) ,
224
- format ! ( "unknown argument, expected one of:\n \t {}" , VALID_KEYS ) ,
225
- ) )
226
- }
82
+ pub trait AttrBuilder : FromIterator < syn:: Meta > {
83
+ type Attr ;
84
+ fn done ( self ) -> Result < Self :: Attr , syn:: Error > ;
227
85
}
228
86
229
- impl FromIterator < syn:: Meta > for AttrBuilder {
230
- fn from_iter < I > ( iter : I ) -> Self
231
- where
232
- I : IntoIterator < Item = syn:: Meta > ,
233
- {
234
- let mut builder = AttrBuilder :: default ( ) ;
235
- for meta in iter {
236
- builder. extend_meta ( & meta) ;
237
- }
238
- builder
239
- }
240
- }
241
-
242
- impl AttrBuilder {
243
- pub fn done ( mut self ) -> Result < Attr , syn:: Error > {
244
- if self . errors . is_empty ( ) {
245
- Ok ( Attr {
246
- skip_to_variant : self . skip_to_variant ,
247
- skip_from_variant : self . skip_from_variant ,
248
- to_variant_with : self . to_variant_with ,
249
- from_variant_with : self . from_variant_with ,
250
- } )
251
- } else {
252
- let first_error = self . errors . remove ( 0 ) ;
253
- let errors = self
254
- . errors
255
- . into_iter ( )
256
- . fold ( first_error, |mut errors, error| {
257
- errors. combine ( error) ;
258
- errors
259
- } ) ;
87
+ pub mod field;
88
+ pub mod item;
260
89
261
- Err ( errors)
262
- }
263
- }
264
- }
90
+ pub use field:: { FieldAttr , FieldAttrBuilder } ;
91
+ pub use item:: { ItemAttr , ItemAttrBuilder } ;
0 commit comments