diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go')
-rw-r--r-- | vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go new file mode 100644 index 0000000..1a3d106 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go | |||
@@ -0,0 +1,108 @@ | |||
1 | package awsutil | ||
2 | |||
3 | import ( | ||
4 | "io" | ||
5 | "reflect" | ||
6 | "time" | ||
7 | ) | ||
8 | |||
9 | // Copy deeply copies a src structure to dst. Useful for copying request and | ||
10 | // response structures. | ||
11 | // | ||
12 | // Can copy between structs of different type, but will only copy fields which | ||
13 | // are assignable, and exist in both structs. Fields which are not assignable, | ||
14 | // or do not exist in both structs are ignored. | ||
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 | // CopyOf returns a copy of src while also allocating the memory for dst. | ||
25 | // src must be a pointer type or this operation will fail. | ||
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 | // rcopy performs a recursive copy of values from the source to destination. | ||
34 | // | ||
35 | // root is used to skip certain aspects of the copy which are not valid | ||
36 | // for the root node of a object. | ||
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 | dst.Set(reflect.New(e)) | ||
55 | } else { | ||
56 | tempValue := reflect.New(e) | ||
57 | tempValue.Elem().Set(src.Elem()) | ||
58 | // Sets time.Time's unexported values | ||
59 | dst.Set(tempValue) | ||
60 | } | ||
61 | } | ||
62 | if src.Elem().IsValid() { | ||
63 | // Keep the current root state since the depth hasn't changed | ||
64 | rcopy(dst.Elem(), src.Elem(), root) | ||
65 | } | ||
66 | } | ||
67 | case reflect.Struct: | ||
68 | t := dst.Type() | ||
69 | for i := 0; i < t.NumField(); i++ { | ||
70 | name := t.Field(i).Name | ||
71 | srcVal := src.FieldByName(name) | ||
72 | dstVal := dst.FieldByName(name) | ||
73 | if srcVal.IsValid() && dstVal.CanSet() { | ||
74 | rcopy(dstVal, srcVal, false) | ||
75 | } | ||
76 | } | ||
77 | case reflect.Slice: | ||
78 | if src.IsNil() { | ||
79 | break | ||
80 | } | ||
81 | |||
82 | s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) | ||
83 | dst.Set(s) | ||
84 | for i := 0; i < src.Len(); i++ { | ||
85 | rcopy(dst.Index(i), src.Index(i), false) | ||
86 | } | ||
87 | case reflect.Map: | ||
88 | if src.IsNil() { | ||
89 | break | ||
90 | } | ||
91 | |||
92 | s := reflect.MakeMap(src.Type()) | ||
93 | dst.Set(s) | ||
94 | for _, k := range src.MapKeys() { | ||
95 | v := src.MapIndex(k) | ||
96 | v2 := reflect.New(v.Type()).Elem() | ||
97 | rcopy(v2, v, false) | ||
98 | dst.SetMapIndex(k, v2) | ||
99 | } | ||
100 | default: | ||
101 | // Assign the value if possible. If its not assignable, the value would | ||
102 | // need to be converted and the impact of that may be unexpected, or is | ||
103 | // not compatible with the dst type. | ||
104 | if src.Type().AssignableTo(dst.Type()) { | ||
105 | dst.Set(src) | ||
106 | } | ||
107 | } | ||
108 | } | ||