1// Copyright 2013 Dario Castañé. All rights reserved.
2// Copyright 2009 The Go Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6// Based on src/pkg/reflect/deepequal.go from official
7// golang's stdlib.
8
9package mergo
10
11import (
12	"fmt"
13	"reflect"
14)
15
16func hasMergeableFields(dst reflect.Value) (exported bool) {
17	for i, n := 0, dst.NumField(); i < n; i++ {
18		field := dst.Type().Field(i)
19		if field.Anonymous && dst.Field(i).Kind() == reflect.Struct {
20			exported = exported || hasMergeableFields(dst.Field(i))
21		} else if isExportedComponent(&field) {
22			exported = exported || len(field.PkgPath) == 0
23		}
24	}
25	return
26}
27
28func isExportedComponent(field *reflect.StructField) bool {
29	pkgPath := field.PkgPath
30	if len(pkgPath) > 0 {
31		return false
32	}
33	c := field.Name[0]
34	if 'a' <= c && c <= 'z' || c == '_' {
35		return false
36	}
37	return true
38}
39
40type Config struct {
41	Overwrite                    bool
42	AppendSlice                  bool
43	TypeCheck                    bool
44	Transformers                 Transformers
45	overwriteWithEmptyValue      bool
46	overwriteSliceWithEmptyValue bool
47	sliceDeepCopy                bool
48	debug                        bool
49}
50
51type Transformers interface {
52	Transformer(reflect.Type) func(dst, src reflect.Value) error
53}
54
55// Traverses recursively both values, assigning src's fields values to dst.
56// The map argument tracks comparisons that have already been seen, which allows
57// short circuiting on recursive types.
58func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
59	overwrite := config.Overwrite
60	typeCheck := config.TypeCheck
61	overwriteWithEmptySrc := config.overwriteWithEmptyValue
62	overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue
63	sliceDeepCopy := config.sliceDeepCopy
64
65	if !src.IsValid() {
66		return
67	}
68	if dst.CanAddr() {
69		addr := dst.UnsafeAddr()
70		h := 17 * addr
71		seen := visited[h]
72		typ := dst.Type()
73		for p := seen; p != nil; p = p.next {
74			if p.ptr == addr && p.typ == typ {
75				return nil
76			}
77		}
78		// Remember, remember...
79		visited[h] = &visit{addr, typ, seen}
80	}
81
82	if config.Transformers != nil && !isEmptyValue(dst) {
83		if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
84			err = fn(dst, src)
85			return
86		}
87	}
88
89	switch dst.Kind() {
90	case reflect.Struct:
91		if hasMergeableFields(dst) {
92			for i, n := 0, dst.NumField(); i < n; i++ {
93				if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil {
94					return
95				}
96			}
97		} else {
98			if (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) {
99				dst.Set(src)
100			}
101		}
102	case reflect.Map:
103		if dst.IsNil() && !src.IsNil() {
104			dst.Set(reflect.MakeMap(dst.Type()))
105		}
106
107		if src.Kind() != reflect.Map {
108			if overwrite {
109				dst.Set(src)
110			}
111			return
112		}
113
114		for _, key := range src.MapKeys() {
115			srcElement := src.MapIndex(key)
116			if !srcElement.IsValid() {
117				continue
118			}
119			dstElement := dst.MapIndex(key)
120			switch srcElement.Kind() {
121			case reflect.Chan, reflect.Func, reflect.Map, reflect.Interface, reflect.Slice:
122				if srcElement.IsNil() {
123					if overwrite {
124						dst.SetMapIndex(key, srcElement)
125					}
126					continue
127				}
128				fallthrough
129			default:
130				if !srcElement.CanInterface() {
131					continue
132				}
133				switch reflect.TypeOf(srcElement.Interface()).Kind() {
134				case reflect.Struct:
135					fallthrough
136				case reflect.Ptr:
137					fallthrough
138				case reflect.Map:
139					srcMapElm := srcElement
140					dstMapElm := dstElement
141					if srcMapElm.CanInterface() {
142						srcMapElm = reflect.ValueOf(srcMapElm.Interface())
143						if dstMapElm.IsValid() {
144							dstMapElm = reflect.ValueOf(dstMapElm.Interface())
145						}
146					}
147					if err = deepMerge(dstMapElm, srcMapElm, visited, depth+1, config); err != nil {
148						return
149					}
150				case reflect.Slice:
151					srcSlice := reflect.ValueOf(srcElement.Interface())
152
153					var dstSlice reflect.Value
154					if !dstElement.IsValid() || dstElement.IsNil() {
155						dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
156					} else {
157						dstSlice = reflect.ValueOf(dstElement.Interface())
158					}
159
160					if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice && !sliceDeepCopy {
161						if typeCheck && srcSlice.Type() != dstSlice.Type() {
162							return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
163						}
164						dstSlice = srcSlice
165					} else if config.AppendSlice {
166						if srcSlice.Type() != dstSlice.Type() {
167							return fmt.Errorf("cannot append two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
168						}
169						dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
170					} else if sliceDeepCopy {
171						i := 0
172						for ; i < srcSlice.Len() && i < dstSlice.Len(); i++ {
173							srcElement := srcSlice.Index(i)
174							dstElement := dstSlice.Index(i)
175
176							if srcElement.CanInterface() {
177								srcElement = reflect.ValueOf(srcElement.Interface())
178							}
179							if dstElement.CanInterface() {
180								dstElement = reflect.ValueOf(dstElement.Interface())
181							}
182
183							if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
184								return
185							}
186						}
187
188					}
189					dst.SetMapIndex(key, dstSlice)
190				}
191			}
192			if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) {
193				continue
194			}
195
196			if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement)) {
197				if dst.IsNil() {
198					dst.Set(reflect.MakeMap(dst.Type()))
199				}
200				dst.SetMapIndex(key, srcElement)
201			}
202		}
203	case reflect.Slice:
204		if !dst.CanSet() {
205			break
206		}
207		if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice && !sliceDeepCopy {
208			dst.Set(src)
209		} else if config.AppendSlice {
210			if src.Type() != dst.Type() {
211				return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type())
212			}
213			dst.Set(reflect.AppendSlice(dst, src))
214		} else if sliceDeepCopy {
215			for i := 0; i < src.Len() && i < dst.Len(); i++ {
216				srcElement := src.Index(i)
217				dstElement := dst.Index(i)
218				if srcElement.CanInterface() {
219					srcElement = reflect.ValueOf(srcElement.Interface())
220				}
221				if dstElement.CanInterface() {
222					dstElement = reflect.ValueOf(dstElement.Interface())
223				}
224
225				if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
226					return
227				}
228			}
229		}
230	case reflect.Ptr:
231		fallthrough
232	case reflect.Interface:
233		if isReflectNil(src) {
234			if overwriteWithEmptySrc && dst.CanSet() && src.Type().AssignableTo(dst.Type()) {
235				dst.Set(src)
236			}
237			break
238		}
239
240		if src.Kind() != reflect.Interface {
241			if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) {
242				if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
243					dst.Set(src)
244				}
245			} else if src.Kind() == reflect.Ptr {
246				if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
247					return
248				}
249			} else if dst.Elem().Type() == src.Type() {
250				if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
251					return
252				}
253			} else {
254				return ErrDifferentArgumentsTypes
255			}
256			break
257		}
258
259		if dst.IsNil() || overwrite {
260			if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
261				dst.Set(src)
262			}
263			break
264		}
265
266		if dst.Elem().Kind() == src.Elem().Kind() {
267			if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
268				return
269			}
270			break
271		}
272	default:
273		mustSet := (isEmptyValue(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc)
274		if mustSet {
275			if dst.CanSet() {
276				dst.Set(src)
277			} else {
278				dst = src
279			}
280		}
281	}
282
283	return
284}
285
286// Merge will fill any empty for value type attributes on the dst struct using corresponding
287// src attributes if they themselves are not empty. dst and src must be valid same-type structs
288// and dst must be a pointer to struct.
289// It won't merge unexported (private) fields and will do recursively any exported field.
290func Merge(dst, src interface{}, opts ...func(*Config)) error {
291	return merge(dst, src, opts...)
292}
293
294// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by
295// non-empty src attribute values.
296// Deprecated: use Merge(…) with WithOverride
297func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
298	return merge(dst, src, append(opts, WithOverride)...)
299}
300
301// WithTransformers adds transformers to merge, allowing to customize the merging of some types.
302func WithTransformers(transformers Transformers) func(*Config) {
303	return func(config *Config) {
304		config.Transformers = transformers
305	}
306}
307
308// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
309func WithOverride(config *Config) {
310	config.Overwrite = true
311}
312
313// WithOverwriteWithEmptyValue will make merge override non empty dst attributes with empty src attributes values.
314func WithOverwriteWithEmptyValue(config *Config) {
315	config.Overwrite = true
316	config.overwriteWithEmptyValue = true
317}
318
319// WithOverrideEmptySlice will make merge override empty dst slice with empty src slice.
320func WithOverrideEmptySlice(config *Config) {
321	config.overwriteSliceWithEmptyValue = true
322}
323
324// WithAppendSlice will make merge append slices instead of overwriting it.
325func WithAppendSlice(config *Config) {
326	config.AppendSlice = true
327}
328
329// WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
330func WithTypeCheck(config *Config) {
331	config.TypeCheck = true
332}
333
334// WithSliceDeepCopy will merge slice element one by one with Overwrite flag.
335func WithSliceDeepCopy(config *Config) {
336	config.sliceDeepCopy = true
337	config.Overwrite = true
338}
339
340func merge(dst, src interface{}, opts ...func(*Config)) error {
341	if dst != nil && reflect.ValueOf(dst).Kind() != reflect.Ptr {
342		return ErrNonPointerAgument
343	}
344	var (
345		vDst, vSrc reflect.Value
346		err        error
347	)
348
349	config := &Config{}
350
351	for _, opt := range opts {
352		opt(config)
353	}
354
355	if vDst, vSrc, err = resolveValues(dst, src); err != nil {
356		return err
357	}
358	if vDst.Type() != vSrc.Type() {
359		return ErrDifferentArgumentsTypes
360	}
361	return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
362}
363
364// IsReflectNil is the reflect value provided nil
365func isReflectNil(v reflect.Value) bool {
366	k := v.Kind()
367	switch k {
368	case reflect.Interface, reflect.Slice, reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr:
369		// Both interface and slice are nil if first word is 0.
370		// Both are always bigger than a word; assume flagIndir.
371		return v.IsNil()
372	default:
373		return false
374	}
375}
376