@@ -82,7 +82,7 @@ pub(crate) fn hasher(input: ItemStruct) -> Result<TokenStream> {
82
82
. any ( |attr| attr. path ( ) . is_ident ( "flatten" ) )
83
83
} ) ;
84
84
85
- let mut flattned_fields_added = vec ! [ quote! { Self :: NUM_FIELDS as usize } ] ;
85
+ let mut flattned_fields_added = vec ! [ quote! { 0usize } ] ;
86
86
let mut truncate_code = Vec :: new ( ) ;
87
87
88
88
// Process each field
@@ -206,21 +206,37 @@ pub(crate) fn hasher(input: ItemStruct) -> Result<TokenStream> {
206
206
flattned_fields_added. push ( quote ! {
207
207
+ #field_type:: NUM_FIELDS as usize
208
208
} ) ;
209
+
210
+ // For flattened fields, we need to use their individual byte arrays directly
211
+ // rather than hashing the whole struct first
209
212
code. push ( quote ! {
210
213
{
211
- for ( j, element) in <#field_type as :: light_hasher:: to_byte_array:: ToByteArray >:: to_byte_arrays:: <{ #field_type:: NUM_FIELDS } >( & self . #field_name) ?. iter( ) . enumerate( ) {
212
- field_array[ #i + j + num_flattned_fields ] = * element;
213
- num_flattned_fields +=1 ;
214
+ // Get individual byte arrays from the flattened field
215
+ let flattened_arrays = <#field_type as :: light_hasher:: to_byte_array:: ToByteArray >:: to_byte_arrays:: <{ #field_type:: NUM_FIELDS } >( & self . #field_name) ?;
216
+ // Add each element individually to the field_array
217
+ for element in flattened_arrays. iter( ) {
218
+ field_array[ num_flattned_fields] = * element;
219
+ num_flattned_fields += 1 ;
214
220
}
215
221
}
216
222
} ) ;
217
223
} else {
224
+ if flatten_field_exists {
225
+ flattned_fields_added. push ( quote ! {
226
+ + 1
227
+ } ) ;
228
+ }
218
229
to_byte_arrays_fields. push ( quote ! {
219
230
arrays[ #i ] = self . #field_name. to_byte_array( ) ?;
220
231
} ) ;
221
232
if flatten_field_exists {
233
+ // Store field index in the field_assignments for later non-flattened field processing
222
234
field_assignments. push ( quote ! {
223
- field_array[ #i + num_flattned_fields ] = self . #field_name. to_byte_array( ) ?;
235
+ #i
236
+ } ) ;
237
+ code. push ( quote ! {
238
+ field_array[ num_flattned_fields] = self . #field_name. to_byte_array( ) ?;
239
+ num_flattned_fields += 1 ;
224
240
} ) ;
225
241
} else {
226
242
field_assignments. push ( quote ! {
@@ -242,8 +258,9 @@ pub(crate) fn hasher(input: ItemStruct) -> Result<TokenStream> {
242
258
} ,
243
259
) ;
244
260
code. push ( quote ! {
245
- for element in field_array. iter( ) {
246
- slices[ num_flattned_fields] = element. as_slice( ) ;
261
+ // Set all slices properly for both flattened and non-flattened fields
262
+ for i in 0 ..num_flattned_fields {
263
+ slices[ i] = field_array[ i] . as_slice( ) ;
247
264
}
248
265
} ) ;
249
266
quote ! {
@@ -310,9 +327,35 @@ pub(crate) fn hasher(input: ItemStruct) -> Result<TokenStream> {
310
327
}
311
328
} ;
312
329
330
+ // Calculate the total number of fields, accounting for flattened fields
331
+ let total_field_count = if flatten_field_exists {
332
+ // When there are flattened fields, we need to adjust the total field count
333
+ let mut sum = quote ! { 0 } ;
334
+
335
+ for field in fields. named . iter ( ) {
336
+ let flatten = field
337
+ . attrs
338
+ . iter ( )
339
+ . any ( |attr| attr. path ( ) . is_ident ( "flatten" ) ) ;
340
+
341
+ if flatten {
342
+ // Use the field type's NUM_FIELDS instead of counting as one field
343
+ let field_type = & field. ty ;
344
+ sum = quote ! { #sum + #field_type:: NUM_FIELDS } ;
345
+ } else {
346
+ // Regular fields count as one
347
+ sum = quote ! { #sum + 1 } ;
348
+ }
349
+ }
350
+ sum
351
+ } else {
352
+ // Without flattened fields, just use the regular field count
353
+ quote ! { #field_count }
354
+ } ;
355
+
313
356
Ok ( quote ! {
314
357
impl #impl_gen :: light_hasher:: to_byte_array:: ToByteArray for #struct_name #type_gen #where_clause {
315
- const NUM_FIELDS : usize = #field_count ;
358
+ const NUM_FIELDS : usize = #total_field_count ;
316
359
317
360
fn to_byte_array( & self ) -> :: std:: result:: Result <[ u8 ; 32 ] , :: light_hasher:: HasherError > {
318
361
#to_byte_array
0 commit comments