1
1
use proc_macro2:: { Ident , Span , TokenStream } ;
2
2
use quote:: { quote, ToTokens } ;
3
3
use std:: str:: FromStr ;
4
- use syn:: { parenthesized, DeriveInput , LitStr , Result , Type } ;
4
+ use syn:: meta:: ParseNestedMeta ;
5
+ use syn:: spanned:: Spanned ;
6
+ use syn:: { parenthesized, DeriveInput , Error , Lit , LitStr , Result , Type } ;
5
7
6
8
const FILLER : & str = "filler" ;
7
9
const ATTRIBUTE : & str = "attribute" ;
8
10
const EXTENDABLE : & str = "extendable" ;
11
+ const EMPTY_VALUE : & str = "empty_value" ;
9
12
10
13
pub ( crate ) struct Filler {
11
14
visibility : syn:: Visibility ,
@@ -16,18 +19,28 @@ pub(crate) struct Filler {
16
19
fields : Vec < Field > ,
17
20
}
18
21
19
- #[ derive( Debug , PartialEq ) ]
22
+ #[ derive( PartialEq ) ]
20
23
enum FillerType {
21
24
Option ,
25
+ /// The type with `Default`, `Extend`, `IntoIterator` and `is_empty` implementations
22
26
Extendable ( Ident ) ,
27
+ /// The type defined a value for empty
28
+ NativeValue ( Lit ) ,
23
29
}
24
30
25
31
impl FillerType {
26
32
fn inner ( & self ) -> & Ident {
27
33
if let FillerType :: Extendable ( ident) = self {
28
34
ident
29
35
} else {
30
- panic ! ( "FillerType::Option has no inner indent" )
36
+ panic ! ( "Only FillerType::Extendable has inner indent" )
37
+ }
38
+ }
39
+ fn value ( & self ) -> & Lit {
40
+ if let FillerType :: NativeValue ( lit) = self {
41
+ lit
42
+ } else {
43
+ panic ! ( "Only FillerType::NativeValue has value" )
31
44
}
32
45
}
33
46
}
@@ -74,6 +87,18 @@ impl Filler {
74
87
. map ( |f| f. fty . inner ( ) )
75
88
. collect :: < Vec < _ > > ( ) ;
76
89
90
+ let native_value_field_names = fields
91
+ . iter ( )
92
+ . filter ( |f| matches ! ( f. fty, FillerType :: NativeValue ( _) ) )
93
+ . map ( |f| f. ident . as_ref ( ) )
94
+ . collect :: < Vec < _ > > ( ) ;
95
+
96
+ let native_value_field_values = fields
97
+ . iter ( )
98
+ . filter ( |f| matches ! ( f. fty, FillerType :: NativeValue ( _) ) )
99
+ . map ( |f| f. fty . value ( ) )
100
+ . collect :: < Vec < _ > > ( ) ;
101
+
77
102
let mapped_attributes = attributes
78
103
. iter ( )
79
104
. map ( |a| {
@@ -105,6 +130,11 @@ impl Filler {
105
130
return false
106
131
}
107
132
) *
133
+ #(
134
+ if self . #native_value_field_names != #native_value_field_values {
135
+ return false
136
+ }
137
+ ) *
108
138
true
109
139
}
110
140
}
@@ -115,6 +145,11 @@ impl Filler {
115
145
let filler_impl = quote ! {
116
146
impl #generics struct_patch:: traits:: Filler < #name #generics > for #struct_name #generics #where_clause {
117
147
fn apply( & mut self , filler: #name #generics) {
148
+ #(
149
+ if self . #native_value_field_names == #native_value_field_values {
150
+ self . #native_value_field_names = filler. #native_value_field_names;
151
+ }
152
+ ) *
118
153
#(
119
154
if self . #extendable_field_names. is_empty( ) {
120
155
self . #extendable_field_names. extend( filler. #extendable_field_names. into_iter( ) ) ;
@@ -133,6 +168,7 @@ impl Filler {
133
168
#name {
134
169
#( #option_field_names: None , ) *
135
170
#( #extendable_field_names: #extendable_field_types:: default ( ) , ) *
171
+ #( #native_value_field_names: #native_value_field_values, ) *
136
172
}
137
173
}
138
174
}
@@ -282,7 +318,24 @@ impl Field {
282
318
}
283
319
EXTENDABLE => {
284
320
// #[filler(extendable)]
285
- fty = Some ( FillerType :: Extendable ( extendable_filler_type ( & ty) ) ) ;
321
+ if fty. is_some ( ) {
322
+ return Err ( meta
323
+ . error ( "The field is already the field of filler, we can't defined more than once" ) ) ;
324
+ }
325
+ fty = Some ( FillerType :: Extendable ( none_option_filler_type ( & ty) ) ) ;
326
+ }
327
+ EMPTY_VALUE => {
328
+ // #[filler(empty_value=some value)]
329
+ if fty. is_some ( ) {
330
+ return Err ( meta
331
+ . error ( "The field is already the field of filler, we can't defined more than once" ) ) ;
332
+ }
333
+ if let Some ( lit) = get_lit ( path, & meta) ? {
334
+ fty = Some ( FillerType :: NativeValue ( lit) ) ;
335
+ } else {
336
+ return Err ( meta
337
+ . error ( "empty_value needs a clear value to define empty" ) ) ;
338
+ }
286
339
}
287
340
_ => {
288
341
return Err ( meta. error ( format_args ! (
@@ -342,10 +395,29 @@ fn filler_type(ty: &Type) -> Option<FillerType> {
342
395
None
343
396
}
344
397
345
- fn extendable_filler_type ( ty : & Type ) -> Ident {
398
+ fn none_option_filler_type ( ty : & Type ) -> Ident {
346
399
if let Type :: Path ( type_path) = ty {
347
400
type_path. path . segments [ 0 ] . ident . clone ( )
348
401
} else {
349
402
panic ! ( "#[filler(extendable)] should use on a type" )
350
403
}
351
404
}
405
+
406
+ fn get_lit ( attr_name : String , meta : & ParseNestedMeta ) -> syn:: Result < Option < syn:: Lit > > {
407
+ let expr: syn:: Expr = meta. value ( ) ?. parse ( ) ?;
408
+ let mut value = & expr;
409
+ while let syn:: Expr :: Group ( e) = value {
410
+ value = & e. expr ;
411
+ }
412
+ if let syn:: Expr :: Lit ( syn:: ExprLit { lit, .. } ) = value {
413
+ Ok ( Some ( lit. clone ( ) ) )
414
+ } else {
415
+ Err ( Error :: new (
416
+ expr. span ( ) ,
417
+ format ! (
418
+ "expected serde {} attribute to be lit: `{} = \" ...\" `" ,
419
+ attr_name, attr_name
420
+ ) ,
421
+ ) )
422
+ }
423
+ }
0 commit comments