aboutsummaryrefslogtreecommitdiffsponsor
path: root/vendor/dario.cat/mergo/merge.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/dario.cat/mergo/merge.go')
-rw-r--r--vendor/dario.cat/mergo/merge.go409
1 files changed, 0 insertions, 409 deletions
diff --git a/vendor/dario.cat/mergo/merge.go b/vendor/dario.cat/mergo/merge.go
deleted file mode 100644
index 0ef9b21..0000000
--- a/vendor/dario.cat/mergo/merge.go
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright 2013 Dario Castañé. All rights reserved.
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Based on src/pkg/reflect/deepequal.go from official
-// golang's stdlib.
-
-package mergo
-
-import (
- "fmt"
- "reflect"
-)
-
-func hasMergeableFields(dst reflect.Value) (exported bool) {
- for i, n := 0, dst.NumField(); i < n; i++ {
- field := dst.Type().Field(i)
- if field.Anonymous && dst.Field(i).Kind() == reflect.Struct {
- exported = exported || hasMergeableFields(dst.Field(i))
- } else if isExportedComponent(&field) {
- exported = exported || len(field.PkgPath) == 0
- }
- }
- return
-}
-
-func isExportedComponent(field *reflect.StructField) bool {
- pkgPath := field.PkgPath
- if len(pkgPath) > 0 {
- return false
- }
- c := field.Name[0]
- if 'a' <= c && c <= 'z' || c == '_' {
- return false
- }
- return true
-}
-
-type Config struct {
- Transformers Transformers
- Overwrite bool
- ShouldNotDereference bool
- AppendSlice bool
- TypeCheck bool
- overwriteWithEmptyValue bool
- overwriteSliceWithEmptyValue bool
- sliceDeepCopy bool
- debug bool
-}
-
-type Transformers interface {
- Transformer(reflect.Type) func(dst, src reflect.Value) error
-}
-
-// Traverses recursively both values, assigning src's fields values to dst.
-// The map argument tracks comparisons that have already been seen, which allows
-// short circuiting on recursive types.
-func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
- overwrite := config.Overwrite
- typeCheck := config.TypeCheck
- overwriteWithEmptySrc := config.overwriteWithEmptyValue
- overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue
- sliceDeepCopy := config.sliceDeepCopy
-
- if !src.IsValid() {
- return
- }
- if dst.CanAddr() {
- addr := dst.UnsafeAddr()
- h := 17 * addr
- seen := visited[h]
- typ := dst.Type()
- for p := seen; p != nil; p = p.next {
- if p.ptr == addr && p.typ == typ {
- return nil
- }
- }
- // Remember, remember...
- visited[h] = &visit{typ, seen, addr}
- }
-
- if config.Transformers != nil && !isReflectNil(dst) && dst.IsValid() {
- if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
- err = fn(dst, src)
- return
- }
- }
-
- switch dst.Kind() {
- case reflect.Struct:
- if hasMergeableFields(dst) {
- for i, n := 0, dst.NumField(); i < n; i++ {
- if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil {
- return
- }
- }
- } else {
- if dst.CanSet() && (isReflectNil(dst) || overwrite) && (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc) {
- dst.Set(src)
- }
- }
- case reflect.Map:
- if dst.IsNil() && !src.IsNil() {
- if dst.CanSet() {
- dst.Set(reflect.MakeMap(dst.Type()))
- } else {
- dst = src
- return
- }
- }
-
- if src.Kind() != reflect.Map {
- if overwrite && dst.CanSet() {
- dst.Set(src)
- }
- return
- }
-
- for _, key := range src.MapKeys() {
- srcElement := src.MapIndex(key)
- if !srcElement.IsValid() {
- continue
- }
- dstElement := dst.MapIndex(key)
- switch srcElement.Kind() {
- case reflect.Chan, reflect.Func, reflect.Map, reflect.Interface, reflect.Slice:
- if srcElement.IsNil() {
- if overwrite {
- dst.SetMapIndex(key, srcElement)
- }
- continue
- }
- fallthrough
- default:
- if !srcElement.CanInterface() {
- continue
- }
- switch reflect.TypeOf(srcElement.Interface()).Kind() {
- case reflect.Struct:
- fallthrough
- case reflect.Ptr:
- fallthrough
- case reflect.Map:
- srcMapElm := srcElement
- dstMapElm := dstElement
- if srcMapElm.CanInterface() {
- srcMapElm = reflect.ValueOf(srcMapElm.Interface())
- if dstMapElm.IsValid() {
- dstMapElm = reflect.ValueOf(dstMapElm.Interface())
- }
- }
- if err = deepMerge(dstMapElm, srcMapElm, visited, depth+1, config); err != nil {
- return
- }
- case reflect.Slice:
- srcSlice := reflect.ValueOf(srcElement.Interface())
-
- var dstSlice reflect.Value
- if !dstElement.IsValid() || dstElement.IsNil() {
- dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
- } else {
- dstSlice = reflect.ValueOf(dstElement.Interface())
- }
-
- if (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) && !config.AppendSlice && !sliceDeepCopy {
- if typeCheck && srcSlice.Type() != dstSlice.Type() {
- return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
- }
- dstSlice = srcSlice
- } else if config.AppendSlice {
- if srcSlice.Type() != dstSlice.Type() {
- return fmt.Errorf("cannot append two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
- }
- dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
- } else if sliceDeepCopy {
- i := 0
- for ; i < srcSlice.Len() && i < dstSlice.Len(); i++ {
- srcElement := srcSlice.Index(i)
- dstElement := dstSlice.Index(i)
-
- if srcElement.CanInterface() {
- srcElement = reflect.ValueOf(srcElement.Interface())
- }
- if dstElement.CanInterface() {
- dstElement = reflect.ValueOf(dstElement.Interface())
- }
-
- if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
- return
- }
- }
-
- }
- dst.SetMapIndex(key, dstSlice)
- }
- }
-
- if dstElement.IsValid() && !isEmptyValue(dstElement, !config.ShouldNotDereference) {
- if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice {
- continue
- }
- if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map && reflect.TypeOf(dstElement.Interface()).Kind() == reflect.Map {
- continue
- }
- }
-
- if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement, !config.ShouldNotDereference)) {
- if dst.IsNil() {
- dst.Set(reflect.MakeMap(dst.Type()))
- }
- dst.SetMapIndex(key, srcElement)
- }
- }
-
- // Ensure that all keys in dst are deleted if they are not in src.
- if overwriteWithEmptySrc {
- for _, key := range dst.MapKeys() {
- srcElement := src.MapIndex(key)
- if !srcElement.IsValid() {
- dst.SetMapIndex(key, reflect.Value{})
- }
- }
- }
- case reflect.Slice:
- if !dst.CanSet() {
- break
- }
- if (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) && !config.AppendSlice && !sliceDeepCopy {
- dst.Set(src)
- } else if config.AppendSlice {
- if src.Type() != dst.Type() {
- return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type())
- }
- dst.Set(reflect.AppendSlice(dst, src))
- } else if sliceDeepCopy {
- for i := 0; i < src.Len() && i < dst.Len(); i++ {
- srcElement := src.Index(i)
- dstElement := dst.Index(i)
- if srcElement.CanInterface() {
- srcElement = reflect.ValueOf(srcElement.Interface())
- }
- if dstElement.CanInterface() {
- dstElement = reflect.ValueOf(dstElement.Interface())
- }
-
- if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
- return
- }
- }
- }
- case reflect.Ptr:
- fallthrough
- case reflect.Interface:
- if isReflectNil(src) {
- if overwriteWithEmptySrc && dst.CanSet() && src.Type().AssignableTo(dst.Type()) {
- dst.Set(src)
- }
- break
- }
-
- if src.Kind() != reflect.Interface {
- if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) {
- if dst.CanSet() && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) {
- dst.Set(src)
- }
- } else if src.Kind() == reflect.Ptr {
- if !config.ShouldNotDereference {
- if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
- return
- }
- } else {
- if overwriteWithEmptySrc || (overwrite && !src.IsNil()) || dst.IsNil() {
- dst.Set(src)
- }
- }
- } else if dst.Elem().Type() == src.Type() {
- if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
- return
- }
- } else {
- return ErrDifferentArgumentsTypes
- }
- break
- }
-
- if dst.IsNil() || overwrite {
- if dst.CanSet() && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) {
- dst.Set(src)
- }
- break
- }
-
- if dst.Elem().Kind() == src.Elem().Kind() {
- if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
- return
- }
- break
- }
- default:
- mustSet := (isEmptyValue(dst, !config.ShouldNotDereference) || overwrite) && (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc)
- if mustSet {
- if dst.CanSet() {
- dst.Set(src)
- } else {
- dst = src
- }
- }
- }
-
- return
-}
-
-// Merge will fill any empty for value type attributes on the dst struct using corresponding
-// src attributes if they themselves are not empty. dst and src must be valid same-type structs
-// and dst must be a pointer to struct.
-// It won't merge unexported (private) fields and will do recursively any exported field.
-func Merge(dst, src interface{}, opts ...func(*Config)) error {
- return merge(dst, src, opts...)
-}
-
-// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by
-// non-empty src attribute values.
-// Deprecated: use Merge(…) with WithOverride
-func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
- return merge(dst, src, append(opts, WithOverride)...)
-}
-
-// WithTransformers adds transformers to merge, allowing to customize the merging of some types.
-func WithTransformers(transformers Transformers) func(*Config) {
- return func(config *Config) {
- config.Transformers = transformers
- }
-}
-
-// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
-func WithOverride(config *Config) {
- config.Overwrite = true
-}
-
-// WithOverwriteWithEmptyValue will make merge override non empty dst attributes with empty src attributes values.
-func WithOverwriteWithEmptyValue(config *Config) {
- config.Overwrite = true
- config.overwriteWithEmptyValue = true
-}
-
-// WithOverrideEmptySlice will make merge override empty dst slice with empty src slice.
-func WithOverrideEmptySlice(config *Config) {
- config.overwriteSliceWithEmptyValue = true
-}
-
-// WithoutDereference prevents dereferencing pointers when evaluating whether they are empty
-// (i.e. a non-nil pointer is never considered empty).
-func WithoutDereference(config *Config) {
- config.ShouldNotDereference = true
-}
-
-// WithAppendSlice will make merge append slices instead of overwriting it.
-func WithAppendSlice(config *Config) {
- config.AppendSlice = true
-}
-
-// WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
-func WithTypeCheck(config *Config) {
- config.TypeCheck = true
-}
-
-// WithSliceDeepCopy will merge slice element one by one with Overwrite flag.
-func WithSliceDeepCopy(config *Config) {
- config.sliceDeepCopy = true
- config.Overwrite = true
-}
-
-func merge(dst, src interface{}, opts ...func(*Config)) error {
- if dst != nil && reflect.ValueOf(dst).Kind() != reflect.Ptr {
- return ErrNonPointerArgument
- }
- var (
- vDst, vSrc reflect.Value
- err error
- )
-
- config := &Config{}
-
- for _, opt := range opts {
- opt(config)
- }
-
- if vDst, vSrc, err = resolveValues(dst, src); err != nil {
- return err
- }
- if vDst.Type() != vSrc.Type() {
- return ErrDifferentArgumentsTypes
- }
- return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
-}
-
-// IsReflectNil is the reflect value provided nil
-func isReflectNil(v reflect.Value) bool {
- k := v.Kind()
- switch k {
- case reflect.Interface, reflect.Slice, reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr:
- // Both interface and slice are nil if first word is 0.
- // Both are always bigger than a word; assume flagIndir.
- return v.IsNil()
- default:
- return false
- }
-}