11use proc_macro2:: { Ident , Span , TokenStream } ;
22use quote:: { quote, ToTokens } ;
33use 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 } ;
57
68const FILLER : & str = "filler" ;
79const ATTRIBUTE : & str = "attribute" ;
810const EXTENDABLE : & str = "extendable" ;
11+ const EMPTY_VALUE : & str = "empty_value" ;
912
1013pub ( crate ) struct Filler {
1114 visibility : syn:: Visibility ,
@@ -16,18 +19,27 @@ pub(crate) struct Filler {
1619 fields : Vec < Field > ,
1720}
1821
19- #[ derive( Debug , PartialEq ) ]
2022enum FillerType {
2123 Option ,
24+ /// The type with `Default`, `Extend`, `IntoIterator` and `is_empty` implementations
2225 Extendable ( Ident ) ,
26+ /// The type defined a value for empty
27+ NativeValue ( Lit ) ,
2328}
2429
2530impl FillerType {
2631 fn inner ( & self ) -> & Ident {
2732 if let FillerType :: Extendable ( ident) = self {
2833 ident
2934 } else {
30- panic ! ( "FillerType::Option has no inner indent" )
35+ panic ! ( "Only FillerType::Extendable has inner indent" )
36+ }
37+ }
38+ fn value ( & self ) -> & Lit {
39+ if let FillerType :: NativeValue ( lit) = self {
40+ lit
41+ } else {
42+ panic ! ( "Only FillerType::NativeValue has value" )
3143 }
3244 }
3345}
@@ -58,7 +70,7 @@ impl Filler {
5870
5971 let option_field_names = fields
6072 . iter ( )
61- . filter ( |f| f. fty == FillerType :: Option )
73+ . filter ( |f| matches ! ( f. fty, FillerType :: Option ) )
6274 . map ( |f| f. ident . as_ref ( ) )
6375 . collect :: < Vec < _ > > ( ) ;
6476
@@ -74,6 +86,18 @@ impl Filler {
7486 . map ( |f| f. fty . inner ( ) )
7587 . collect :: < Vec < _ > > ( ) ;
7688
89+ let native_value_field_names = fields
90+ . iter ( )
91+ . filter ( |f| matches ! ( f. fty, FillerType :: NativeValue ( _) ) )
92+ . map ( |f| f. ident . as_ref ( ) )
93+ . collect :: < Vec < _ > > ( ) ;
94+
95+ let native_value_field_values = fields
96+ . iter ( )
97+ . filter ( |f| matches ! ( f. fty, FillerType :: NativeValue ( _) ) )
98+ . map ( |f| f. fty . value ( ) )
99+ . collect :: < Vec < _ > > ( ) ;
100+
77101 let mapped_attributes = attributes
78102 . iter ( )
79103 . map ( |a| {
@@ -105,6 +129,11 @@ impl Filler {
105129 return false
106130 }
107131 ) *
132+ #(
133+ if self . #native_value_field_names != #native_value_field_values {
134+ return false
135+ }
136+ ) *
108137 true
109138 }
110139 }
@@ -115,6 +144,11 @@ impl Filler {
115144 let filler_impl = quote ! {
116145 impl #generics struct_patch:: traits:: Filler < #name #generics > for #struct_name #generics #where_clause {
117146 fn apply( & mut self , filler: #name #generics) {
147+ #(
148+ if self . #native_value_field_names == #native_value_field_values {
149+ self . #native_value_field_names = filler. #native_value_field_names;
150+ }
151+ ) *
118152 #(
119153 if self . #extendable_field_names. is_empty( ) {
120154 self . #extendable_field_names. extend( filler. #extendable_field_names. into_iter( ) ) ;
@@ -133,6 +167,7 @@ impl Filler {
133167 #name {
134168 #( #option_field_names: None , ) *
135169 #( #extendable_field_names: #extendable_field_types:: default ( ) , ) *
170+ #( #native_value_field_names: #native_value_field_values, ) *
136171 }
137172 }
138173 }
@@ -282,7 +317,24 @@ impl Field {
282317 }
283318 EXTENDABLE => {
284319 // #[filler(extendable)]
285- fty = Some ( FillerType :: Extendable ( extendable_filler_type ( & ty) ) ) ;
320+ if fty. is_some ( ) {
321+ return Err ( meta
322+ . error ( "The field is already the field of filler, we can't defined more than once" ) ) ;
323+ }
324+ fty = Some ( FillerType :: Extendable ( none_option_filler_type ( & ty) ) ) ;
325+ }
326+ EMPTY_VALUE => {
327+ // #[filler(empty_value=some value)]
328+ if fty. is_some ( ) {
329+ return Err ( meta
330+ . error ( "The field is already the field of filler, we can't defined more than once" ) ) ;
331+ }
332+ if let Some ( lit) = get_lit ( path, & meta) ? {
333+ fty = Some ( FillerType :: NativeValue ( lit) ) ;
334+ } else {
335+ return Err ( meta
336+ . error ( "empty_value needs a clear value to define empty" ) ) ;
337+ }
286338 }
287339 _ => {
288340 return Err ( meta. error ( format_args ! (
@@ -342,10 +394,29 @@ fn filler_type(ty: &Type) -> Option<FillerType> {
342394 None
343395}
344396
345- fn extendable_filler_type ( ty : & Type ) -> Ident {
397+ fn none_option_filler_type ( ty : & Type ) -> Ident {
346398 if let Type :: Path ( type_path) = ty {
347399 type_path. path . segments [ 0 ] . ident . clone ( )
348400 } else {
349401 panic ! ( "#[filler(extendable)] should use on a type" )
350402 }
351403}
404+
405+ fn get_lit ( attr_name : String , meta : & ParseNestedMeta ) -> syn:: Result < Option < syn:: Lit > > {
406+ let expr: syn:: Expr = meta. value ( ) ?. parse ( ) ?;
407+ let mut value = & expr;
408+ while let syn:: Expr :: Group ( e) = value {
409+ value = & e. expr ;
410+ }
411+ if let syn:: Expr :: Lit ( syn:: ExprLit { lit, .. } ) = value {
412+ Ok ( Some ( lit. clone ( ) ) )
413+ } else {
414+ Err ( Error :: new (
415+ expr. span ( ) ,
416+ format ! (
417+ "expected serde {} attribute to be lit: `{} = \" ...\" `" ,
418+ attr_name, attr_name
419+ ) ,
420+ ) )
421+ }
422+ }
0 commit comments