github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/converter.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package conversion
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  )
    23  
    24  type typePair struct {
    25  	source reflect.Type
    26  	dest   reflect.Type
    27  }
    28  
    29  type typeNamePair struct {
    30  	fieldType reflect.Type
    31  	fieldName string
    32  }
    33  
    34  // DebugLogger allows you to get debugging messages if necessary.
    35  type DebugLogger interface {
    36  	Logf(format string, args ...interface{})
    37  }
    38  
    39  // Converter knows how to convert one type to another.
    40  type Converter struct {
    41  	// Map from the conversion pair to a function which can
    42  	// do the conversion.
    43  	conversionFuncs          map[typePair]reflect.Value
    44  	generatedConversionFuncs map[typePair]reflect.Value
    45  
    46  	// This is a map from a source field type and name, to a list of destination
    47  	// field type and name.
    48  	structFieldDests map[typeNamePair][]typeNamePair
    49  
    50  	// Allows for the opposite lookup of structFieldDests. So that SourceFromDest
    51  	// copy flag also works. So this is a map of destination field name, to potential
    52  	// source field name and type to look for.
    53  	structFieldSources map[typeNamePair][]typeNamePair
    54  
    55  	// Map from a type to a function which applies defaults.
    56  	defaultingFuncs map[reflect.Type]reflect.Value
    57  
    58  	// Similar to above, but function is stored as interface{}.
    59  	defaultingInterfaces map[reflect.Type]interface{}
    60  
    61  	// Map from an input type to a function which can apply a key name mapping
    62  	inputFieldMappingFuncs map[reflect.Type]FieldMappingFunc
    63  
    64  	// Map from an input type to a set of default conversion flags.
    65  	inputDefaultFlags map[reflect.Type]FieldMatchingFlags
    66  
    67  	// If non-nil, will be called to print helpful debugging info. Quite verbose.
    68  	Debug DebugLogger
    69  
    70  	// nameFunc is called to retrieve the name of a type; this name is used for the
    71  	// purpose of deciding whether two types match or not (i.e., will we attempt to
    72  	// do a conversion). The default returns the go type name.
    73  	nameFunc func(t reflect.Type) string
    74  }
    75  
    76  // NewConverter creates a new Converter object.
    77  func NewConverter() *Converter {
    78  	c := &Converter{
    79  		conversionFuncs:          map[typePair]reflect.Value{},
    80  		generatedConversionFuncs: map[typePair]reflect.Value{},
    81  		defaultingFuncs:          map[reflect.Type]reflect.Value{},
    82  		defaultingInterfaces:     map[reflect.Type]interface{}{},
    83  		nameFunc:                 func(t reflect.Type) string { return t.Name() },
    84  		structFieldDests:         map[typeNamePair][]typeNamePair{},
    85  		structFieldSources:       map[typeNamePair][]typeNamePair{},
    86  
    87  		inputFieldMappingFuncs: map[reflect.Type]FieldMappingFunc{},
    88  		inputDefaultFlags:      map[reflect.Type]FieldMatchingFlags{},
    89  	}
    90  	c.RegisterConversionFunc(byteSliceCopy)
    91  	return c
    92  }
    93  
    94  // Prevent recursing into every byte...
    95  func byteSliceCopy(in *[]byte, out *[]byte, s Scope) error {
    96  	*out = make([]byte, len(*in))
    97  	copy(*out, *in)
    98  	return nil
    99  }
   100  
   101  // Scope is passed to conversion funcs to allow them to continue an ongoing conversion.
   102  // If multiple converters exist in the system, Scope will allow you to use the correct one
   103  // from a conversion function--that is, the one your conversion function was called by.
   104  type Scope interface {
   105  	// Call Convert to convert sub-objects. Note that if you call it with your own exact
   106  	// parameters, you'll run out of stack space before anything useful happens.
   107  	Convert(src, dest interface{}, flags FieldMatchingFlags) error
   108  
   109  	// DefaultConvert performs the default conversion, without calling a conversion func
   110  	// on the current stack frame. This makes it safe to call from a conversion func.
   111  	DefaultConvert(src, dest interface{}, flags FieldMatchingFlags) error
   112  
   113  	// If registered, returns a function applying defaults for objects of a given type.
   114  	// Used for automatically generating conversion functions.
   115  	DefaultingInterface(inType reflect.Type) (interface{}, bool)
   116  
   117  	// SrcTags and DestTags contain the struct tags that src and dest had, respectively.
   118  	// If the enclosing object was not a struct, then these will contain no tags, of course.
   119  	SrcTag() reflect.StructTag
   120  	DestTag() reflect.StructTag
   121  
   122  	// Flags returns the flags with which the conversion was started.
   123  	Flags() FieldMatchingFlags
   124  
   125  	// Meta returns any information originally passed to Convert.
   126  	Meta() *Meta
   127  }
   128  
   129  // FieldMappingFunc can convert an input field value into different values, depending on
   130  // the value of the source or destination struct tags.
   131  type FieldMappingFunc func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string)
   132  
   133  // Meta is supplied by Scheme, when it calls Convert.
   134  type Meta struct {
   135  	SrcVersion  string
   136  	DestVersion string
   137  
   138  	// KeyNameMapping is an optional function which may map the listed key (field name)
   139  	// into a source and destination value.
   140  	KeyNameMapping FieldMappingFunc
   141  }
   142  
   143  // scope contains information about an ongoing conversion.
   144  type scope struct {
   145  	converter *Converter
   146  	meta      *Meta
   147  	flags     FieldMatchingFlags
   148  
   149  	// srcStack & destStack are separate because they may not have a 1:1
   150  	// relationship.
   151  	srcStack  scopeStack
   152  	destStack scopeStack
   153  }
   154  
   155  type scopeStackElem struct {
   156  	tag   reflect.StructTag
   157  	value reflect.Value
   158  	key   string
   159  }
   160  
   161  type scopeStack []scopeStackElem
   162  
   163  func (s *scopeStack) pop() {
   164  	n := len(*s)
   165  	*s = (*s)[:n-1]
   166  }
   167  
   168  func (s *scopeStack) push(e scopeStackElem) {
   169  	*s = append(*s, e)
   170  }
   171  
   172  func (s *scopeStack) top() *scopeStackElem {
   173  	return &(*s)[len(*s)-1]
   174  }
   175  
   176  func (s scopeStack) describe() string {
   177  	desc := ""
   178  	if len(s) > 1 {
   179  		desc = "(" + s[1].value.Type().String() + ")"
   180  	}
   181  	for i, v := range s {
   182  		if i < 2 {
   183  			// First layer on stack is not real; second is handled specially above.
   184  			continue
   185  		}
   186  		if v.key == "" {
   187  			desc += fmt.Sprintf(".%v", v.value.Type())
   188  		} else {
   189  			desc += fmt.Sprintf(".%v", v.key)
   190  		}
   191  	}
   192  	return desc
   193  }
   194  
   195  func (s *scope) DefaultingInterface(inType reflect.Type) (interface{}, bool) {
   196  	value, found := s.converter.defaultingInterfaces[inType]
   197  	return value, found
   198  }
   199  
   200  // Formats src & dest as indices for printing.
   201  func (s *scope) setIndices(src, dest int) {
   202  	s.srcStack.top().key = fmt.Sprintf("[%v]", src)
   203  	s.destStack.top().key = fmt.Sprintf("[%v]", dest)
   204  }
   205  
   206  // Formats src & dest as map keys for printing.
   207  func (s *scope) setKeys(src, dest interface{}) {
   208  	s.srcStack.top().key = fmt.Sprintf(`["%v"]`, src)
   209  	s.destStack.top().key = fmt.Sprintf(`["%v"]`, dest)
   210  }
   211  
   212  // Convert continues a conversion.
   213  func (s *scope) Convert(src, dest interface{}, flags FieldMatchingFlags) error {
   214  	return s.converter.Convert(src, dest, flags, s.meta)
   215  }
   216  
   217  // DefaultConvert continues a conversion, performing a default conversion (no conversion func)
   218  // for the current stack frame.
   219  func (s *scope) DefaultConvert(src, dest interface{}, flags FieldMatchingFlags) error {
   220  	return s.converter.DefaultConvert(src, dest, flags, s.meta)
   221  }
   222  
   223  // SrcTag returns the tag of the struct containing the current source item, if any.
   224  func (s *scope) SrcTag() reflect.StructTag {
   225  	return s.srcStack.top().tag
   226  }
   227  
   228  // DestTag returns the tag of the struct containing the current dest item, if any.
   229  func (s *scope) DestTag() reflect.StructTag {
   230  	return s.destStack.top().tag
   231  }
   232  
   233  // Flags returns the flags with which the current conversion was started.
   234  func (s *scope) Flags() FieldMatchingFlags {
   235  	return s.flags
   236  }
   237  
   238  // Meta returns the meta object that was originally passed to Convert.
   239  func (s *scope) Meta() *Meta {
   240  	return s.meta
   241  }
   242  
   243  // describe prints the path to get to the current (source, dest) values.
   244  func (s *scope) describe() (src, dest string) {
   245  	return s.srcStack.describe(), s.destStack.describe()
   246  }
   247  
   248  // error makes an error that includes information about where we were in the objects
   249  // we were asked to convert.
   250  func (s *scope) errorf(message string, args ...interface{}) error {
   251  	srcPath, destPath := s.describe()
   252  	where := fmt.Sprintf("converting %v to %v: ", srcPath, destPath)
   253  	return fmt.Errorf(where+message, args...)
   254  }
   255  
   256  // Verifies whether a conversion function has a correct signature.
   257  func verifyConversionFunctionSignature(ft reflect.Type) error {
   258  	if ft.Kind() != reflect.Func {
   259  		return fmt.Errorf("expected func, got: %v", ft)
   260  	}
   261  	if ft.NumIn() != 3 {
   262  		return fmt.Errorf("expected three 'in' params, got: %v", ft)
   263  	}
   264  	if ft.NumOut() != 1 {
   265  		return fmt.Errorf("expected one 'out' param, got: %v", ft)
   266  	}
   267  	if ft.In(0).Kind() != reflect.Ptr {
   268  		return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft)
   269  	}
   270  	if ft.In(1).Kind() != reflect.Ptr {
   271  		return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft)
   272  	}
   273  	scopeType := Scope(nil)
   274  	if e, a := reflect.TypeOf(&scopeType).Elem(), ft.In(2); e != a {
   275  		return fmt.Errorf("expected '%v' arg for 'in' param 2, got '%v' (%v)", e, a, ft)
   276  	}
   277  	var forErrorType error
   278  	// This convolution is necessary, otherwise TypeOf picks up on the fact
   279  	// that forErrorType is nil.
   280  	errorType := reflect.TypeOf(&forErrorType).Elem()
   281  	if ft.Out(0) != errorType {
   282  		return fmt.Errorf("expected error return, got: %v", ft)
   283  	}
   284  	return nil
   285  }
   286  
   287  // RegisterConversionFunc registers a conversion func with the
   288  // Converter. conversionFunc must take three parameters: a pointer to the input
   289  // type, a pointer to the output type, and a conversion.Scope (which should be
   290  // used if recursive conversion calls are desired).  It must return an error.
   291  //
   292  // Example:
   293  // c.RegisterConversionFunc(
   294  //         func(in *Pod, out *v1.Pod, s Scope) error {
   295  //                 // conversion logic...
   296  //                 return nil
   297  //          })
   298  func (c *Converter) RegisterConversionFunc(conversionFunc interface{}) error {
   299  	fv := reflect.ValueOf(conversionFunc)
   300  	ft := fv.Type()
   301  	if err := verifyConversionFunctionSignature(ft); err != nil {
   302  		return err
   303  	}
   304  	c.conversionFuncs[typePair{ft.In(0).Elem(), ft.In(1).Elem()}] = fv
   305  	return nil
   306  }
   307  
   308  // Similar to RegisterConversionFunc, but registers conversion function that were
   309  // automatically generated.
   310  func (c *Converter) RegisterGeneratedConversionFunc(conversionFunc interface{}) error {
   311  	fv := reflect.ValueOf(conversionFunc)
   312  	ft := fv.Type()
   313  	if err := verifyConversionFunctionSignature(ft); err != nil {
   314  		return err
   315  	}
   316  	c.generatedConversionFuncs[typePair{ft.In(0).Elem(), ft.In(1).Elem()}] = fv
   317  	return nil
   318  }
   319  
   320  func (c *Converter) HasConversionFunc(inType, outType reflect.Type) bool {
   321  	_, found := c.conversionFuncs[typePair{inType, outType}]
   322  	return found
   323  }
   324  
   325  // SetStructFieldCopy registers a correspondence. Whenever a struct field is encountered
   326  // which has a type and name matching srcFieldType and srcFieldName, it wil be copied
   327  // into the field in the destination struct matching destFieldType & Name, if such a
   328  // field exists.
   329  // May be called multiple times, even for the same source field & type--all applicable
   330  // copies will be performed.
   331  func (c *Converter) SetStructFieldCopy(srcFieldType interface{}, srcFieldName string, destFieldType interface{}, destFieldName string) error {
   332  	st := reflect.TypeOf(srcFieldType)
   333  	dt := reflect.TypeOf(destFieldType)
   334  	srcKey := typeNamePair{st, srcFieldName}
   335  	destKey := typeNamePair{dt, destFieldName}
   336  	c.structFieldDests[srcKey] = append(c.structFieldDests[srcKey], destKey)
   337  	c.structFieldSources[destKey] = append(c.structFieldSources[destKey], srcKey)
   338  	return nil
   339  }
   340  
   341  // RegisterDefaultingFunc registers a value-defaulting func with the Converter.
   342  // defaultingFunc must take one parameters: a pointer to the input type.
   343  //
   344  // Example:
   345  // c.RegisteDefaultingFunc(
   346  //         func(in *v1.Pod) {
   347  //                 // defaulting logic...
   348  //          })
   349  func (c *Converter) RegisterDefaultingFunc(defaultingFunc interface{}) error {
   350  	fv := reflect.ValueOf(defaultingFunc)
   351  	ft := fv.Type()
   352  	if ft.Kind() != reflect.Func {
   353  		return fmt.Errorf("expected func, got: %v", ft)
   354  	}
   355  	if ft.NumIn() != 1 {
   356  		return fmt.Errorf("expected one 'in' param, got: %v", ft)
   357  	}
   358  	if ft.NumOut() != 0 {
   359  		return fmt.Errorf("expected zero 'out' params, got: %v", ft)
   360  	}
   361  	if ft.In(0).Kind() != reflect.Ptr {
   362  		return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft)
   363  	}
   364  	inType := ft.In(0).Elem()
   365  	c.defaultingFuncs[inType] = fv
   366  	c.defaultingInterfaces[inType] = defaultingFunc
   367  	return nil
   368  }
   369  
   370  // RegisterInputDefaults registers a field name mapping function, used when converting
   371  // from maps to structs. Inputs to the conversion methods are checked for this type and a mapping
   372  // applied automatically if the input matches in. A set of default flags for the input conversion
   373  // may also be provided, which will be used when no explicit flags are requested.
   374  func (c *Converter) RegisterInputDefaults(in interface{}, fn FieldMappingFunc, defaultFlags FieldMatchingFlags) error {
   375  	fv := reflect.ValueOf(in)
   376  	ft := fv.Type()
   377  	if ft.Kind() != reflect.Ptr {
   378  		return fmt.Errorf("expected pointer 'in' argument, got: %v", ft)
   379  	}
   380  	c.inputFieldMappingFuncs[ft] = fn
   381  	c.inputDefaultFlags[ft] = defaultFlags
   382  	return nil
   383  }
   384  
   385  // FieldMatchingFlags contains a list of ways in which struct fields could be
   386  // copied. These constants may be | combined.
   387  type FieldMatchingFlags int
   388  
   389  const (
   390  	// Loop through destination fields, search for matching source
   391  	// field to copy it from. Source fields with no corresponding
   392  	// destination field will be ignored. If SourceToDest is
   393  	// specified, this flag is ignored. If neither is specified,
   394  	// or no flags are passed, this flag is the default.
   395  	DestFromSource FieldMatchingFlags = 0
   396  	// Loop through source fields, search for matching dest field
   397  	// to copy it into. Destination fields with no corresponding
   398  	// source field will be ignored.
   399  	SourceToDest FieldMatchingFlags = 1 << iota
   400  	// Don't treat it as an error if the corresponding source or
   401  	// dest field can't be found.
   402  	IgnoreMissingFields
   403  	// Don't require type names to match.
   404  	AllowDifferentFieldTypeNames
   405  )
   406  
   407  // IsSet returns true if the given flag or combination of flags is set.
   408  func (f FieldMatchingFlags) IsSet(flag FieldMatchingFlags) bool {
   409  	if flag == DestFromSource {
   410  		// The bit logic doesn't work on the default value.
   411  		return f&SourceToDest != SourceToDest
   412  	}
   413  	return f&flag == flag
   414  }
   415  
   416  // Convert will translate src to dest if it knows how. Both must be pointers.
   417  // If no conversion func is registered and the default copying mechanism
   418  // doesn't work on this type pair, an error will be returned.
   419  // Read the comments on the various FieldMatchingFlags constants to understand
   420  // what the 'flags' parameter does.
   421  // 'meta' is given to allow you to pass information to conversion functions,
   422  // it is not used by Convert() other than storing it in the scope.
   423  // Not safe for objects with cyclic references!
   424  func (c *Converter) Convert(src, dest interface{}, flags FieldMatchingFlags, meta *Meta) error {
   425  	return c.doConversion(src, dest, flags, meta, c.convert)
   426  }
   427  
   428  // DefaultConvert will translate src to dest if it knows how. Both must be pointers.
   429  // No conversion func is used. If the default copying mechanism
   430  // doesn't work on this type pair, an error will be returned.
   431  // Read the comments on the various FieldMatchingFlags constants to understand
   432  // what the 'flags' parameter does.
   433  // 'meta' is given to allow you to pass information to conversion functions,
   434  // it is not used by DefaultConvert() other than storing it in the scope.
   435  // Not safe for objects with cyclic references!
   436  func (c *Converter) DefaultConvert(src, dest interface{}, flags FieldMatchingFlags, meta *Meta) error {
   437  	return c.doConversion(src, dest, flags, meta, c.defaultConvert)
   438  }
   439  
   440  type conversionFunc func(sv, dv reflect.Value, scope *scope) error
   441  
   442  func (c *Converter) doConversion(src, dest interface{}, flags FieldMatchingFlags, meta *Meta, f conversionFunc) error {
   443  	dv, err := EnforcePtr(dest)
   444  	if err != nil {
   445  		return err
   446  	}
   447  	if !dv.CanAddr() && !dv.CanSet() {
   448  		return fmt.Errorf("can't write to dest")
   449  	}
   450  	sv, err := EnforcePtr(src)
   451  	if err != nil {
   452  		return err
   453  	}
   454  	s := &scope{
   455  		converter: c,
   456  		flags:     flags,
   457  		meta:      meta,
   458  	}
   459  	// Leave something on the stack, so that calls to struct tag getters never fail.
   460  	s.srcStack.push(scopeStackElem{})
   461  	s.destStack.push(scopeStackElem{})
   462  	return f(sv, dv, s)
   463  }
   464  
   465  // callCustom calls 'custom' with sv & dv. custom must be a conversion function.
   466  func (c *Converter) callCustom(sv, dv, custom reflect.Value, scope *scope) error {
   467  	if !sv.CanAddr() {
   468  		sv2 := reflect.New(sv.Type())
   469  		sv2.Elem().Set(sv)
   470  		sv = sv2
   471  	} else {
   472  		sv = sv.Addr()
   473  	}
   474  	if !dv.CanAddr() {
   475  		if !dv.CanSet() {
   476  			return scope.errorf("can't addr or set dest.")
   477  		}
   478  		dvOrig := dv
   479  		dv := reflect.New(dvOrig.Type())
   480  		defer func() { dvOrig.Set(dv) }()
   481  	} else {
   482  		dv = dv.Addr()
   483  	}
   484  	args := []reflect.Value{sv, dv, reflect.ValueOf(scope)}
   485  	ret := custom.Call(args)[0].Interface()
   486  	// This convolution is necessary because nil interfaces won't convert
   487  	// to errors.
   488  	if ret == nil {
   489  		return nil
   490  	}
   491  	return ret.(error)
   492  }
   493  
   494  // convert recursively copies sv into dv, calling an appropriate conversion function if
   495  // one is registered.
   496  func (c *Converter) convert(sv, dv reflect.Value, scope *scope) error {
   497  	dt, st := dv.Type(), sv.Type()
   498  	// Apply default values.
   499  	if fv, ok := c.defaultingFuncs[st]; ok {
   500  		if c.Debug != nil {
   501  			c.Debug.Logf("Applying defaults for '%v'", st)
   502  		}
   503  		args := []reflect.Value{sv.Addr()}
   504  		fv.Call(args)
   505  	}
   506  
   507  	// Convert sv to dv.
   508  	if fv, ok := c.conversionFuncs[typePair{st, dt}]; ok {
   509  		if c.Debug != nil {
   510  			c.Debug.Logf("Calling custom conversion of '%v' to '%v'", st, dt)
   511  		}
   512  		return c.callCustom(sv, dv, fv, scope)
   513  	}
   514  	if fv, ok := c.generatedConversionFuncs[typePair{st, dt}]; ok {
   515  		if c.Debug != nil {
   516  			c.Debug.Logf("Calling custom conversion of '%v' to '%v'", st, dt)
   517  		}
   518  		return c.callCustom(sv, dv, fv, scope)
   519  	}
   520  
   521  	return c.defaultConvert(sv, dv, scope)
   522  }
   523  
   524  // defaultConvert recursively copies sv into dv. no conversion function is called
   525  // for the current stack frame (but conversion functions may be called for nested objects)
   526  func (c *Converter) defaultConvert(sv, dv reflect.Value, scope *scope) error {
   527  	dt, st := dv.Type(), sv.Type()
   528  
   529  	if !dv.CanSet() {
   530  		return scope.errorf("Cannot set dest. (Tried to deep copy something with unexported fields?)")
   531  	}
   532  
   533  	if !scope.flags.IsSet(AllowDifferentFieldTypeNames) && c.nameFunc(dt) != c.nameFunc(st) {
   534  		return scope.errorf(
   535  			"type names don't match (%v, %v), and no conversion 'func (%v, %v) error' registered.",
   536  			c.nameFunc(st), c.nameFunc(dt), st, dt)
   537  	}
   538  
   539  	switch st.Kind() {
   540  	case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct:
   541  		// Don't copy these via assignment/conversion!
   542  	default:
   543  		// This should handle all simple types.
   544  		if st.AssignableTo(dt) {
   545  			dv.Set(sv)
   546  			return nil
   547  		}
   548  		if st.ConvertibleTo(dt) {
   549  			dv.Set(sv.Convert(dt))
   550  			return nil
   551  		}
   552  	}
   553  
   554  	if c.Debug != nil {
   555  		c.Debug.Logf("Trying to convert '%v' to '%v'", st, dt)
   556  	}
   557  
   558  	scope.srcStack.push(scopeStackElem{value: sv})
   559  	scope.destStack.push(scopeStackElem{value: dv})
   560  	defer scope.srcStack.pop()
   561  	defer scope.destStack.pop()
   562  
   563  	switch dv.Kind() {
   564  	case reflect.Struct:
   565  		return c.convertKV(toKVValue(sv), toKVValue(dv), scope)
   566  	case reflect.Slice:
   567  		if sv.IsNil() {
   568  			// Don't make a zero-length slice.
   569  			dv.Set(reflect.Zero(dt))
   570  			return nil
   571  		}
   572  		dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap()))
   573  		for i := 0; i < sv.Len(); i++ {
   574  			scope.setIndices(i, i)
   575  			if err := c.convert(sv.Index(i), dv.Index(i), scope); err != nil {
   576  				return err
   577  			}
   578  		}
   579  	case reflect.Ptr:
   580  		if sv.IsNil() {
   581  			// Don't copy a nil ptr!
   582  			dv.Set(reflect.Zero(dt))
   583  			return nil
   584  		}
   585  		dv.Set(reflect.New(dt.Elem()))
   586  		switch st.Kind() {
   587  		case reflect.Ptr, reflect.Interface:
   588  			return c.convert(sv.Elem(), dv.Elem(), scope)
   589  		default:
   590  			return c.convert(sv, dv.Elem(), scope)
   591  		}
   592  	case reflect.Map:
   593  		if sv.IsNil() {
   594  			// Don't copy a nil ptr!
   595  			dv.Set(reflect.Zero(dt))
   596  			return nil
   597  		}
   598  		dv.Set(reflect.MakeMap(dt))
   599  		for _, sk := range sv.MapKeys() {
   600  			dk := reflect.New(dt.Key()).Elem()
   601  			if err := c.convert(sk, dk, scope); err != nil {
   602  				return err
   603  			}
   604  			dkv := reflect.New(dt.Elem()).Elem()
   605  			scope.setKeys(sk.Interface(), dk.Interface())
   606  			// TODO:  sv.MapIndex(sk) may return a value with CanAddr() == false,
   607  			// because a map[string]struct{} does not allow a pointer reference.
   608  			// Calling a custom conversion function defined for the map value
   609  			// will panic. Example is PodInfo map[string]ContainerStatus.
   610  			if err := c.convert(sv.MapIndex(sk), dkv, scope); err != nil {
   611  				return err
   612  			}
   613  			dv.SetMapIndex(dk, dkv)
   614  		}
   615  	case reflect.Interface:
   616  		if sv.IsNil() {
   617  			// Don't copy a nil interface!
   618  			dv.Set(reflect.Zero(dt))
   619  			return nil
   620  		}
   621  		tmpdv := reflect.New(sv.Elem().Type()).Elem()
   622  		if err := c.convert(sv.Elem(), tmpdv, scope); err != nil {
   623  			return err
   624  		}
   625  		dv.Set(reflect.ValueOf(tmpdv.Interface()))
   626  		return nil
   627  	default:
   628  		return scope.errorf("couldn't copy '%v' into '%v'; didn't understand types", st, dt)
   629  	}
   630  	return nil
   631  }
   632  
   633  var stringType = reflect.TypeOf("")
   634  
   635  func toKVValue(v reflect.Value) kvValue {
   636  	switch v.Kind() {
   637  	case reflect.Struct:
   638  		return structAdaptor(v)
   639  	case reflect.Map:
   640  		if v.Type().Key().AssignableTo(stringType) {
   641  			return stringMapAdaptor(v)
   642  		}
   643  	}
   644  
   645  	return nil
   646  }
   647  
   648  // kvValue lets us write the same conversion logic to work with both maps
   649  // and structs. Only maps with string keys make sense for this.
   650  type kvValue interface {
   651  	// returns all keys, as a []string.
   652  	keys() []string
   653  	// Will just return "" for maps.
   654  	tagOf(key string) reflect.StructTag
   655  	// Will return the zero Value if the key doesn't exist.
   656  	value(key string) reflect.Value
   657  	// Maps require explicit setting-- will do nothing for structs.
   658  	// Returns false on failure.
   659  	confirmSet(key string, v reflect.Value) bool
   660  }
   661  
   662  type stringMapAdaptor reflect.Value
   663  
   664  func (a stringMapAdaptor) len() int {
   665  	return reflect.Value(a).Len()
   666  }
   667  
   668  func (a stringMapAdaptor) keys() []string {
   669  	v := reflect.Value(a)
   670  	keys := make([]string, v.Len())
   671  	for i, v := range v.MapKeys() {
   672  		if v.IsNil() {
   673  			continue
   674  		}
   675  		switch t := v.Interface().(type) {
   676  		case string:
   677  			keys[i] = t
   678  		}
   679  	}
   680  	return keys
   681  }
   682  
   683  func (a stringMapAdaptor) tagOf(key string) reflect.StructTag {
   684  	return ""
   685  }
   686  
   687  func (a stringMapAdaptor) value(key string) reflect.Value {
   688  	return reflect.Value(a).MapIndex(reflect.ValueOf(key))
   689  }
   690  
   691  func (a stringMapAdaptor) confirmSet(key string, v reflect.Value) bool {
   692  	return true
   693  }
   694  
   695  type structAdaptor reflect.Value
   696  
   697  func (a structAdaptor) len() int {
   698  	v := reflect.Value(a)
   699  	return v.Type().NumField()
   700  }
   701  
   702  func (a structAdaptor) keys() []string {
   703  	v := reflect.Value(a)
   704  	t := v.Type()
   705  	keys := make([]string, t.NumField())
   706  	for i := range keys {
   707  		keys[i] = t.Field(i).Name
   708  	}
   709  	return keys
   710  }
   711  
   712  func (a structAdaptor) tagOf(key string) reflect.StructTag {
   713  	v := reflect.Value(a)
   714  	field, ok := v.Type().FieldByName(key)
   715  	if ok {
   716  		return field.Tag
   717  	}
   718  	return ""
   719  }
   720  
   721  func (a structAdaptor) value(key string) reflect.Value {
   722  	v := reflect.Value(a)
   723  	return v.FieldByName(key)
   724  }
   725  
   726  func (a structAdaptor) confirmSet(key string, v reflect.Value) bool {
   727  	return true
   728  }
   729  
   730  // convertKV can convert things that consist of key/value pairs, like structs
   731  // and some maps.
   732  func (c *Converter) convertKV(skv, dkv kvValue, scope *scope) error {
   733  	if skv == nil || dkv == nil {
   734  		// TODO: add keys to stack to support really understandable error messages.
   735  		return fmt.Errorf("Unable to convert %#v to %#v", skv, dkv)
   736  	}
   737  
   738  	lister := dkv
   739  	if scope.flags.IsSet(SourceToDest) {
   740  		lister = skv
   741  	}
   742  
   743  	var mapping FieldMappingFunc
   744  	if scope.meta != nil && scope.meta.KeyNameMapping != nil {
   745  		mapping = scope.meta.KeyNameMapping
   746  	}
   747  
   748  	for _, key := range lister.keys() {
   749  		if found, err := c.checkField(key, skv, dkv, scope); found {
   750  			if err != nil {
   751  				return err
   752  			}
   753  			continue
   754  		}
   755  		stag := skv.tagOf(key)
   756  		dtag := dkv.tagOf(key)
   757  		skey := key
   758  		dkey := key
   759  		if mapping != nil {
   760  			skey, dkey = scope.meta.KeyNameMapping(key, stag, dtag)
   761  		}
   762  
   763  		df := dkv.value(dkey)
   764  		sf := skv.value(skey)
   765  		if !df.IsValid() || !sf.IsValid() {
   766  			switch {
   767  			case scope.flags.IsSet(IgnoreMissingFields):
   768  				// No error.
   769  			case scope.flags.IsSet(SourceToDest):
   770  				return scope.errorf("%v not present in dest", dkey)
   771  			default:
   772  				return scope.errorf("%v not present in src", skey)
   773  			}
   774  			continue
   775  		}
   776  		scope.srcStack.top().key = skey
   777  		scope.srcStack.top().tag = stag
   778  		scope.destStack.top().key = dkey
   779  		scope.destStack.top().tag = dtag
   780  		if err := c.convert(sf, df, scope); err != nil {
   781  			return err
   782  		}
   783  	}
   784  	return nil
   785  }
   786  
   787  // checkField returns true if the field name matches any of the struct
   788  // field copying rules. The error should be ignored if it returns false.
   789  func (c *Converter) checkField(fieldName string, skv, dkv kvValue, scope *scope) (bool, error) {
   790  	replacementMade := false
   791  	if scope.flags.IsSet(DestFromSource) {
   792  		df := dkv.value(fieldName)
   793  		if !df.IsValid() {
   794  			return false, nil
   795  		}
   796  		destKey := typeNamePair{df.Type(), fieldName}
   797  		// Check each of the potential source (type, name) pairs to see if they're
   798  		// present in sv.
   799  		for _, potentialSourceKey := range c.structFieldSources[destKey] {
   800  			sf := skv.value(potentialSourceKey.fieldName)
   801  			if !sf.IsValid() {
   802  				continue
   803  			}
   804  			if sf.Type() == potentialSourceKey.fieldType {
   805  				// Both the source's name and type matched, so copy.
   806  				scope.srcStack.top().key = potentialSourceKey.fieldName
   807  				scope.destStack.top().key = fieldName
   808  				if err := c.convert(sf, df, scope); err != nil {
   809  					return true, err
   810  				}
   811  				dkv.confirmSet(fieldName, df)
   812  				replacementMade = true
   813  			}
   814  		}
   815  		return replacementMade, nil
   816  	}
   817  
   818  	sf := skv.value(fieldName)
   819  	if !sf.IsValid() {
   820  		return false, nil
   821  	}
   822  	srcKey := typeNamePair{sf.Type(), fieldName}
   823  	// Check each of the potential dest (type, name) pairs to see if they're
   824  	// present in dv.
   825  	for _, potentialDestKey := range c.structFieldDests[srcKey] {
   826  		df := dkv.value(potentialDestKey.fieldName)
   827  		if !df.IsValid() {
   828  			continue
   829  		}
   830  		if df.Type() == potentialDestKey.fieldType {
   831  			// Both the dest's name and type matched, so copy.
   832  			scope.srcStack.top().key = fieldName
   833  			scope.destStack.top().key = potentialDestKey.fieldName
   834  			if err := c.convert(sf, df, scope); err != nil {
   835  				return true, err
   836  			}
   837  			dkv.confirmSet(potentialDestKey.fieldName, df)
   838  			replacementMade = true
   839  		}
   840  	}
   841  	return replacementMade, nil
   842  }