merge.go 11 KB

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