1/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package conversion
18
19import (
20	"fmt"
21	"reflect"
22)
23
24type typePair struct {
25	source reflect.Type
26	dest   reflect.Type
27}
28
29type typeNamePair struct {
30	fieldType reflect.Type
31	fieldName string
32}
33
34// DebugLogger allows you to get debugging messages if necessary.
35type DebugLogger interface {
36	Logf(format string, args ...interface{})
37}
38
39type NameFunc func(t reflect.Type) string
40
41var 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.
47type ConversionFunc func(a, b interface{}, scope Scope) error
48
49// Converter knows how to convert one type to another.
50type 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.
84func 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.
102func (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.
109func (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
116func 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.
129type 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.
152type FieldMappingFunc func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string)
153
154func NewConversionFuncs() ConversionFuncs {
155	return ConversionFuncs{
156		fns:     make(map[typePair]reflect.Value),
157		untyped: make(map[typePair]ConversionFunc),
158	}
159}
160
161type 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.
169func (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.
184func (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.
198func (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.
216type 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.
225type 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
236type scopeStackElem struct {
237	tag   reflect.StructTag
238	value reflect.Value
239	key   string
240}
241
242type scopeStack []scopeStackElem
243
244func (s *scopeStack) pop() {
245	n := len(*s)
246	*s = (*s)[:n-1]
247}
248
249func (s *scopeStack) push(e scopeStackElem) {
250	*s = append(*s, e)
251}
252
253func (s *scopeStack) top() *scopeStackElem {
254	return &(*s)[len(*s)-1]
255}
256
257func (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.
277func (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.
283func (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.
289func (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.
295func (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.
300func (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.
305func (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.
310func (s *scope) Flags() FieldMatchingFlags {
311	return s.flags
312}
313
314// Meta returns the meta object that was originally passed to Convert.
315func (s *scope) Meta() *Meta {
316	return s.meta
317}
318
319// describe prints the path to get to the current (source, dest) values.
320func (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.
326func (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.
333func 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
375func (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
382func (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.
389func (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.
396func (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.
402func (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.
419func (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.
432type FieldMatchingFlags int
433
434const (
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.
453func (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!
469func (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!
481func (c *Converter) DefaultConvert(src, dest interface{}, flags FieldMatchingFlags, meta *Meta) error {
482	return c.doConversion(src, dest, flags, meta, c.defaultConvert)
483}
484
485type conversionFunc func(sv, dv reflect.Value, scope *scope) error
486
487func (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.
521func (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.
551func (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)
582func (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
689var stringType = reflect.TypeOf("")
690
691func 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.
706type 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
718type stringMapAdaptor reflect.Value
719
720func (a stringMapAdaptor) len() int {
721	return reflect.Value(a).Len()
722}
723
724func (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
739func (a stringMapAdaptor) tagOf(key string) reflect.StructTag {
740	return ""
741}
742
743func (a stringMapAdaptor) value(key string) reflect.Value {
744	return reflect.Value(a).MapIndex(reflect.ValueOf(key))
745}
746
747func (a stringMapAdaptor) confirmSet(key string, v reflect.Value) bool {
748	return true
749}
750
751type structAdaptor reflect.Value
752
753func (a structAdaptor) len() int {
754	v := reflect.Value(a)
755	return v.Type().NumField()
756}
757
758func (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
768func (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
777func (a structAdaptor) value(key string) reflect.Value {
778	v := reflect.Value(a)
779	return v.FieldByName(key)
780}
781
782func (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.
788func (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.
845func (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}
899