@@ -250,6 +250,17 @@ func (d *decoder) unmarshalMap(size uint, offset uint, result reflect.Value) (ui
250
250
newOffset , err := d .decodeMap (size , offset , rv )
251
251
result .Set (rv )
252
252
return newOffset , err
253
+ case reflect .Ptr :
254
+ // XXX - This duplicate Ptr hanlding code exists because decodeMap
255
+ // calls unmarshalMap directly when handling embeded structs. It
256
+ // would be nice to clean this up.
257
+ for result .Kind () == reflect .Ptr {
258
+ if result .IsNil () {
259
+ result .Set (reflect .New (result .Type ().Elem ()))
260
+ }
261
+ result = result .Elem ()
262
+ }
263
+ return d .unmarshalMap (size , offset , result )
253
264
}
254
265
}
255
266
@@ -450,8 +461,13 @@ func (d *decoder) decodeString(size uint, offset uint) (string, uint, error) {
450
461
return string (d .buffer [offset :newOffset ]), newOffset , nil
451
462
}
452
463
464
+ type fieldsType struct {
465
+ namedFields map [string ]int
466
+ anonymousFields []int
467
+ }
468
+
453
469
var (
454
- fieldMap = map [reflect.Type ]map [ string ] int {}
470
+ fieldMap = map [reflect.Type ]* fieldsType {}
455
471
fieldMapMu sync.RWMutex
456
472
)
457
473
@@ -463,21 +479,39 @@ func (d *decoder) decodeStruct(size uint, offset uint, result reflect.Value) (ui
463
479
fieldMapMu .RUnlock ()
464
480
if ! ok {
465
481
numFields := resultType .NumField ()
466
- fields = make (map [string ]int , numFields )
482
+ namedFields := make (map [string ]int , numFields )
483
+ var anonymous []int
467
484
for i := 0 ; i < numFields ; i ++ {
468
- fieldType := resultType .Field (i )
485
+ field := resultType .Field (i )
469
486
470
- fieldName := fieldType .Name
471
- if tag := fieldType .Tag .Get ("maxminddb" ); tag != "" {
487
+ fieldName := field .Name
488
+ if tag := field .Tag .Get ("maxminddb" ); tag != "" {
489
+ if tag == "-" {
490
+ continue
491
+ }
472
492
fieldName = tag
473
493
}
474
- fields [fieldName ] = i
494
+ if field .Anonymous {
495
+ anonymous = append (anonymous , i )
496
+ continue
497
+ }
498
+ namedFields [fieldName ] = i
475
499
}
476
500
fieldMapMu .Lock ()
501
+ fields = & fieldsType {namedFields , anonymous }
477
502
fieldMap [resultType ] = fields
478
503
fieldMapMu .Unlock ()
479
504
}
480
505
506
+ // This fills in embedded structs
507
+ for i := range fields .anonymousFields {
508
+ _ , err := d .unmarshalMap (size , offset , result .Field (i ))
509
+ if err != nil {
510
+ return 0 , err
511
+ }
512
+ }
513
+
514
+ // This handles named fields
481
515
for i := uint (0 ); i < size ; i ++ {
482
516
var (
483
517
err error
@@ -487,12 +521,13 @@ func (d *decoder) decodeStruct(size uint, offset uint, result reflect.Value) (ui
487
521
if err != nil {
488
522
return 0 , err
489
523
}
490
- i , ok := fields [key ]
524
+ j , ok := fields . namedFields [key ]
491
525
if ! ok {
492
526
offset = d .nextValueOffset (offset , 1 )
493
527
continue
494
528
}
495
- offset , err = d .decode (offset , result .Field (i ))
529
+
530
+ offset , err = d .decode (offset , result .Field (j ))
496
531
if err != nil {
497
532
return 0 , err
498
533
}
0 commit comments