...
1 package awsutil
2
3 import (
4 "io"
5 "reflect"
6 "time"
7 )
8
9
10
11
12
13
14
15 func Copy(dst, src interface{}) {
16 dstval := reflect.ValueOf(dst)
17 if !dstval.IsValid() {
18 panic("Copy dst cannot be nil")
19 }
20
21 rcopy(dstval, reflect.ValueOf(src), true)
22 }
23
24
25
26 func CopyOf(src interface{}) (dst interface{}) {
27 dsti := reflect.New(reflect.TypeOf(src).Elem())
28 dst = dsti.Interface()
29 rcopy(dsti, reflect.ValueOf(src), true)
30 return
31 }
32
33
34
35
36
37 func rcopy(dst, src reflect.Value, root bool) {
38 if !src.IsValid() {
39 return
40 }
41
42 switch src.Kind() {
43 case reflect.Ptr:
44 if _, ok := src.Interface().(io.Reader); ok {
45 if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() {
46 dst.Elem().Set(src)
47 } else if dst.CanSet() {
48 dst.Set(src)
49 }
50 } else {
51 e := src.Type().Elem()
52 if dst.CanSet() && !src.IsNil() {
53 if _, ok := src.Interface().(*time.Time); !ok {
54 if dst.Kind() == reflect.String {
55 dst.SetString(e.String())
56 } else {
57 dst.Set(reflect.New(e))
58 }
59 } else {
60 tempValue := reflect.New(e)
61 tempValue.Elem().Set(src.Elem())
62
63 dst.Set(tempValue)
64 }
65 }
66 if dst.Kind() != reflect.String && src.Elem().IsValid() {
67
68 rcopy(dst.Elem(), src.Elem(), root)
69 }
70 }
71 case reflect.Struct:
72 t := dst.Type()
73 for i := 0; i < t.NumField(); i++ {
74 name := t.Field(i).Name
75 srcVal := src.FieldByName(name)
76 dstVal := dst.FieldByName(name)
77 if srcVal.IsValid() && dstVal.CanSet() {
78 rcopy(dstVal, srcVal, false)
79 }
80 }
81 case reflect.Slice:
82 if src.IsNil() {
83 break
84 }
85
86 s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
87 dst.Set(s)
88 for i := 0; i < src.Len(); i++ {
89 rcopy(dst.Index(i), src.Index(i), false)
90 }
91 case reflect.Map:
92 if src.IsNil() {
93 break
94 }
95
96 s := reflect.MakeMap(src.Type())
97 dst.Set(s)
98 for _, k := range src.MapKeys() {
99 v := src.MapIndex(k)
100 v2 := reflect.New(v.Type()).Elem()
101 rcopy(v2, v, false)
102 dst.SetMapIndex(k, v2)
103 }
104 default:
105
106
107
108 if src.Type().AssignableTo(dst.Type()) {
109 dst.Set(src)
110 }
111 }
112 }
113
View as plain text