You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2014 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. // Based on src/pkg/reflect/deepequal.go from official
  6. // golang's stdlib.
  7. package mergo
  8. import (
  9. "fmt"
  10. "reflect"
  11. "unicode"
  12. "unicode/utf8"
  13. )
  14. func changeInitialCase(s string, mapper func(rune) rune) string {
  15. if s == "" {
  16. return s
  17. }
  18. r, n := utf8.DecodeRuneInString(s)
  19. return string(mapper(r)) + s[n:]
  20. }
  21. func isExported(field reflect.StructField) bool {
  22. r, _ := utf8.DecodeRuneInString(field.Name)
  23. return r >= 'A' && r <= 'Z'
  24. }
  25. // Traverses recursively both values, assigning src's fields values to dst.
  26. // The map argument tracks comparisons that have already been seen, which allows
  27. // short circuiting on recursive types.
  28. func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
  29. overwrite := config.Overwrite
  30. if dst.CanAddr() {
  31. addr := dst.UnsafeAddr()
  32. h := 17 * addr
  33. seen := visited[h]
  34. typ := dst.Type()
  35. for p := seen; p != nil; p = p.next {
  36. if p.ptr == addr && p.typ == typ {
  37. return nil
  38. }
  39. }
  40. // Remember, remember...
  41. visited[h] = &visit{addr, typ, seen}
  42. }
  43. zeroValue := reflect.Value{}
  44. switch dst.Kind() {
  45. case reflect.Map:
  46. dstMap := dst.Interface().(map[string]interface{})
  47. for i, n := 0, src.NumField(); i < n; i++ {
  48. srcType := src.Type()
  49. field := srcType.Field(i)
  50. if !isExported(field) {
  51. continue
  52. }
  53. fieldName := field.Name
  54. fieldName = changeInitialCase(fieldName, unicode.ToLower)
  55. if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) {
  56. dstMap[fieldName] = src.Field(i).Interface()
  57. }
  58. }
  59. case reflect.Ptr:
  60. if dst.IsNil() {
  61. v := reflect.New(dst.Type().Elem())
  62. dst.Set(v)
  63. }
  64. dst = dst.Elem()
  65. fallthrough
  66. case reflect.Struct:
  67. srcMap := src.Interface().(map[string]interface{})
  68. for key := range srcMap {
  69. config.overwriteWithEmptyValue = true
  70. srcValue := srcMap[key]
  71. fieldName := changeInitialCase(key, unicode.ToUpper)
  72. dstElement := dst.FieldByName(fieldName)
  73. if dstElement == zeroValue {
  74. // We discard it because the field doesn't exist.
  75. continue
  76. }
  77. srcElement := reflect.ValueOf(srcValue)
  78. dstKind := dstElement.Kind()
  79. srcKind := srcElement.Kind()
  80. if srcKind == reflect.Ptr && dstKind != reflect.Ptr {
  81. srcElement = srcElement.Elem()
  82. srcKind = reflect.TypeOf(srcElement.Interface()).Kind()
  83. } else if dstKind == reflect.Ptr {
  84. // Can this work? I guess it can't.
  85. if srcKind != reflect.Ptr && srcElement.CanAddr() {
  86. srcPtr := srcElement.Addr()
  87. srcElement = reflect.ValueOf(srcPtr)
  88. srcKind = reflect.Ptr
  89. }
  90. }
  91. if !srcElement.IsValid() {
  92. continue
  93. }
  94. if srcKind == dstKind {
  95. if _, err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
  96. return
  97. }
  98. } else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
  99. if _, err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
  100. return
  101. }
  102. } else if srcKind == reflect.Map {
  103. if err = deepMap(dstElement, srcElement, visited, depth+1, config); err != nil {
  104. return
  105. }
  106. } else {
  107. return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
  108. }
  109. }
  110. }
  111. return
  112. }
  113. // Map sets fields' values in dst from src.
  114. // src can be a map with string keys or a struct. dst must be the opposite:
  115. // if src is a map, dst must be a valid pointer to struct. If src is a struct,
  116. // dst must be map[string]interface{}.
  117. // It won't merge unexported (private) fields and will do recursively
  118. // any exported field.
  119. // If dst is a map, keys will be src fields' names in lower camel case.
  120. // Missing key in src that doesn't match a field in dst will be skipped. This
  121. // doesn't apply if dst is a map.
  122. // This is separated method from Merge because it is cleaner and it keeps sane
  123. // semantics: merging equal types, mapping different (restricted) types.
  124. func Map(dst, src interface{}, opts ...func(*Config)) error {
  125. return _map(dst, src, opts...)
  126. }
  127. // MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overridden by
  128. // non-empty src attribute values.
  129. // Deprecated: Use Map(…) with WithOverride
  130. func MapWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
  131. return _map(dst, src, append(opts, WithOverride)...)
  132. }
  133. func _map(dst, src interface{}, opts ...func(*Config)) error {
  134. var (
  135. vDst, vSrc reflect.Value
  136. err error
  137. )
  138. config := &Config{}
  139. for _, opt := range opts {
  140. opt(config)
  141. }
  142. if vDst, vSrc, err = resolveValues(dst, src); err != nil {
  143. return err
  144. }
  145. // To be friction-less, we redirect equal-type arguments
  146. // to deepMerge. Only because arguments can be anything.
  147. if vSrc.Kind() == vDst.Kind() {
  148. _, err := deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
  149. return err
  150. }
  151. switch vSrc.Kind() {
  152. case reflect.Struct:
  153. if vDst.Kind() != reflect.Map {
  154. return ErrExpectedMapAsDestination
  155. }
  156. case reflect.Map:
  157. if vDst.Kind() != reflect.Struct {
  158. return ErrExpectedStructAsDestination
  159. }
  160. default:
  161. return ErrNotSupported
  162. }
  163. return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, config)
  164. }