1- use anyhow:: { bail, Error } ;
1+ use anyhow:: { bail, Error } ;
22use proc_macro2:: TokenStream ;
33use quote:: quote;
4- use syn:: { Meta , Lit , MetaNameValue , Path , Expr , ExprLit } ;
4+ use syn:: { Expr , ExprLit , Lit , Meta , MetaNameValue , Path } ;
55
6- use crate :: field:: { set_bool, word_attr} ;
6+ use crate :: field:: { set_bool, set_option , word_attr} ;
77
88#[ derive( Clone ) ]
99pub struct Field {
@@ -14,28 +14,21 @@ impl Field {
1414 pub fn new ( attrs : & [ Meta ] ) -> Result < Option < Field > , Error > {
1515 let mut skip = false ;
1616 let mut default_fn = None ;
17+ let mut default_lit = None ;
1718 let mut unknown_attrs = Vec :: new ( ) ;
1819
1920 for attr in attrs {
2021 if word_attr ( "skip" , attr) {
2122 set_bool ( & mut skip, "duplicate skip attribute" ) ?;
2223 } else if let Meta :: NameValue ( MetaNameValue { path, value, .. } ) = attr {
2324 if path. is_ident ( "default" ) {
24- let lit_str = match value {
25+ match value {
2526 // There has to be a better way...
26- Expr :: Lit ( ExprLit { lit : Lit :: Str ( lit) , .. } ) => Some ( lit) ,
27- _ => None ,
27+ Expr :: Lit ( ExprLit {
28+ lit : Lit :: Str ( lit) , ..
29+ } ) => set_option ( & mut default_lit, lit, "duplicate default attributes" ) ?,
30+ _ => bail ! ( "default attribute value must be a string literal" ) ,
2831 } ;
29- if let Some ( lit) = lit_str {
30- let fn_path: Path = syn:: parse_str ( & lit. value ( ) )
31- . map_err ( |_| anyhow:: anyhow!( "invalid path for default function" ) ) ?;
32- if default_fn. is_some ( ) {
33- bail ! ( "duplicate default attribute for skipped field" ) ;
34- }
35- default_fn = Some ( fn_path) ;
36- } else {
37- bail ! ( "default attribute value must be a string literal" ) ;
38- }
3932 } else {
4033 unknown_attrs. push ( attr) ;
4134 }
@@ -55,6 +48,15 @@ impl Field {
5548 ) ;
5649 }
5750
51+ if let Some ( lit) = default_lit {
52+ let fn_path: Path = syn:: parse_str ( & lit. value ( ) )
53+ . map_err ( |_| anyhow:: anyhow!( "invalid path for default function" ) ) ?;
54+ if default_fn. is_some ( ) {
55+ bail ! ( "duplicate default attribute for skipped field" ) ;
56+ }
57+ default_fn = Some ( fn_path) ;
58+ }
59+
5860 Ok ( Some ( Field { default_fn } ) )
5961 }
6062
@@ -70,4 +72,4 @@ impl Field {
7072 quote ! { :: core:: default :: Default :: default ( ) }
7173 }
7274 }
73- }
75+ }
0 commit comments