Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

merge.go 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. // Based on src/pkg/reflect/deepequal.go from official
  6. // golang's stdlib.
  7. package mergo
  8. import (
  9. "fmt"
  10. "reflect"
  11. "unsafe"
  12. )
  13. func hasExportedField(dst reflect.Value) (exported bool) {
  14. for i, n := 0, dst.NumField(); i < n; i++ {
  15. field := dst.Type().Field(i)
  16. if isExportedComponent(&field) {
  17. return true
  18. }
  19. }
  20. return
  21. }
  22. func isExportedComponent(field *reflect.StructField) bool {
  23. name := field.Name
  24. pkgPath := field.PkgPath
  25. if len(pkgPath) > 0 {
  26. return false
  27. }
  28. c := name[0]
  29. if 'a' <= c && c <= 'z' || c == '_' {
  30. return false
  31. }
  32. return true
  33. }
  34. type Config struct {
  35. Overwrite bool
  36. AppendSlice bool
  37. TypeCheck bool
  38. Transformers Transformers
  39. overwriteWithEmptyValue bool
  40. overwriteSliceWithEmptyValue bool
  41. }
  42. type Transformers interface {
  43. Transformer(reflect.Type) func(dst, src reflect.Value) error
  44. }
  45. // Traverses recursively both values, assigning src's fields values to dst.
  46. // The map argument tracks comparisons that have already been seen, which allows
  47. // short circuiting on recursive types.
  48. func deepMerge(dstIn, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (dst reflect.Value, err error) {
  49. dst = dstIn
  50. overwrite := config.Overwrite
  51. typeCheck := config.TypeCheck
  52. overwriteWithEmptySrc := config.overwriteWithEmptyValue
  53. overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue
  54. if !src.IsValid() {
  55. return
  56. }
  57. if dst.CanAddr() {
  58. addr := dst.UnsafeAddr()
  59. h := 17 * addr
  60. seen := visited[h]
  61. typ := dst.Type()
  62. for p := seen; p != nil; p = p.next {
  63. if p.ptr == addr && p.typ == typ {
  64. return dst, nil
  65. }
  66. }
  67. // Remember, remember...
  68. visited[h] = &visit{addr, typ, seen}
  69. }
  70. if config.Transformers != nil && !isEmptyValue(dst) {
  71. if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
  72. err = fn(dst, src)
  73. return
  74. }
  75. }
  76. if dst.IsValid() && src.IsValid() && src.Type() != dst.Type() {
  77. err = fmt.Errorf("cannot append two different types (%s, %s)", src.Kind(), dst.Kind())
  78. return
  79. }
  80. switch dst.Kind() {
  81. case reflect.Struct:
  82. if hasExportedField(dst) {
  83. dstCp := reflect.New(dst.Type()).Elem()
  84. for i, n := 0, dst.NumField(); i < n; i++ {
  85. dstField := dst.Field(i)
  86. structField := dst.Type().Field(i)
  87. // copy un-exported struct fields
  88. if !isExportedComponent(&structField) {
  89. rf := dstCp.Field(i)
  90. rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem() //nolint:gosec
  91. dstRF := dst.Field(i)
  92. if !dst.Field(i).CanAddr() {
  93. continue
  94. }
  95. dstRF = reflect.NewAt(dstRF.Type(), unsafe.Pointer(dstRF.UnsafeAddr())).Elem() //nolint:gosec
  96. rf.Set(dstRF)
  97. continue
  98. }
  99. dstField, err = deepMerge(dstField, src.Field(i), visited, depth+1, config)
  100. if err != nil {
  101. return
  102. }
  103. dstCp.Field(i).Set(dstField)
  104. }
  105. if dst.CanSet() {
  106. dst.Set(dstCp)
  107. } else {
  108. dst = dstCp
  109. }
  110. return
  111. } else {
  112. if (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) {
  113. dst = src
  114. }
  115. }
  116. case reflect.Map:
  117. if dst.IsNil() && !src.IsNil() {
  118. if dst.CanSet() {
  119. dst.Set(reflect.MakeMap(dst.Type()))
  120. } else {
  121. dst = src
  122. return
  123. }
  124. }
  125. for _, key := range src.MapKeys() {
  126. srcElement := src.MapIndex(key)
  127. dstElement := dst.MapIndex(key)
  128. if !srcElement.IsValid() {
  129. continue
  130. }
  131. if dst.MapIndex(key).IsValid() {
  132. k := dstElement.Interface()
  133. dstElement = reflect.ValueOf(k)
  134. }
  135. if isReflectNil(srcElement) {
  136. if overwrite || isReflectNil(dstElement) {
  137. dst.SetMapIndex(key, srcElement)
  138. }
  139. continue
  140. }
  141. if !srcElement.CanInterface() {
  142. continue
  143. }
  144. if srcElement.CanInterface() {
  145. srcElement = reflect.ValueOf(srcElement.Interface())
  146. if dstElement.IsValid() {
  147. dstElement = reflect.ValueOf(dstElement.Interface())
  148. }
  149. }
  150. dstElement, err = deepMerge(dstElement, srcElement, visited, depth+1, config)
  151. if err != nil {
  152. return
  153. }
  154. dst.SetMapIndex(key, dstElement)
  155. }
  156. case reflect.Slice:
  157. newSlice := dst
  158. if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
  159. if typeCheck && src.Type() != dst.Type() {
  160. return dst, fmt.Errorf("cannot override two slices with different type (%s, %s)", src.Type(), dst.Type())
  161. }
  162. newSlice = src
  163. } else if config.AppendSlice {
  164. if typeCheck && src.Type() != dst.Type() {
  165. err = fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type())
  166. return
  167. }
  168. newSlice = reflect.AppendSlice(dst, src)
  169. }
  170. if dst.CanSet() {
  171. dst.Set(newSlice)
  172. } else {
  173. dst = newSlice
  174. }
  175. case reflect.Ptr, reflect.Interface:
  176. if isReflectNil(src) {
  177. break
  178. }
  179. if dst.Kind() != reflect.Ptr && src.Type().AssignableTo(dst.Type()) {
  180. if dst.IsNil() || overwrite {
  181. if overwrite || isEmptyValue(dst) {
  182. if dst.CanSet() {
  183. dst.Set(src)
  184. } else {
  185. dst = src
  186. }
  187. }
  188. }
  189. break
  190. }
  191. if src.Kind() != reflect.Interface {
  192. if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) {
  193. if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
  194. dst.Set(src)
  195. }
  196. } else if src.Kind() == reflect.Ptr {
  197. if dst, err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
  198. return
  199. }
  200. dst = dst.Addr()
  201. } else if dst.Elem().Type() == src.Type() {
  202. if dst, err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
  203. return
  204. }
  205. } else {
  206. return dst, ErrDifferentArgumentsTypes
  207. }
  208. break
  209. }
  210. if dst.IsNil() || overwrite {
  211. if (overwrite || isEmptyValue(dst)) && (overwriteWithEmptySrc || !isEmptyValue(src)) {
  212. if dst.CanSet() {
  213. dst.Set(src)
  214. } else {
  215. dst = src
  216. }
  217. }
  218. } else if _, err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
  219. return
  220. }
  221. default:
  222. overwriteFull := (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst))
  223. if overwriteFull {
  224. if dst.CanSet() {
  225. dst.Set(src)
  226. } else {
  227. dst = src
  228. }
  229. }
  230. }
  231. return
  232. }
  233. // Merge will fill any empty for value type attributes on the dst struct using corresponding
  234. // src attributes if they themselves are not empty. dst and src must be valid same-type structs
  235. // and dst must be a pointer to struct.
  236. // It won't merge unexported (private) fields and will do recursively any exported field.
  237. func Merge(dst, src interface{}, opts ...func(*Config)) error {
  238. return merge(dst, src, opts...)
  239. }
  240. // MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by
  241. // non-empty src attribute values.
  242. // Deprecated: use Merge(…) with WithOverride
  243. func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
  244. return merge(dst, src, append(opts, WithOverride)...)
  245. }
  246. // WithTransformers adds transformers to merge, allowing to customize the merging of some types.
  247. func WithTransformers(transformers Transformers) func(*Config) {
  248. return func(config *Config) {
  249. config.Transformers = transformers
  250. }
  251. }
  252. // WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
  253. func WithOverride(config *Config) {
  254. config.Overwrite = true
  255. }
  256. // WithOverwriteWithEmptyValue will make merge override non empty dst attributes with empty src attributes values.
  257. func WithOverwriteWithEmptyValue(config *Config) {
  258. config.overwriteWithEmptyValue = true
  259. }
  260. // WithOverrideEmptySlice will make merge override empty dst slice with empty src slice.
  261. func WithOverrideEmptySlice(config *Config) {
  262. config.overwriteSliceWithEmptyValue = true
  263. }
  264. // WithAppendSlice will make merge append slices instead of overwriting it.
  265. func WithAppendSlice(config *Config) {
  266. config.AppendSlice = true
  267. }
  268. // WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
  269. func WithTypeCheck(config *Config) {
  270. config.TypeCheck = true
  271. }
  272. func merge(dst, src interface{}, opts ...func(*Config)) error {
  273. var (
  274. vDst, vSrc reflect.Value
  275. err error
  276. )
  277. config := &Config{}
  278. for _, opt := range opts {
  279. opt(config)
  280. }
  281. if vDst, vSrc, err = resolveValues(dst, src); err != nil {
  282. return err
  283. }
  284. if !vDst.CanSet() {
  285. return fmt.Errorf("cannot set dst, needs reference")
  286. }
  287. if vDst.Type() != vSrc.Type() {
  288. return ErrDifferentArgumentsTypes
  289. }
  290. _, err = deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
  291. return err
  292. }
  293. // IsReflectNil is the reflect value provided nil
  294. func isReflectNil(v reflect.Value) bool {
  295. k := v.Kind()
  296. switch k {
  297. case reflect.Interface, reflect.Slice, reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr:
  298. // Both interface and slice are nil if first word is 0.
  299. // Both are always bigger than a word; assume flagIndir.
  300. return v.IsNil()
  301. default:
  302. return false
  303. }
  304. }