Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / imdario / mergo / mergo.go
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
9 package mergo
10
11 import (
12         "errors"
13         "reflect"
14 )
15
16 // Errors reported by Mergo when it finds invalid arguments.
17 var (
18         ErrNilArguments                = errors.New("src and dst must not be nil")
19         ErrDifferentArgumentsTypes     = errors.New("src and dst must be of same type")
20         ErrNotSupported                = errors.New("only structs and maps are supported")
21         ErrExpectedMapAsDestination    = errors.New("dst was expected to be a map")
22         ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
23 )
24
25 // During deepMerge, must keep track of checks that are
26 // in progress.  The comparison algorithm assumes that all
27 // checks in progress are true when it reencounters them.
28 // Visited are stored in a map indexed by 17 * a1 + a2;
29 type visit struct {
30         ptr  uintptr
31         typ  reflect.Type
32         next *visit
33 }
34
35 // From src/pkg/encoding/json/encode.go.
36 func isEmptyValue(v reflect.Value) bool {
37         switch v.Kind() {
38         case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
39                 return v.Len() == 0
40         case reflect.Bool:
41                 return !v.Bool()
42         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
43                 return v.Int() == 0
44         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
45                 return v.Uint() == 0
46         case reflect.Float32, reflect.Float64:
47                 return v.Float() == 0
48         case reflect.Interface, reflect.Ptr:
49                 if v.IsNil() {
50                         return true
51                 }
52                 return isEmptyValue(v.Elem())
53         case reflect.Func:
54                 return v.IsNil()
55         case reflect.Invalid:
56                 return true
57         }
58         return false
59 }
60
61 func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
62         if dst == nil || src == nil {
63                 err = ErrNilArguments
64                 return
65         }
66         vDst = reflect.ValueOf(dst).Elem()
67         if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
68                 err = ErrNotSupported
69                 return
70         }
71         vSrc = reflect.ValueOf(src)
72         // We check if vSrc is a pointer to dereference it.
73         if vSrc.Kind() == reflect.Ptr {
74                 vSrc = vSrc.Elem()
75         }
76         return
77 }
78
79 // Traverses recursively both values, assigning src's fields values to dst.
80 // The map argument tracks comparisons that have already been seen, which allows
81 // short circuiting on recursive types.
82 func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
83         if dst.CanAddr() {
84                 addr := dst.UnsafeAddr()
85                 h := 17 * addr
86                 seen := visited[h]
87                 typ := dst.Type()
88                 for p := seen; p != nil; p = p.next {
89                         if p.ptr == addr && p.typ == typ {
90                                 return nil
91                         }
92                 }
93                 // Remember, remember...
94                 visited[h] = &visit{addr, typ, seen}
95         }
96         return // TODO refactor
97 }