@@ -24,6 +24,13 @@ struct StructAttrs {
2424 // This annotation only works if `enforce_order` is specified.
2525 #[ darling( default ) ]
2626 skip_name_checks : bool ,
27+
28+ // If true, then - if this field is missing from the UDT fields metadata
29+ // - it will be initialized to Default::default().
30+ // currently only supported with Flavor::MatchByName
31+ #[ darling( default ) ]
32+ #[ darling( rename = "allow_missing" ) ]
33+ default_when_missing : bool ,
2734}
2835
2936impl DeserializeCommonStructAttrs for StructAttrs {
@@ -51,6 +58,13 @@ struct Field {
5158 #[ darling( default ) ]
5259 default_when_null : bool ,
5360
61+ // If true, then - if this field is missing from the UDT fields metadata
62+ // - it will be initialized to Default::default().
63+ // currently only supported with Flavor::MatchByName
64+ #[ darling( default ) ]
65+ #[ darling( rename = "allow_missing" ) ]
66+ default_when_missing : bool ,
67+
5468 ident : Option < syn:: Ident > ,
5569 ty : syn:: Type ,
5670}
@@ -135,7 +149,7 @@ fn validate_attrs(attrs: &StructAttrs, fields: &[Field]) -> Result<(), darling::
135149impl Field {
136150 // Returns whether this field is mandatory for deserialization.
137151 fn is_required ( & self ) -> bool {
138- !self . skip
152+ !self . skip && ! self . default_when_missing
139153 }
140154
141155 // The name of the column corresponding to this Rust struct field
@@ -209,13 +223,7 @@ impl TypeCheckAssumeOrderGenerator<'_> {
209223 let macro_internal = self . 0 . struct_attrs ( ) . macro_internal_path ( ) ;
210224 let ( frame_lifetime, metadata_lifetime) = self . 0 . constraint_lifetimes ( ) ;
211225
212- let required_fields_iter = || {
213- self . 0
214- . fields ( )
215- . iter ( )
216- . enumerate ( )
217- . filter ( |( _, f) | f. is_required ( ) )
218- } ;
226+ let required_fields_iter = || self . 0 . fields ( ) . iter ( ) . enumerate ( ) . filter ( |( _, f) | !f. skip ) ;
219227 let required_fields_count = required_fields_iter ( ) . count ( ) ;
220228 let required_fields_idents: Vec < _ > = ( 0 ..required_fields_count)
221229 . map ( |i| quote:: format_ident!( "f_{}" , i) )
@@ -394,7 +402,7 @@ impl TypeCheckUnorderedGenerator<'_> {
394402 let visited_flag = Self :: visited_flag_variable ( field) ;
395403 let typ = field. deserialize_target ( ) ;
396404 let cql_name_literal = field. cql_name_literal ( ) ;
397- let decrement_if_required: Option :: < syn:: Stmt > = field. is_required ( ) . then ( || parse_quote ! {
405+ let decrement_if_required: Option :: < syn:: Stmt > = ( ! self . 0 . attrs . default_when_missing && field. is_required ( ) ) . then ( || parse_quote ! {
398406 remaining_required_fields -= 1 ;
399407 } ) ;
400408
@@ -467,7 +475,11 @@ impl TypeCheckUnorderedGenerator<'_> {
467475 . iter ( )
468476 . filter ( |f| !f. skip )
469477 . map ( |f| f. cql_name_literal ( ) ) ;
470- let field_count_lit = fields. iter ( ) . filter ( |f| f. is_required ( ) ) . count ( ) ;
478+ let field_count_lit = if self . 0 . attrs . default_when_missing {
479+ 0
480+ } else {
481+ fields. iter ( ) . filter ( |f| f. is_required ( ) ) . count ( )
482+ } ;
471483
472484 parse_quote ! {
473485 fn type_check(
@@ -541,11 +553,18 @@ impl DeserializeUnorderedGenerator<'_> {
541553
542554 let deserialize_field = Self :: deserialize_field_variable ( field) ;
543555 let cql_name_literal = field. cql_name_literal ( ) ;
544- parse_quote ! {
545- #deserialize_field. unwrap_or_else( || :: std:: panic!(
546- "column {} missing in DB row - type check should have prevented this!" ,
547- #cql_name_literal
548- ) )
556+ if self . 0 . attrs . default_when_missing || field. default_when_missing {
557+ // Generate Default::default if the field was missing
558+ parse_quote ! {
559+ #deserialize_field. unwrap_or_default( )
560+ }
561+ } else {
562+ parse_quote ! {
563+ #deserialize_field. unwrap_or_else( || :: std:: panic!(
564+ "column {} missing in DB row - type check should have prevented this!" ,
565+ #cql_name_literal
566+ ) )
567+ }
549568 }
550569 }
551570
0 commit comments