@@ -250,6 +250,17 @@ func (d *decoder) unmarshalMap(size uint, offset uint, result reflect.Value) (ui
250250 newOffset , err := d .decodeMap (size , offset , rv )
251251 result .Set (rv )
252252 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 )
253264 }
254265}
255266
@@ -450,8 +461,13 @@ func (d *decoder) decodeString(size uint, offset uint) (string, uint, error) {
450461 return string (d .buffer [offset :newOffset ]), newOffset , nil
451462}
452463
464+ type fieldsType struct {
465+ namedFields map [string ]int
466+ anonymousFields []int
467+ }
468+
453469var (
454- fieldMap = map [reflect.Type ]map [ string ] int {}
470+ fieldMap = map [reflect.Type ]* fieldsType {}
455471 fieldMapMu sync.RWMutex
456472)
457473
@@ -463,21 +479,39 @@ func (d *decoder) decodeStruct(size uint, offset uint, result reflect.Value) (ui
463479 fieldMapMu .RUnlock ()
464480 if ! ok {
465481 numFields := resultType .NumField ()
466- fields = make (map [string ]int , numFields )
482+ namedFields := make (map [string ]int , numFields )
483+ var anonymous []int
467484 for i := 0 ; i < numFields ; i ++ {
468- fieldType := resultType .Field (i )
485+ field := resultType .Field (i )
469486
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+ }
472492 fieldName = tag
473493 }
474- fields [fieldName ] = i
494+ if field .Anonymous {
495+ anonymous = append (anonymous , i )
496+ continue
497+ }
498+ namedFields [fieldName ] = i
475499 }
476500 fieldMapMu .Lock ()
501+ fields = & fieldsType {namedFields , anonymous }
477502 fieldMap [resultType ] = fields
478503 fieldMapMu .Unlock ()
479504 }
480505
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
481515 for i := uint (0 ); i < size ; i ++ {
482516 var (
483517 err error
@@ -487,12 +521,13 @@ func (d *decoder) decodeStruct(size uint, offset uint, result reflect.Value) (ui
487521 if err != nil {
488522 return 0 , err
489523 }
490- i , ok := fields [key ]
524+ j , ok := fields . namedFields [key ]
491525 if ! ok {
492526 offset = d .nextValueOffset (offset , 1 )
493527 continue
494528 }
495- offset , err = d .decode (offset , result .Field (i ))
529+
530+ offset , err = d .decode (offset , result .Field (j ))
496531 if err != nil {
497532 return 0 , err
498533 }
0 commit comments