@@ -5,6 +5,7 @@ use syn::{parenthesized, DeriveInput, LitStr, Result, Type};
55
66const FILLER : & str = "filler" ;
77const ATTRIBUTE : & str = "attribute" ;
8+ const EXTENDABLE : & str = "extendable" ;
89
910pub ( crate ) struct Filler {
1011 visibility : syn:: Visibility ,
@@ -18,7 +19,17 @@ pub(crate) struct Filler {
1819#[ derive( Debug , PartialEq ) ]
1920enum FillerType {
2021 Option ,
21- Vec ,
22+ Extendable ( Ident ) ,
23+ }
24+
25+ impl FillerType {
26+ fn inner ( & self ) -> & Ident {
27+ if let FillerType :: Extendable ( ident) = self {
28+ ident
29+ } else {
30+ panic ! ( "FillerType::Option has no inner indent" )
31+ }
32+ }
2233}
2334
2435struct Field {
@@ -45,18 +56,24 @@ impl Filler {
4556 . map ( |f| f. to_token_stream ( ) )
4657 . collect :: < Result < Vec < _ > > > ( ) ?;
4758
48- let vector_field_names = fields
59+ let option_field_names = fields
4960 . iter ( )
50- . filter ( |f| f. fty == FillerType :: Vec )
61+ . filter ( |f| f. fty == FillerType :: Option )
5162 . map ( |f| f. ident . as_ref ( ) )
5263 . collect :: < Vec < _ > > ( ) ;
5364
54- let option_field_names = fields
65+ let extendable_field_names = fields
5566 . iter ( )
56- . filter ( |f| f. fty == FillerType :: Option )
67+ . filter ( |f| matches ! ( f. fty, FillerType :: Extendable ( _ ) ) )
5768 . map ( |f| f. ident . as_ref ( ) )
5869 . collect :: < Vec < _ > > ( ) ;
5970
71+ let extendable_field_types = fields
72+ . iter ( )
73+ . filter ( |f| matches ! ( f. fty, FillerType :: Extendable ( _) ) )
74+ . map ( |f| f. fty . inner ( ) )
75+ . collect :: < Vec < _ > > ( ) ;
76+
6077 let mapped_attributes = attributes
6178 . iter ( )
6279 . map ( |a| {
@@ -84,7 +101,7 @@ impl Filler {
84101 }
85102 ) *
86103 #(
87- if !self . #vector_field_names . is_empty( ) {
104+ if !self . #extendable_field_names . is_empty( ) {
88105 return false
89106 }
90107 ) *
@@ -99,7 +116,9 @@ impl Filler {
99116 impl #generics struct_patch:: traits:: Filler < #name #generics > for #struct_name #generics #where_clause {
100117 fn apply( & mut self , filler: #name #generics) {
101118 #(
102- self . #vector_field_names. extend( filler. #vector_field_names. iter( ) ) ;
119+ if self . #extendable_field_names. is_empty( ) {
120+ self . #extendable_field_names. extend( filler. #extendable_field_names. into_iter( ) ) ;
121+ }
103122 ) *
104123 #(
105124 if let Some ( v) = filler. #option_field_names {
@@ -113,7 +132,7 @@ impl Filler {
113132 fn new_empty_filler( ) -> #name #generics {
114133 #name {
115134 #( #option_field_names: None , ) *
116- #( #vector_field_names : Vec :: new ( ) , ) *
135+ #( #extendable_field_names : #extendable_field_types :: default ( ) , ) *
117136 }
118137 }
119138 }
@@ -237,12 +256,7 @@ impl Field {
237256 ident, ty, attrs, ..
238257 } : syn:: Field ,
239258 ) -> Result < Option < Field > > {
240- let fty = if let Some ( fty) = filler_type ( & ty) {
241- fty
242- } else {
243- return Ok ( None ) ;
244- } ;
245-
259+ let mut fty = filler_type ( & ty) ;
246260 let mut attributes = vec ! [ ] ;
247261
248262 for attr in attrs {
@@ -266,6 +280,10 @@ impl Field {
266280 let attribute: TokenStream = content. parse ( ) ?;
267281 attributes. push ( attribute) ;
268282 }
283+ EXTENDABLE => {
284+ // #[filler(extendable)]
285+ fty = Some ( FillerType :: Extendable ( extendable_filler_type ( & ty) ) ) ;
286+ }
269287 _ => {
270288 return Err ( meta. error ( format_args ! (
271289 "unknown filler field attribute `{}`" ,
@@ -277,7 +295,7 @@ impl Field {
277295 } ) ?;
278296 }
279297
280- Ok ( Some ( Field {
298+ Ok ( fty . map ( |fty| Field {
281299 ident,
282300 ty,
283301 attributes,
@@ -305,13 +323,29 @@ fn filler_type(ty: &Type) -> Option<FillerType> {
305323 return Some ( FillerType :: Option ) ;
306324 }
307325 }
308- } else if segments. len ( ) == 1 && segments[ 0 ] . ident == "Vec" {
326+ } else if segments. len ( ) == 1 && segments[ 0 ] . ident == "Vec"
327+ || segments[ 0 ] . ident == "VecDeque"
328+ || segments[ 0 ] . ident == "LinkedList"
329+ || segments[ 0 ] . ident == "HashMap"
330+ || segments[ 0 ] . ident == "BTreeMap"
331+ || segments[ 0 ] . ident == "HashSet"
332+ || segments[ 0 ] . ident == "BTreeSet"
333+ || segments[ 0 ] . ident == "BinaryHeap"
334+ {
309335 if let syn:: PathArguments :: AngleBracketed ( args) = & segments[ 0 ] . arguments {
310336 if args. args . len ( ) == 1 {
311- return Some ( FillerType :: Vec ) ;
337+ return Some ( FillerType :: Extendable ( segments [ 0 ] . ident . clone ( ) ) ) ;
312338 }
313339 }
314340 }
315341 }
316342 None
317343}
344+
345+ fn extendable_filler_type ( ty : & Type ) -> Ident {
346+ if let Type :: Path ( type_path) = ty {
347+ type_path. path . segments [ 0 ] . ident . clone ( )
348+ } else {
349+ panic ! ( "#[filler(extendable)] should use on a type" )
350+ }
351+ }
0 commit comments