github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go (about)

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package bsoncodec
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"reflect"
    13  	"sort"
    14  	"strings"
    15  	"sync"
    16  	"time"
    17  
    18  	"go.mongodb.org/mongo-driver/bson/bsonoptions"
    19  	"go.mongodb.org/mongo-driver/bson/bsonrw"
    20  	"go.mongodb.org/mongo-driver/bson/bsontype"
    21  )
    22  
    23  // DecodeError represents an error that occurs when unmarshalling BSON bytes into a native Go type.
    24  type DecodeError struct {
    25  	keys    []string
    26  	wrapped error
    27  }
    28  
    29  // Unwrap returns the underlying error
    30  func (de *DecodeError) Unwrap() error {
    31  	return de.wrapped
    32  }
    33  
    34  // Error implements the error interface.
    35  func (de *DecodeError) Error() string {
    36  	// The keys are stored in reverse order because the de.keys slice is builtup while propagating the error up the
    37  	// stack of BSON keys, so we call de.Keys(), which reverses them.
    38  	keyPath := strings.Join(de.Keys(), ".")
    39  	return fmt.Sprintf("error decoding key %s: %v", keyPath, de.wrapped)
    40  }
    41  
    42  // Keys returns the BSON key path that caused an error as a slice of strings. The keys in the slice are in top-down
    43  // order. For example, if the document being unmarshalled was {a: {b: {c: 1}}} and the value for c was supposed to be
    44  // a string, the keys slice will be ["a", "b", "c"].
    45  func (de *DecodeError) Keys() []string {
    46  	reversedKeys := make([]string, 0, len(de.keys))
    47  	for idx := len(de.keys) - 1; idx >= 0; idx-- {
    48  		reversedKeys = append(reversedKeys, de.keys[idx])
    49  	}
    50  
    51  	return reversedKeys
    52  }
    53  
    54  // Zeroer allows custom struct types to implement a report of zero
    55  // state. All struct types that don't implement Zeroer or where IsZero
    56  // returns false are considered to be not zero.
    57  type Zeroer interface {
    58  	IsZero() bool
    59  }
    60  
    61  // StructCodec is the Codec used for struct values.
    62  //
    63  // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
    64  // StructCodec registered.
    65  type StructCodec struct {
    66  	cache  map[reflect.Type]*structDescription
    67  	l      sync.RWMutex
    68  	parser StructTagParser
    69  
    70  	// DecodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the
    71  	// destination value passed to Decode before unmarshaling BSON documents into them.
    72  	//
    73  	// Deprecated: Use bson.Decoder.ZeroStructs instead.
    74  	DecodeZeroStruct bool
    75  
    76  	// DecodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the
    77  	// destination value passed to Decode before unmarshaling BSON documents into them.
    78  	//
    79  	// Deprecated: DecodeDeepZeroInline will not be supported in Go Driver 2.0.
    80  	DecodeDeepZeroInline bool
    81  
    82  	// EncodeOmitDefaultStruct causes the Encoder to consider the zero value for a struct (e.g.
    83  	// MyStruct{}) as empty and omit it from the marshaled BSON when the "omitempty" struct tag
    84  	// option is set.
    85  	//
    86  	// Deprecated: Use bson.Encoder.OmitZeroStruct instead.
    87  	EncodeOmitDefaultStruct bool
    88  
    89  	// AllowUnexportedFields allows encoding and decoding values from un-exported struct fields.
    90  	//
    91  	// Deprecated: AllowUnexportedFields does not work on recent versions of Go and will not be
    92  	// supported in Go Driver 2.0.
    93  	AllowUnexportedFields bool
    94  
    95  	// OverwriteDuplicatedInlinedFields, if false, causes EncodeValue to return an error if there is
    96  	// a duplicate field in the marshaled BSON when the "inline" struct tag option is set. The
    97  	// default value is true.
    98  	//
    99  	// Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates instead.
   100  	OverwriteDuplicatedInlinedFields bool
   101  }
   102  
   103  var _ ValueEncoder = &StructCodec{}
   104  var _ ValueDecoder = &StructCodec{}
   105  
   106  // NewStructCodec returns a StructCodec that uses p for struct tag parsing.
   107  //
   108  // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
   109  // StructCodec registered.
   110  func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) {
   111  	if p == nil {
   112  		return nil, errors.New("a StructTagParser must be provided to NewStructCodec")
   113  	}
   114  
   115  	structOpt := bsonoptions.MergeStructCodecOptions(opts...)
   116  
   117  	codec := &StructCodec{
   118  		cache:  make(map[reflect.Type]*structDescription),
   119  		parser: p,
   120  	}
   121  
   122  	if structOpt.DecodeZeroStruct != nil {
   123  		codec.DecodeZeroStruct = *structOpt.DecodeZeroStruct
   124  	}
   125  	if structOpt.DecodeDeepZeroInline != nil {
   126  		codec.DecodeDeepZeroInline = *structOpt.DecodeDeepZeroInline
   127  	}
   128  	if structOpt.EncodeOmitDefaultStruct != nil {
   129  		codec.EncodeOmitDefaultStruct = *structOpt.EncodeOmitDefaultStruct
   130  	}
   131  	if structOpt.OverwriteDuplicatedInlinedFields != nil {
   132  		codec.OverwriteDuplicatedInlinedFields = *structOpt.OverwriteDuplicatedInlinedFields
   133  	}
   134  	if structOpt.AllowUnexportedFields != nil {
   135  		codec.AllowUnexportedFields = *structOpt.AllowUnexportedFields
   136  	}
   137  
   138  	return codec, nil
   139  }
   140  
   141  // EncodeValue handles encoding generic struct types.
   142  func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
   143  	if !val.IsValid() || val.Kind() != reflect.Struct {
   144  		return ValueEncoderError{Name: "StructCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val}
   145  	}
   146  
   147  	sd, err := sc.describeStruct(ec.Registry, val.Type(), ec.useJSONStructTags, ec.errorOnInlineDuplicates)
   148  	if err != nil {
   149  		return err
   150  	}
   151  
   152  	dw, err := vw.WriteDocument()
   153  	if err != nil {
   154  		return err
   155  	}
   156  	var rv reflect.Value
   157  	for _, desc := range sd.fl {
   158  		if desc.inline == nil {
   159  			rv = val.Field(desc.idx)
   160  		} else {
   161  			rv, err = fieldByIndexErr(val, desc.inline)
   162  			if err != nil {
   163  				continue
   164  			}
   165  		}
   166  
   167  		desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(ec, desc.encoder, rv)
   168  
   169  		if err != nil && err != errInvalidValue {
   170  			return err
   171  		}
   172  
   173  		if err == errInvalidValue {
   174  			if desc.omitEmpty {
   175  				continue
   176  			}
   177  			vw2, err := dw.WriteDocumentElement(desc.name)
   178  			if err != nil {
   179  				return err
   180  			}
   181  			err = vw2.WriteNull()
   182  			if err != nil {
   183  				return err
   184  			}
   185  			continue
   186  		}
   187  
   188  		if desc.encoder == nil {
   189  			return ErrNoEncoder{Type: rv.Type()}
   190  		}
   191  
   192  		encoder := desc.encoder
   193  
   194  		var zero bool
   195  		rvInterface := rv.Interface()
   196  		if cz, ok := encoder.(CodecZeroer); ok {
   197  			zero = cz.IsTypeZero(rvInterface)
   198  		} else if rv.Kind() == reflect.Interface {
   199  			// isZero will not treat an interface rv as an interface, so we need to check for the
   200  			// zero interface separately.
   201  			zero = rv.IsNil()
   202  		} else {
   203  			zero = isZero(rvInterface, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct)
   204  		}
   205  		if desc.omitEmpty && zero {
   206  			continue
   207  		}
   208  
   209  		vw2, err := dw.WriteDocumentElement(desc.name)
   210  		if err != nil {
   211  			return err
   212  		}
   213  
   214  		ectx := EncodeContext{
   215  			Registry:                ec.Registry,
   216  			MinSize:                 desc.minSize || ec.MinSize,
   217  			errorOnInlineDuplicates: ec.errorOnInlineDuplicates,
   218  			stringifyMapKeysWithFmt: ec.stringifyMapKeysWithFmt,
   219  			nilMapAsEmpty:           ec.nilMapAsEmpty,
   220  			nilSliceAsEmpty:         ec.nilSliceAsEmpty,
   221  			nilByteSliceAsEmpty:     ec.nilByteSliceAsEmpty,
   222  			omitZeroStruct:          ec.omitZeroStruct,
   223  			useJSONStructTags:       ec.useJSONStructTags,
   224  		}
   225  		err = encoder.EncodeValue(ectx, vw2, rv)
   226  		if err != nil {
   227  			return err
   228  		}
   229  	}
   230  
   231  	if sd.inlineMap >= 0 {
   232  		rv := val.Field(sd.inlineMap)
   233  		collisionFn := func(key string) bool {
   234  			_, exists := sd.fm[key]
   235  			return exists
   236  		}
   237  
   238  		return defaultMapCodec.mapEncodeValue(ec, dw, rv, collisionFn)
   239  	}
   240  
   241  	return dw.WriteDocumentEnd()
   242  }
   243  
   244  func newDecodeError(key string, original error) error {
   245  	de, ok := original.(*DecodeError)
   246  	if !ok {
   247  		return &DecodeError{
   248  			keys:    []string{key},
   249  			wrapped: original,
   250  		}
   251  	}
   252  
   253  	de.keys = append(de.keys, key)
   254  	return de
   255  }
   256  
   257  // DecodeValue implements the Codec interface.
   258  // By default, map types in val will not be cleared. If a map has existing key/value pairs, it will be extended with the new ones from vr.
   259  // For slices, the decoder will set the length of the slice to zero and append all elements. The underlying array will not be cleared.
   260  func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
   261  	if !val.CanSet() || val.Kind() != reflect.Struct {
   262  		return ValueDecoderError{Name: "StructCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val}
   263  	}
   264  
   265  	switch vrType := vr.Type(); vrType {
   266  	case bsontype.Type(0), bsontype.EmbeddedDocument:
   267  	case bsontype.Null:
   268  		if err := vr.ReadNull(); err != nil {
   269  			return err
   270  		}
   271  
   272  		val.Set(reflect.Zero(val.Type()))
   273  		return nil
   274  	case bsontype.Undefined:
   275  		if err := vr.ReadUndefined(); err != nil {
   276  			return err
   277  		}
   278  
   279  		val.Set(reflect.Zero(val.Type()))
   280  		return nil
   281  	default:
   282  		return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type())
   283  	}
   284  
   285  	sd, err := sc.describeStruct(dc.Registry, val.Type(), dc.useJSONStructTags, false)
   286  	if err != nil {
   287  		return err
   288  	}
   289  
   290  	if sc.DecodeZeroStruct || dc.zeroStructs {
   291  		val.Set(reflect.Zero(val.Type()))
   292  	}
   293  	if sc.DecodeDeepZeroInline && sd.inline {
   294  		val.Set(deepZero(val.Type()))
   295  	}
   296  
   297  	var decoder ValueDecoder
   298  	var inlineMap reflect.Value
   299  	if sd.inlineMap >= 0 {
   300  		inlineMap = val.Field(sd.inlineMap)
   301  		decoder, err = dc.LookupDecoder(inlineMap.Type().Elem())
   302  		if err != nil {
   303  			return err
   304  		}
   305  	}
   306  
   307  	dr, err := vr.ReadDocument()
   308  	if err != nil {
   309  		return err
   310  	}
   311  
   312  	for {
   313  		name, vr, err := dr.ReadElement()
   314  		if err == bsonrw.ErrEOD {
   315  			break
   316  		}
   317  		if err != nil {
   318  			return err
   319  		}
   320  
   321  		fd, exists := sd.fm[name]
   322  		if !exists {
   323  			// if the original name isn't found in the struct description, try again with the name in lowercase
   324  			// this could match if a BSON tag isn't specified because by default, describeStruct lowercases all field
   325  			// names
   326  			fd, exists = sd.fm[strings.ToLower(name)]
   327  		}
   328  
   329  		if !exists {
   330  			if sd.inlineMap < 0 {
   331  				// The encoding/json package requires a flag to return on error for non-existent fields.
   332  				// This functionality seems appropriate for the struct codec.
   333  				err = vr.Skip()
   334  				if err != nil {
   335  					return err
   336  				}
   337  				continue
   338  			}
   339  
   340  			if inlineMap.IsNil() {
   341  				inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
   342  			}
   343  
   344  			elem := reflect.New(inlineMap.Type().Elem()).Elem()
   345  			dc.Ancestor = inlineMap.Type()
   346  			err = decoder.DecodeValue(dc, vr, elem)
   347  			if err != nil {
   348  				return err
   349  			}
   350  			inlineMap.SetMapIndex(reflect.ValueOf(name), elem)
   351  			continue
   352  		}
   353  
   354  		var field reflect.Value
   355  		if fd.inline == nil {
   356  			field = val.Field(fd.idx)
   357  		} else {
   358  			field, err = getInlineField(val, fd.inline)
   359  			if err != nil {
   360  				return err
   361  			}
   362  		}
   363  
   364  		if !field.CanSet() { // Being settable is a super set of being addressable.
   365  			innerErr := fmt.Errorf("field %v is not settable", field)
   366  			return newDecodeError(fd.name, innerErr)
   367  		}
   368  		if field.Kind() == reflect.Ptr && field.IsNil() {
   369  			field.Set(reflect.New(field.Type().Elem()))
   370  		}
   371  		field = field.Addr()
   372  
   373  		dctx := DecodeContext{
   374  			Registry:            dc.Registry,
   375  			Truncate:            fd.truncate || dc.Truncate,
   376  			defaultDocumentType: dc.defaultDocumentType,
   377  			binaryAsSlice:       dc.binaryAsSlice,
   378  			useJSONStructTags:   dc.useJSONStructTags,
   379  			useLocalTimeZone:    dc.useLocalTimeZone,
   380  			zeroMaps:            dc.zeroMaps,
   381  			zeroStructs:         dc.zeroStructs,
   382  		}
   383  
   384  		if fd.decoder == nil {
   385  			return newDecodeError(fd.name, ErrNoDecoder{Type: field.Elem().Type()})
   386  		}
   387  
   388  		err = fd.decoder.DecodeValue(dctx, vr, field.Elem())
   389  		if err != nil {
   390  			return newDecodeError(fd.name, err)
   391  		}
   392  	}
   393  
   394  	return nil
   395  }
   396  
   397  func isZero(i interface{}, omitZeroStruct bool) bool {
   398  	v := reflect.ValueOf(i)
   399  
   400  	// check the value validity
   401  	if !v.IsValid() {
   402  		return true
   403  	}
   404  
   405  	if z, ok := v.Interface().(Zeroer); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
   406  		return z.IsZero()
   407  	}
   408  
   409  	switch v.Kind() {
   410  	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
   411  		return v.Len() == 0
   412  	case reflect.Bool:
   413  		return !v.Bool()
   414  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   415  		return v.Int() == 0
   416  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   417  		return v.Uint() == 0
   418  	case reflect.Float32, reflect.Float64:
   419  		return v.Float() == 0
   420  	case reflect.Interface, reflect.Ptr:
   421  		return v.IsNil()
   422  	case reflect.Struct:
   423  		if !omitZeroStruct {
   424  			return false
   425  		}
   426  
   427  		// TODO(GODRIVER-2820): Update the logic to be able to handle private struct fields.
   428  		// TODO Use condition "reflect.Zero(v.Type()).Equal(v)" instead.
   429  
   430  		vt := v.Type()
   431  		if vt == tTime {
   432  			return v.Interface().(time.Time).IsZero()
   433  		}
   434  		for i := 0; i < v.NumField(); i++ {
   435  			if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous {
   436  				continue // Private field
   437  			}
   438  			fld := v.Field(i)
   439  			if !isZero(fld.Interface(), omitZeroStruct) {
   440  				return false
   441  			}
   442  		}
   443  		return true
   444  	}
   445  
   446  	return false
   447  }
   448  
   449  type structDescription struct {
   450  	fm        map[string]fieldDescription
   451  	fl        []fieldDescription
   452  	inlineMap int
   453  	inline    bool
   454  }
   455  
   456  type fieldDescription struct {
   457  	name      string // BSON key name
   458  	fieldName string // struct field name
   459  	idx       int
   460  	omitEmpty bool
   461  	minSize   bool
   462  	truncate  bool
   463  	inline    []int
   464  	encoder   ValueEncoder
   465  	decoder   ValueDecoder
   466  }
   467  
   468  type byIndex []fieldDescription
   469  
   470  func (bi byIndex) Len() int { return len(bi) }
   471  
   472  func (bi byIndex) Swap(i, j int) { bi[i], bi[j] = bi[j], bi[i] }
   473  
   474  func (bi byIndex) Less(i, j int) bool {
   475  	// If a field is inlined, its index in the top level struct is stored at inline[0]
   476  	iIdx, jIdx := bi[i].idx, bi[j].idx
   477  	if len(bi[i].inline) > 0 {
   478  		iIdx = bi[i].inline[0]
   479  	}
   480  	if len(bi[j].inline) > 0 {
   481  		jIdx = bi[j].inline[0]
   482  	}
   483  	if iIdx != jIdx {
   484  		return iIdx < jIdx
   485  	}
   486  	for k, biik := range bi[i].inline {
   487  		if k >= len(bi[j].inline) {
   488  			return false
   489  		}
   490  		if biik != bi[j].inline[k] {
   491  			return biik < bi[j].inline[k]
   492  		}
   493  	}
   494  	return len(bi[i].inline) < len(bi[j].inline)
   495  }
   496  
   497  func (sc *StructCodec) describeStruct(
   498  	r *Registry,
   499  	t reflect.Type,
   500  	useJSONStructTags bool,
   501  	errorOnDuplicates bool,
   502  ) (*structDescription, error) {
   503  	// We need to analyze the struct, including getting the tags, collecting
   504  	// information about inlining, and create a map of the field name to the field.
   505  	sc.l.RLock()
   506  	ds, exists := sc.cache[t]
   507  	sc.l.RUnlock()
   508  	if exists {
   509  		return ds, nil
   510  	}
   511  
   512  	numFields := t.NumField()
   513  	sd := &structDescription{
   514  		fm:        make(map[string]fieldDescription, numFields),
   515  		fl:        make([]fieldDescription, 0, numFields),
   516  		inlineMap: -1,
   517  	}
   518  
   519  	var fields []fieldDescription
   520  	for i := 0; i < numFields; i++ {
   521  		sf := t.Field(i)
   522  		if sf.PkgPath != "" && (!sc.AllowUnexportedFields || !sf.Anonymous) {
   523  			// field is private or unexported fields aren't allowed, ignore
   524  			continue
   525  		}
   526  
   527  		sfType := sf.Type
   528  		encoder, err := r.LookupEncoder(sfType)
   529  		if err != nil {
   530  			encoder = nil
   531  		}
   532  		decoder, err := r.LookupDecoder(sfType)
   533  		if err != nil {
   534  			decoder = nil
   535  		}
   536  
   537  		description := fieldDescription{
   538  			fieldName: sf.Name,
   539  			idx:       i,
   540  			encoder:   encoder,
   541  			decoder:   decoder,
   542  		}
   543  
   544  		var stags StructTags
   545  		// If the caller requested that we use JSON struct tags, use the JSONFallbackStructTagParser
   546  		// instead of the parser defined on the codec.
   547  		if useJSONStructTags {
   548  			stags, err = JSONFallbackStructTagParser.ParseStructTags(sf)
   549  		} else {
   550  			stags, err = sc.parser.ParseStructTags(sf)
   551  		}
   552  		if err != nil {
   553  			return nil, err
   554  		}
   555  		if stags.Skip {
   556  			continue
   557  		}
   558  		description.name = stags.Name
   559  		description.omitEmpty = stags.OmitEmpty
   560  		description.minSize = stags.MinSize
   561  		description.truncate = stags.Truncate
   562  
   563  		if stags.Inline {
   564  			sd.inline = true
   565  			switch sfType.Kind() {
   566  			case reflect.Map:
   567  				if sd.inlineMap >= 0 {
   568  					return nil, errors.New("(struct " + t.String() + ") multiple inline maps")
   569  				}
   570  				if sfType.Key() != tString {
   571  					return nil, errors.New("(struct " + t.String() + ") inline map must have a string keys")
   572  				}
   573  				sd.inlineMap = description.idx
   574  			case reflect.Ptr:
   575  				sfType = sfType.Elem()
   576  				if sfType.Kind() != reflect.Struct {
   577  					return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String())
   578  				}
   579  				fallthrough
   580  			case reflect.Struct:
   581  				inlinesf, err := sc.describeStruct(r, sfType, useJSONStructTags, errorOnDuplicates)
   582  				if err != nil {
   583  					return nil, err
   584  				}
   585  				for _, fd := range inlinesf.fl {
   586  					if fd.inline == nil {
   587  						fd.inline = []int{i, fd.idx}
   588  					} else {
   589  						fd.inline = append([]int{i}, fd.inline...)
   590  					}
   591  					fields = append(fields, fd)
   592  
   593  				}
   594  			default:
   595  				return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String())
   596  			}
   597  			continue
   598  		}
   599  		fields = append(fields, description)
   600  	}
   601  
   602  	// Sort fieldDescriptions by name and use dominance rules to determine which should be added for each name
   603  	sort.Slice(fields, func(i, j int) bool {
   604  		x := fields
   605  		// sort field by name, breaking ties with depth, then
   606  		// breaking ties with index sequence.
   607  		if x[i].name != x[j].name {
   608  			return x[i].name < x[j].name
   609  		}
   610  		if len(x[i].inline) != len(x[j].inline) {
   611  			return len(x[i].inline) < len(x[j].inline)
   612  		}
   613  		return byIndex(x).Less(i, j)
   614  	})
   615  
   616  	for advance, i := 0, 0; i < len(fields); i += advance {
   617  		// One iteration per name.
   618  		// Find the sequence of fields with the name of this first field.
   619  		fi := fields[i]
   620  		name := fi.name
   621  		for advance = 1; i+advance < len(fields); advance++ {
   622  			fj := fields[i+advance]
   623  			if fj.name != name {
   624  				break
   625  			}
   626  		}
   627  		if advance == 1 { // Only one field with this name
   628  			sd.fl = append(sd.fl, fi)
   629  			sd.fm[name] = fi
   630  			continue
   631  		}
   632  		dominant, ok := dominantField(fields[i : i+advance])
   633  		if !ok || !sc.OverwriteDuplicatedInlinedFields || errorOnDuplicates {
   634  			return nil, fmt.Errorf("struct %s has duplicated key %s", t.String(), name)
   635  		}
   636  		sd.fl = append(sd.fl, dominant)
   637  		sd.fm[name] = dominant
   638  	}
   639  
   640  	sort.Sort(byIndex(sd.fl))
   641  
   642  	sc.l.Lock()
   643  	sc.cache[t] = sd
   644  	sc.l.Unlock()
   645  
   646  	return sd, nil
   647  }
   648  
   649  // dominantField looks through the fields, all of which are known to
   650  // have the same name, to find the single field that dominates the
   651  // others using Go's inlining rules. If there are multiple top-level
   652  // fields, the boolean will be false: This condition is an error in Go
   653  // and we skip all the fields.
   654  func dominantField(fields []fieldDescription) (fieldDescription, bool) {
   655  	// The fields are sorted in increasing index-length order, then by presence of tag.
   656  	// That means that the first field is the dominant one. We need only check
   657  	// for error cases: two fields at top level.
   658  	if len(fields) > 1 &&
   659  		len(fields[0].inline) == len(fields[1].inline) {
   660  		return fieldDescription{}, false
   661  	}
   662  	return fields[0], true
   663  }
   664  
   665  func fieldByIndexErr(v reflect.Value, index []int) (result reflect.Value, err error) {
   666  	defer func() {
   667  		if recovered := recover(); recovered != nil {
   668  			switch r := recovered.(type) {
   669  			case string:
   670  				err = fmt.Errorf("%s", r)
   671  			case error:
   672  				err = r
   673  			}
   674  		}
   675  	}()
   676  
   677  	result = v.FieldByIndex(index)
   678  	return
   679  }
   680  
   681  func getInlineField(val reflect.Value, index []int) (reflect.Value, error) {
   682  	field, err := fieldByIndexErr(val, index)
   683  	if err == nil {
   684  		return field, nil
   685  	}
   686  
   687  	// if parent of this element doesn't exist, fix its parent
   688  	inlineParent := index[:len(index)-1]
   689  	var fParent reflect.Value
   690  	if fParent, err = fieldByIndexErr(val, inlineParent); err != nil {
   691  		fParent, err = getInlineField(val, inlineParent)
   692  		if err != nil {
   693  			return fParent, err
   694  		}
   695  	}
   696  	fParent.Set(reflect.New(fParent.Type().Elem()))
   697  
   698  	return fieldByIndexErr(val, index)
   699  }
   700  
   701  // DeepZero returns recursive zero object
   702  func deepZero(st reflect.Type) (result reflect.Value) {
   703  	result = reflect.Indirect(reflect.New(st))
   704  
   705  	if result.Kind() == reflect.Struct {
   706  		for i := 0; i < result.NumField(); i++ {
   707  			if f := result.Field(i); f.Kind() == reflect.Ptr {
   708  				if f.CanInterface() {
   709  					if ft := reflect.TypeOf(f.Interface()); ft.Elem().Kind() == reflect.Struct {
   710  						result.Field(i).Set(recursivePointerTo(deepZero(ft.Elem())))
   711  					}
   712  				}
   713  			}
   714  		}
   715  	}
   716  
   717  	return
   718  }
   719  
   720  // recursivePointerTo calls reflect.New(v.Type) but recursively for its fields inside
   721  func recursivePointerTo(v reflect.Value) reflect.Value {
   722  	v = reflect.Indirect(v)
   723  	result := reflect.New(v.Type())
   724  	if v.Kind() == reflect.Struct {
   725  		for i := 0; i < v.NumField(); i++ {
   726  			if f := v.Field(i); f.Kind() == reflect.Ptr {
   727  				if f.Elem().Kind() == reflect.Struct {
   728  					result.Elem().Field(i).Set(recursivePointerTo(f))
   729  				}
   730  			}
   731  		}
   732  	}
   733  
   734  	return result
   735  }