aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil')
-rw-r--r--vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go296
-rw-r--r--vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go250
2 files changed, 546 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go
new file mode 100644
index 0000000..864fb67
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go
@@ -0,0 +1,296 @@
1// Package jsonutil provides JSON serialization of AWS requests and responses.
2package jsonutil
3
4import (
5 "bytes"
6 "encoding/base64"
7 "encoding/json"
8 "fmt"
9 "math"
10 "reflect"
11 "sort"
12 "strconv"
13 "time"
14
15 "github.com/aws/aws-sdk-go/aws"
16 "github.com/aws/aws-sdk-go/private/protocol"
17)
18
19var timeType = reflect.ValueOf(time.Time{}).Type()
20var byteSliceType = reflect.ValueOf([]byte{}).Type()
21
22// BuildJSON builds a JSON string for a given object v.
23func BuildJSON(v interface{}) ([]byte, error) {
24 var buf bytes.Buffer
25
26 err := buildAny(reflect.ValueOf(v), &buf, "")
27 return buf.Bytes(), err
28}
29
30func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
31 origVal := value
32 value = reflect.Indirect(value)
33 if !value.IsValid() {
34 return nil
35 }
36
37 vtype := value.Type()
38
39 t := tag.Get("type")
40 if t == "" {
41 switch vtype.Kind() {
42 case reflect.Struct:
43 // also it can't be a time object
44 if value.Type() != timeType {
45 t = "structure"
46 }
47 case reflect.Slice:
48 // also it can't be a byte slice
49 if _, ok := value.Interface().([]byte); !ok {
50 t = "list"
51 }
52 case reflect.Map:
53 // cannot be a JSONValue map
54 if _, ok := value.Interface().(aws.JSONValue); !ok {
55 t = "map"
56 }
57 }
58 }
59
60 switch t {
61 case "structure":
62 if field, ok := vtype.FieldByName("_"); ok {
63 tag = field.Tag
64 }
65 return buildStruct(value, buf, tag)
66 case "list":
67 return buildList(value, buf, tag)
68 case "map":
69 return buildMap(value, buf, tag)
70 default:
71 return buildScalar(origVal, buf, tag)
72 }
73}
74
75func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
76 if !value.IsValid() {
77 return nil
78 }
79
80 // unwrap payloads
81 if payload := tag.Get("payload"); payload != "" {
82 field, _ := value.Type().FieldByName(payload)
83 tag = field.Tag
84 value = elemOf(value.FieldByName(payload))
85
86 if !value.IsValid() {
87 return nil
88 }
89 }
90
91 buf.WriteByte('{')
92
93 t := value.Type()
94 first := true
95 for i := 0; i < t.NumField(); i++ {
96 member := value.Field(i)
97
98 // This allocates the most memory.
99 // Additionally, we cannot skip nil fields due to
100 // idempotency auto filling.
101 field := t.Field(i)
102
103 if field.PkgPath != "" {
104 continue // ignore unexported fields
105 }
106 if field.Tag.Get("json") == "-" {
107 continue
108 }
109 if field.Tag.Get("location") != "" {
110 continue // ignore non-body elements
111 }
112 if field.Tag.Get("ignore") != "" {
113 continue
114 }
115
116 if protocol.CanSetIdempotencyToken(member, field) {
117 token := protocol.GetIdempotencyToken()
118 member = reflect.ValueOf(&token)
119 }
120
121 if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice || member.Kind() == reflect.Map) && member.IsNil() {
122 continue // ignore unset fields
123 }
124
125 if first {
126 first = false
127 } else {
128 buf.WriteByte(',')
129 }
130
131 // figure out what this field is called
132 name := field.Name
133 if locName := field.Tag.Get("locationName"); locName != "" {
134 name = locName
135 }
136
137 writeString(name, buf)
138 buf.WriteString(`:`)
139
140 err := buildAny(member, buf, field.Tag)
141 if err != nil {
142 return err
143 }
144
145 }
146
147 buf.WriteString("}")
148
149 return nil
150}
151
152func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
153 buf.WriteString("[")
154
155 for i := 0; i < value.Len(); i++ {
156 buildAny(value.Index(i), buf, "")
157
158 if i < value.Len()-1 {
159 buf.WriteString(",")
160 }
161 }
162
163 buf.WriteString("]")
164
165 return nil
166}
167
168type sortedValues []reflect.Value
169
170func (sv sortedValues) Len() int { return len(sv) }
171func (sv sortedValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
172func (sv sortedValues) Less(i, j int) bool { return sv[i].String() < sv[j].String() }
173
174func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
175 buf.WriteString("{")
176
177 sv := sortedValues(value.MapKeys())
178 sort.Sort(sv)
179
180 for i, k := range sv {
181 if i > 0 {
182 buf.WriteByte(',')
183 }
184
185 writeString(k.String(), buf)
186 buf.WriteString(`:`)
187
188 buildAny(value.MapIndex(k), buf, "")
189 }
190
191 buf.WriteString("}")
192
193 return nil
194}
195
196func buildScalar(v reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
197 // prevents allocation on the heap.
198 scratch := [64]byte{}
199 switch value := reflect.Indirect(v); value.Kind() {
200 case reflect.String:
201 writeString(value.String(), buf)
202 case reflect.Bool:
203 if value.Bool() {
204 buf.WriteString("true")
205 } else {
206 buf.WriteString("false")
207 }
208 case reflect.Int64:
209 buf.Write(strconv.AppendInt(scratch[:0], value.Int(), 10))
210 case reflect.Float64:
211 f := value.Float()
212 if math.IsInf(f, 0) || math.IsNaN(f) {
213 return &json.UnsupportedValueError{Value: v, Str: strconv.FormatFloat(f, 'f', -1, 64)}
214 }
215 buf.Write(strconv.AppendFloat(scratch[:0], f, 'f', -1, 64))
216 default:
217 switch converted := value.Interface().(type) {
218 case time.Time:
219 format := tag.Get("timestampFormat")
220 if len(format) == 0 {
221 format = protocol.UnixTimeFormatName
222 }
223
224 ts := protocol.FormatTime(format, converted)
225 if format != protocol.UnixTimeFormatName {
226 ts = `"` + ts + `"`
227 }
228
229 buf.WriteString(ts)
230 case []byte:
231 if !value.IsNil() {
232 buf.WriteByte('"')
233 if len(converted) < 1024 {
234 // for small buffers, using Encode directly is much faster.
235 dst := make([]byte, base64.StdEncoding.EncodedLen(len(converted)))
236 base64.StdEncoding.Encode(dst, converted)
237 buf.Write(dst)
238 } else {
239 // for large buffers, avoid unnecessary extra temporary
240 // buffer space.
241 enc := base64.NewEncoder(base64.StdEncoding, buf)
242 enc.Write(converted)
243 enc.Close()
244 }
245 buf.WriteByte('"')
246 }
247 case aws.JSONValue:
248 str, err := protocol.EncodeJSONValue(converted, protocol.QuotedEscape)
249 if err != nil {
250 return fmt.Errorf("unable to encode JSONValue, %v", err)
251 }
252 buf.WriteString(str)
253 default:
254 return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type())
255 }
256 }
257 return nil
258}
259
260var hex = "0123456789abcdef"
261
262func writeString(s string, buf *bytes.Buffer) {
263 buf.WriteByte('"')
264 for i := 0; i < len(s); i++ {
265 if s[i] == '"' {
266 buf.WriteString(`\"`)
267 } else if s[i] == '\\' {
268 buf.WriteString(`\\`)
269 } else if s[i] == '\b' {
270 buf.WriteString(`\b`)
271 } else if s[i] == '\f' {
272 buf.WriteString(`\f`)
273 } else if s[i] == '\r' {
274 buf.WriteString(`\r`)
275 } else if s[i] == '\t' {
276 buf.WriteString(`\t`)
277 } else if s[i] == '\n' {
278 buf.WriteString(`\n`)
279 } else if s[i] < 32 {
280 buf.WriteString("\\u00")
281 buf.WriteByte(hex[s[i]>>4])
282 buf.WriteByte(hex[s[i]&0xF])
283 } else {
284 buf.WriteByte(s[i])
285 }
286 }
287 buf.WriteByte('"')
288}
289
290// Returns the reflection element of a value, if it is a pointer.
291func elemOf(value reflect.Value) reflect.Value {
292 for value.Kind() == reflect.Ptr {
293 value = value.Elem()
294 }
295 return value
296}
diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
new file mode 100644
index 0000000..ea0da79
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
@@ -0,0 +1,250 @@
1package jsonutil
2
3import (
4 "bytes"
5 "encoding/base64"
6 "encoding/json"
7 "fmt"
8 "io"
9 "reflect"
10 "time"
11
12 "github.com/aws/aws-sdk-go/aws"
13 "github.com/aws/aws-sdk-go/aws/awserr"
14 "github.com/aws/aws-sdk-go/private/protocol"
15)
16
17// UnmarshalJSONError unmarshal's the reader's JSON document into the passed in
18// type. The value to unmarshal the json document into must be a pointer to the
19// type.
20func UnmarshalJSONError(v interface{}, stream io.Reader) error {
21 var errBuf bytes.Buffer
22 body := io.TeeReader(stream, &errBuf)
23
24 err := json.NewDecoder(body).Decode(v)
25 if err != nil {
26 msg := "failed decoding error message"
27 if err == io.EOF {
28 msg = "error message missing"
29 err = nil
30 }
31 return awserr.NewUnmarshalError(err, msg, errBuf.Bytes())
32 }
33
34 return nil
35}
36
37// UnmarshalJSON reads a stream and unmarshals the results in object v.
38func UnmarshalJSON(v interface{}, stream io.Reader) error {
39 var out interface{}
40
41 err := json.NewDecoder(stream).Decode(&out)
42 if err == io.EOF {
43 return nil
44 } else if err != nil {
45 return err
46 }
47
48 return unmarshalAny(reflect.ValueOf(v), out, "")
49}
50
51func unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error {
52 vtype := value.Type()
53 if vtype.Kind() == reflect.Ptr {
54 vtype = vtype.Elem() // check kind of actual element type
55 }
56
57 t := tag.Get("type")
58 if t == "" {
59 switch vtype.Kind() {
60 case reflect.Struct:
61 // also it can't be a time object
62 if _, ok := value.Interface().(*time.Time); !ok {
63 t = "structure"
64 }
65 case reflect.Slice:
66 // also it can't be a byte slice
67 if _, ok := value.Interface().([]byte); !ok {
68 t = "list"
69 }
70 case reflect.Map:
71 // cannot be a JSONValue map
72 if _, ok := value.Interface().(aws.JSONValue); !ok {
73 t = "map"
74 }
75 }
76 }
77
78 switch t {
79 case "structure":
80 if field, ok := vtype.FieldByName("_"); ok {
81 tag = field.Tag
82 }
83 return unmarshalStruct(value, data, tag)
84 case "list":
85 return unmarshalList(value, data, tag)
86 case "map":
87 return unmarshalMap(value, data, tag)
88 default:
89 return unmarshalScalar(value, data, tag)
90 }
91}
92
93func unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error {
94 if data == nil {
95 return nil
96 }
97 mapData, ok := data.(map[string]interface{})
98 if !ok {
99 return fmt.Errorf("JSON value is not a structure (%#v)", data)
100 }
101
102 t := value.Type()
103 if value.Kind() == reflect.Ptr {
104 if value.IsNil() { // create the structure if it's nil
105 s := reflect.New(value.Type().Elem())
106 value.Set(s)
107 value = s
108 }
109
110 value = value.Elem()
111 t = t.Elem()
112 }
113
114 // unwrap any payloads
115 if payload := tag.Get("payload"); payload != "" {
116 field, _ := t.FieldByName(payload)
117 return unmarshalAny(value.FieldByName(payload), data, field.Tag)
118 }
119
120 for i := 0; i < t.NumField(); i++ {
121 field := t.Field(i)
122 if field.PkgPath != "" {
123 continue // ignore unexported fields
124 }
125
126 // figure out what this field is called
127 name := field.Name
128 if locName := field.Tag.Get("locationName"); locName != "" {
129 name = locName
130 }
131
132 member := value.FieldByIndex(field.Index)
133 err := unmarshalAny(member, mapData[name], field.Tag)
134 if err != nil {
135 return err
136 }
137 }
138 return nil
139}
140
141func unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error {
142 if data == nil {
143 return nil
144 }
145 listData, ok := data.([]interface{})
146 if !ok {
147 return fmt.Errorf("JSON value is not a list (%#v)", data)
148 }
149
150 if value.IsNil() {
151 l := len(listData)
152 value.Set(reflect.MakeSlice(value.Type(), l, l))
153 }
154
155 for i, c := range listData {
156 err := unmarshalAny(value.Index(i), c, "")
157 if err != nil {
158 return err
159 }
160 }
161
162 return nil
163}
164
165func unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error {
166 if data == nil {
167 return nil
168 }
169 mapData, ok := data.(map[string]interface{})
170 if !ok {
171 return fmt.Errorf("JSON value is not a map (%#v)", data)
172 }
173
174 if value.IsNil() {
175 value.Set(reflect.MakeMap(value.Type()))
176 }
177
178 for k, v := range mapData {
179 kvalue := reflect.ValueOf(k)
180 vvalue := reflect.New(value.Type().Elem()).Elem()
181
182 unmarshalAny(vvalue, v, "")
183 value.SetMapIndex(kvalue, vvalue)
184 }
185
186 return nil
187}
188
189func unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error {
190
191 switch d := data.(type) {
192 case nil:
193 return nil // nothing to do here
194 case string:
195 switch value.Interface().(type) {
196 case *string:
197 value.Set(reflect.ValueOf(&d))
198 case []byte:
199 b, err := base64.StdEncoding.DecodeString(d)
200 if err != nil {
201 return err
202 }
203 value.Set(reflect.ValueOf(b))
204 case *time.Time:
205 format := tag.Get("timestampFormat")
206 if len(format) == 0 {
207 format = protocol.ISO8601TimeFormatName
208 }
209
210 t, err := protocol.ParseTime(format, d)
211 if err != nil {
212 return err
213 }
214 value.Set(reflect.ValueOf(&t))
215 case aws.JSONValue:
216 // No need to use escaping as the value is a non-quoted string.
217 v, err := protocol.DecodeJSONValue(d, protocol.NoEscape)
218 if err != nil {
219 return err
220 }
221 value.Set(reflect.ValueOf(v))
222 default:
223 return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
224 }
225 case float64:
226 switch value.Interface().(type) {
227 case *int64:
228 di := int64(d)
229 value.Set(reflect.ValueOf(&di))
230 case *float64:
231 value.Set(reflect.ValueOf(&d))
232 case *time.Time:
233 // Time unmarshaled from a float64 can only be epoch seconds
234 t := time.Unix(int64(d), 0).UTC()
235 value.Set(reflect.ValueOf(&t))
236 default:
237 return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
238 }
239 case bool:
240 switch value.Interface().(type) {
241 case *bool:
242 value.Set(reflect.ValueOf(&d))
243 default:
244 return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
245 }
246 default:
247 return fmt.Errorf("unsupported JSON value (%v)", data)
248 }
249 return nil
250}