aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
diff options
context:
space:
mode:
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.go108
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 @@
1package awsutil
2
3import (
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.
15func 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.
26func 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.
37func 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}