...
1 package copystructure
2
3 import (
4 "errors"
5 "reflect"
6 "sync"
7
8 "github.com/mitchellh/reflectwalk"
9 )
10
11 const tagKey = "copy"
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 func Copy(v interface{}) (interface{}, error) {
36 return Config{}.Copy(v)
37 }
38
39
40
41 type CopierFunc func(interface{}) (interface{}, error)
42
43
44
45
46
47
48
49
50
51
52 var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc)
53
54
55
56
57
58
59
60
61
62
63
64
65 var ShallowCopiers map[reflect.Type]struct{} = make(map[reflect.Type]struct{})
66
67
68
69
70
71 func Must(v interface{}, err error) interface{} {
72 if err != nil {
73 panic("copy error: " + err.Error())
74 }
75
76 return v
77 }
78
79 var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true")
80
81 type Config struct {
82
83
84 Lock bool
85
86
87
88 Copiers map[reflect.Type]CopierFunc
89
90
91
92
93 ShallowCopiers map[reflect.Type]struct{}
94 }
95
96 func (c Config) Copy(v interface{}) (interface{}, error) {
97 if c.Lock && reflect.ValueOf(v).Kind() != reflect.Ptr {
98 return nil, errPointerRequired
99 }
100
101 w := new(walker)
102 if c.Lock {
103 w.useLocks = true
104 }
105
106 if c.Copiers == nil {
107 c.Copiers = Copiers
108 }
109 w.copiers = c.Copiers
110
111 if c.ShallowCopiers == nil {
112 c.ShallowCopiers = ShallowCopiers
113 }
114 w.shallowCopiers = c.ShallowCopiers
115
116 err := reflectwalk.Walk(v, w)
117 if err != nil {
118 return nil, err
119 }
120
121
122
123 result := w.Result
124 if result == nil {
125 val := reflect.ValueOf(v)
126 result = reflect.Indirect(reflect.New(val.Type())).Interface()
127 }
128
129 return result, nil
130 }
131
132
133
134
135
136 func ifaceKey(pointers, depth int) uint64 {
137 return uint64(pointers)<<32 | uint64(depth)
138 }
139
140 type walker struct {
141 Result interface{}
142
143 copiers map[reflect.Type]CopierFunc
144 shallowCopiers map[reflect.Type]struct{}
145 depth int
146 ignoreDepth int
147 vals []reflect.Value
148 cs []reflect.Value
149
150
151 ps []int
152
153
154
155
156
157
158 ifaceTypes map[uint64]reflect.Type
159
160
161 locks []sync.Locker
162
163 useLocks bool
164 }
165
166 func (w *walker) Enter(l reflectwalk.Location) error {
167 w.depth++
168
169
170 for w.depth >= len(w.locks) {
171 w.locks = append(w.locks, nil)
172 }
173
174 for len(w.ps) < w.depth+1 {
175 w.ps = append(w.ps, 0)
176 }
177
178 return nil
179 }
180
181 func (w *walker) Exit(l reflectwalk.Location) error {
182 locker := w.locks[w.depth]
183 w.locks[w.depth] = nil
184 if locker != nil {
185 defer locker.Unlock()
186 }
187
188
189 w.ps[w.depth] = 0
190
191 for k := range w.ifaceTypes {
192 mask := uint64(^uint32(0))
193 if k&mask == uint64(w.depth) {
194 delete(w.ifaceTypes, k)
195 }
196 }
197
198 w.depth--
199 if w.ignoreDepth > w.depth {
200 w.ignoreDepth = 0
201 }
202
203 if w.ignoring() {
204 return nil
205 }
206
207 switch l {
208 case reflectwalk.Array:
209 fallthrough
210 case reflectwalk.Map:
211 fallthrough
212 case reflectwalk.Slice:
213 w.replacePointerMaybe()
214
215
216 w.cs = w.cs[:len(w.cs)-1]
217 case reflectwalk.MapValue:
218
219 mv := w.valPop()
220 mk := w.valPop()
221 m := w.cs[len(w.cs)-1]
222
223
224
225
226 if !mv.IsValid() {
227 mv = reflect.Zero(m.Elem().Type().Elem())
228 }
229 m.Elem().SetMapIndex(mk, mv)
230 case reflectwalk.ArrayElem:
231
232 v := w.valPop()
233 i := w.valPop().Interface().(int)
234 if v.IsValid() {
235 a := w.cs[len(w.cs)-1]
236 ae := a.Elem().Index(i)
237 if ae.CanSet() {
238 ae.Set(v)
239 }
240 }
241 case reflectwalk.SliceElem:
242
243 v := w.valPop()
244 i := w.valPop().Interface().(int)
245 if v.IsValid() {
246 s := w.cs[len(w.cs)-1]
247 se := s.Elem().Index(i)
248 if se.CanSet() {
249 se.Set(v)
250 }
251 }
252 case reflectwalk.Struct:
253 w.replacePointerMaybe()
254
255
256 w.cs = w.cs[:len(w.cs)-1]
257 case reflectwalk.StructField:
258
259 v := w.valPop()
260 f := w.valPop().Interface().(reflect.StructField)
261 if v.IsValid() {
262 s := w.cs[len(w.cs)-1]
263 sf := reflect.Indirect(s).FieldByName(f.Name)
264
265 if sf.CanSet() {
266 sf.Set(v)
267 }
268 }
269 case reflectwalk.WalkLoc:
270
271 w.cs = nil
272 w.vals = nil
273 }
274
275 return nil
276 }
277
278 func (w *walker) Map(m reflect.Value) error {
279 if w.ignoring() {
280 return nil
281 }
282 w.lock(m)
283
284
285 var newMap reflect.Value
286 if m.IsNil() {
287 newMap = reflect.New(m.Type())
288 } else {
289 newMap = wrapPtr(reflect.MakeMap(m.Type()))
290 }
291
292 w.cs = append(w.cs, newMap)
293 w.valPush(newMap)
294 return nil
295 }
296
297 func (w *walker) MapElem(m, k, v reflect.Value) error {
298 return nil
299 }
300
301 func (w *walker) PointerEnter(v bool) error {
302 if v {
303 w.ps[w.depth]++
304 }
305 return nil
306 }
307
308 func (w *walker) PointerExit(v bool) error {
309 if v {
310 w.ps[w.depth]--
311 }
312 return nil
313 }
314
315 func (w *walker) Pointer(v reflect.Value) error {
316 if _, ok := w.shallowCopiers[v.Type()]; ok {
317
318
319 if err := w.Primitive(v); err != nil {
320 return err
321 }
322
323 return reflectwalk.SkipEntry
324 }
325
326 return nil
327 }
328
329 func (w *walker) Interface(v reflect.Value) error {
330 if !v.IsValid() {
331 return nil
332 }
333 if w.ifaceTypes == nil {
334 w.ifaceTypes = make(map[uint64]reflect.Type)
335 }
336
337 w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)] = v.Type()
338 return nil
339 }
340
341 func (w *walker) Primitive(v reflect.Value) error {
342 if w.ignoring() {
343 return nil
344 }
345 w.lock(v)
346
347
348
349 var newV reflect.Value
350 if v.IsValid() && v.CanInterface() {
351 newV = reflect.New(v.Type())
352 newV.Elem().Set(v)
353 }
354
355 w.valPush(newV)
356 w.replacePointerMaybe()
357 return nil
358 }
359
360 func (w *walker) Slice(s reflect.Value) error {
361 if w.ignoring() {
362 return nil
363 }
364 w.lock(s)
365
366 var newS reflect.Value
367 if s.IsNil() {
368 newS = reflect.New(s.Type())
369 } else {
370 newS = wrapPtr(reflect.MakeSlice(s.Type(), s.Len(), s.Cap()))
371 }
372
373 w.cs = append(w.cs, newS)
374 w.valPush(newS)
375 return nil
376 }
377
378 func (w *walker) SliceElem(i int, elem reflect.Value) error {
379 if w.ignoring() {
380 return nil
381 }
382
383
384
385 w.valPush(reflect.ValueOf(i))
386
387 return nil
388 }
389
390 func (w *walker) Array(a reflect.Value) error {
391 if w.ignoring() {
392 return nil
393 }
394 w.lock(a)
395
396 newA := reflect.New(a.Type())
397
398 w.cs = append(w.cs, newA)
399 w.valPush(newA)
400 return nil
401 }
402
403 func (w *walker) ArrayElem(i int, elem reflect.Value) error {
404 if w.ignoring() {
405 return nil
406 }
407
408
409
410 w.valPush(reflect.ValueOf(i))
411
412 return nil
413 }
414
415 func (w *walker) Struct(s reflect.Value) error {
416 if w.ignoring() {
417 return nil
418 }
419 w.lock(s)
420
421 var v reflect.Value
422 if c, ok := w.copiers[s.Type()]; ok {
423
424
425 w.ignoreDepth = w.depth
426
427 dup, err := c(s.Interface())
428 if err != nil {
429 return err
430 }
431
432
433
434 v = reflect.New(s.Type())
435 reflect.Indirect(v).Set(reflect.ValueOf(dup))
436 } else {
437
438
439 v = reflect.New(s.Type())
440 }
441
442
443
444
445 w.valPush(v)
446 w.cs = append(w.cs, v)
447
448 return nil
449 }
450
451 func (w *walker) StructField(f reflect.StructField, v reflect.Value) error {
452 if w.ignoring() {
453 return nil
454 }
455
456
457
458 if f.PkgPath != "" {
459 return reflectwalk.SkipEntry
460 }
461
462 switch f.Tag.Get(tagKey) {
463 case "shallow":
464
465
466 if v.IsValid() {
467 s := w.cs[len(w.cs)-1]
468 sf := reflect.Indirect(s).FieldByName(f.Name)
469 if sf.CanSet() {
470 sf.Set(v)
471 }
472 }
473
474 return reflectwalk.SkipEntry
475
476 case "ignore":
477
478 return reflectwalk.SkipEntry
479 }
480
481
482
483 w.valPush(reflect.ValueOf(f))
484
485 return nil
486 }
487
488
489 func (w *walker) ignore() {
490 w.ignoreDepth = w.depth
491 }
492
493 func (w *walker) ignoring() bool {
494 return w.ignoreDepth > 0 && w.depth >= w.ignoreDepth
495 }
496
497 func (w *walker) pointerPeek() bool {
498 return w.ps[w.depth] > 0
499 }
500
501 func (w *walker) valPop() reflect.Value {
502 result := w.vals[len(w.vals)-1]
503 w.vals = w.vals[:len(w.vals)-1]
504
505
506
507
508 if len(w.vals) == 0 {
509 w.Result = nil
510 }
511
512 return result
513 }
514
515 func (w *walker) valPush(v reflect.Value) {
516 w.vals = append(w.vals, v)
517
518
519
520 if w.Result == nil && v.IsValid() {
521 w.Result = v.Interface()
522 }
523 }
524
525 func (w *walker) replacePointerMaybe() {
526
527
528 if !w.pointerPeek() {
529 w.valPush(reflect.Indirect(w.valPop()))
530 return
531 }
532
533 v := w.valPop()
534
535
536
537
538
539
540
541
542
543
544
545 if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)]; ok && iType.Kind() == reflect.Interface {
546 y := reflect.New(iType)
547 y.Elem().Set(reflect.Indirect(v))
548 v = y
549 }
550
551 for i := 1; i < w.ps[w.depth]; i++ {
552 if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok {
553 iface := reflect.New(iType).Elem()
554 iface.Set(v)
555 v = iface
556 }
557
558 p := reflect.New(v.Type())
559 p.Elem().Set(v)
560 v = p
561 }
562
563 w.valPush(v)
564 }
565
566
567 func (w *walker) lock(v reflect.Value) {
568 if !w.useLocks {
569 return
570 }
571
572 if !v.IsValid() || !v.CanInterface() {
573 return
574 }
575
576 type rlocker interface {
577 RLocker() sync.Locker
578 }
579
580 var locker sync.Locker
581
582
583
584
585 if v.Kind() == reflect.Ptr {
586 switch l := v.Interface().(type) {
587 case rlocker:
588
589 if _, ok := l.(*sync.RWMutex); !ok {
590 locker = l.RLocker()
591 }
592 case sync.Locker:
593 locker = l
594 }
595 } else if v.CanAddr() {
596 switch l := v.Addr().Interface().(type) {
597 case rlocker:
598
599 if _, ok := l.(*sync.RWMutex); !ok {
600 locker = l.RLocker()
601 }
602 case sync.Locker:
603 locker = l
604 }
605 }
606
607
608 if locker == nil {
609 return
610 }
611
612
613 switch locker.(type) {
614 case *sync.Mutex, *sync.RWMutex:
615 return
616 }
617
618 locker.Lock()
619 w.locks[w.depth] = locker
620 }
621
622
623
624 func wrapPtr(v reflect.Value) reflect.Value {
625 if !v.IsValid() {
626 return v
627 }
628 vPtr := reflect.New(v.Type())
629 vPtr.Elem().Set(v)
630 return vPtr
631 }
632
View as plain text