@@ -11,6 +11,7 @@ use syn::NestedMeta::*;
11
11
struct Generate < ' a > {
12
12
context : & ' a Context ,
13
13
attrs : & ' a FieldAttrs ,
14
+ protocol : & ' a FieldProtocol ,
14
15
ident : & ' a syn:: Ident ,
15
16
field : & ' a syn:: Field ,
16
17
field_ident : & ' a syn:: Ident ,
@@ -20,6 +21,7 @@ struct Generate<'a> {
20
21
21
22
pub ( crate ) struct FieldProtocol {
22
23
generate : fn ( Generate < ' _ > ) -> TokenStream ,
24
+ custom : Option < syn:: Path > ,
23
25
}
24
26
25
27
/// Parsed field attributes.
@@ -148,10 +150,16 @@ impl Context {
148
150
149
151
let protocol = g. context. protocol( $proto) ;
150
152
151
- quote_spanned! { g. field. span( ) =>
152
- module. field_fn( #protocol, #name, |s: & mut #ident, value: #ty| {
153
- s. #field_ident $op value;
154
- } ) ?;
153
+ if let Some ( custom) = & g. protocol. custom {
154
+ quote_spanned! { g. field. span( ) =>
155
+ module. field_fn( #protocol, #name, #custom) ?;
156
+ }
157
+ } else {
158
+ quote_spanned! { g. field. span( ) =>
159
+ module. field_fn( #protocol, #name, |s: & mut #ident, value: #ty| {
160
+ s. #field_ident $op value;
161
+ } ) ?;
162
+ }
155
163
}
156
164
}
157
165
} ;
@@ -162,8 +170,12 @@ impl Context {
162
170
for attr in attrs {
163
171
for meta in self . get_rune_meta_items ( attr) ? {
164
172
match meta {
165
- Meta ( Path ( path) ) if path == GET => {
173
+ Meta ( Path ( path) ) if path == COPY => {
174
+ output. copy = true ;
175
+ }
176
+ Meta ( meta) if meta. path ( ) == GET => {
166
177
output. protocols . push ( FieldProtocol {
178
+ custom : self . parse_field_custom ( meta) ?,
167
179
generate : |g| {
168
180
let Generate {
169
181
ident,
@@ -186,8 +198,9 @@ impl Context {
186
198
} ,
187
199
} ) ;
188
200
}
189
- Meta ( Path ( path ) ) if path == SET => {
201
+ Meta ( meta ) if meta . path ( ) == SET => {
190
202
output. protocols . push ( FieldProtocol {
203
+ custom : self . parse_field_custom ( meta) ?,
191
204
generate : |g| {
192
205
let Generate {
193
206
ident,
@@ -207,53 +220,65 @@ impl Context {
207
220
} ,
208
221
} ) ;
209
222
}
210
- Meta ( Path ( path ) ) if path == ADD_ASSIGN => {
223
+ Meta ( meta ) if meta . path ( ) == ADD_ASSIGN => {
211
224
output. protocols . push ( FieldProtocol {
225
+ custom : self . parse_field_custom ( meta) ?,
212
226
generate : generate_op ! ( PROTOCOL_ADD_ASSIGN , +=) ,
213
227
} ) ;
214
228
}
215
- Meta ( Path ( path ) ) if path == SUB_ASSIGN => {
229
+ Meta ( meta ) if meta . path ( ) == SUB_ASSIGN => {
216
230
output. protocols . push ( FieldProtocol {
231
+ custom : self . parse_field_custom ( meta) ?,
217
232
generate : generate_op ! ( PROTOCOL_SUB_ASSIGN , -=) ,
218
233
} ) ;
219
234
}
220
- Meta ( Path ( path ) ) if path == DIV_ASSIGN => {
235
+ Meta ( meta ) if meta . path ( ) == DIV_ASSIGN => {
221
236
output. protocols . push ( FieldProtocol {
237
+ custom : self . parse_field_custom ( meta) ?,
222
238
generate : generate_op ! ( PROTOCOL_DIV_ASSIGN , /=) ,
223
239
} ) ;
224
240
}
225
- Meta ( Path ( path ) ) if path == MUL_ASSIGN => {
241
+ Meta ( meta ) if meta . path ( ) == MUL_ASSIGN => {
226
242
output. protocols . push ( FieldProtocol {
243
+ custom : self . parse_field_custom ( meta) ?,
227
244
generate : generate_op ! ( PROTOCOL_MUL_ASSIGN , *=) ,
228
245
} ) ;
229
246
}
230
- Meta ( Path ( path ) ) if path == BIT_AND_ASSIGN => {
247
+ Meta ( meta ) if meta . path ( ) == BIT_AND_ASSIGN => {
231
248
output. protocols . push ( FieldProtocol {
249
+ custom : self . parse_field_custom ( meta) ?,
232
250
generate : generate_op ! ( PROTOCOL_BIT_AND_ASSIGN , &=) ,
233
251
} ) ;
234
252
}
235
- Meta ( Path ( path ) ) if path == BIT_OR_ASSIGN => {
253
+ Meta ( meta ) if meta . path ( ) == BIT_OR_ASSIGN => {
236
254
output. protocols . push ( FieldProtocol {
255
+ custom : self . parse_field_custom ( meta) ?,
237
256
generate : generate_op ! ( PROTOCOL_BIT_OR_ASSIGN , |=) ,
238
257
} ) ;
239
258
}
240
- Meta ( Path ( path ) ) if path == BIT_XOR_ASSIGN => {
259
+ Meta ( meta ) if meta . path ( ) == BIT_XOR_ASSIGN => {
241
260
output. protocols . push ( FieldProtocol {
261
+ custom : self . parse_field_custom ( meta) ?,
242
262
generate : generate_op ! ( PROTOCOL_BIT_XOR_ASSIGN , ^=) ,
243
263
} ) ;
244
264
}
245
- Meta ( Path ( path ) ) if path == SHL_ASSIGN => {
265
+ Meta ( meta ) if meta . path ( ) == SHL_ASSIGN => {
246
266
output. protocols . push ( FieldProtocol {
267
+ custom : self . parse_field_custom ( meta) ?,
247
268
generate : generate_op ! ( PROTOCOL_SHL_ASSIGN , <<=) ,
248
269
} ) ;
249
270
}
250
- Meta ( Path ( path ) ) if path == SHR_ASSIGN => {
271
+ Meta ( meta ) if meta . path ( ) == SHR_ASSIGN => {
251
272
output. protocols . push ( FieldProtocol {
273
+ custom : self . parse_field_custom ( meta) ?,
252
274
generate : generate_op ! ( PROTOCOL_SHR_ASSIGN , >>=) ,
253
275
} ) ;
254
276
}
255
- Meta ( Path ( path) ) if path == COPY => {
256
- output. copy = true ;
277
+ Meta ( meta) if meta. path ( ) == REM_ASSIGN => {
278
+ output. protocols . push ( FieldProtocol {
279
+ custom : self . parse_field_custom ( meta) ?,
280
+ generate : generate_op ! ( PROTOCOL_REM_ASSIGN , %=) ,
281
+ } ) ;
257
282
}
258
283
_ => {
259
284
self . errors
@@ -268,6 +293,30 @@ impl Context {
268
293
Some ( output)
269
294
}
270
295
296
+ /// Parse path to custom field function.
297
+ fn parse_field_custom ( & mut self , meta : syn:: Meta ) -> Option < Option < syn:: Path > > {
298
+ let s = match meta {
299
+ Path ( ..) => return Some ( None ) ,
300
+ NameValue ( syn:: MetaNameValue {
301
+ lit : syn:: Lit :: Str ( s) ,
302
+ ..
303
+ } ) => s,
304
+ _ => {
305
+ self . errors
306
+ . push ( syn:: Error :: new ( meta. span ( ) , "unsupported meta" ) ) ;
307
+ return None ;
308
+ }
309
+ } ;
310
+
311
+ match s. parse_with ( syn:: Path :: parse_mod_style) {
312
+ Ok ( path) => Some ( Some ( path) ) ,
313
+ Err ( error) => {
314
+ self . errors . push ( error) ;
315
+ None
316
+ }
317
+ }
318
+ }
319
+
271
320
/// Parse field attributes.
272
321
pub ( crate ) fn parse_derive_attrs ( & mut self , attrs : & [ syn:: Attribute ] ) -> Option < DeriveAttrs > {
273
322
let mut output = DeriveAttrs :: default ( ) ;
@@ -328,6 +377,7 @@ impl Context {
328
377
for protocol in & attrs. protocols {
329
378
installers. push ( ( protocol. generate ) ( Generate {
330
379
context : self ,
380
+ protocol,
331
381
attrs : & attrs,
332
382
ident,
333
383
field,
0 commit comments