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