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