diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil')
-rw-r--r-- | vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go new file mode 100644 index 0000000..524ca95 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go | |||
@@ -0,0 +1,237 @@ | |||
1 | package queryutil | ||
2 | |||
3 | import ( | ||
4 | "encoding/base64" | ||
5 | "fmt" | ||
6 | "net/url" | ||
7 | "reflect" | ||
8 | "sort" | ||
9 | "strconv" | ||
10 | "strings" | ||
11 | "time" | ||
12 | |||
13 | "github.com/aws/aws-sdk-go/private/protocol" | ||
14 | ) | ||
15 | |||
16 | // Parse parses an object i and fills a url.Values object. The isEC2 flag | ||
17 | // indicates if this is the EC2 Query sub-protocol. | ||
18 | func Parse(body url.Values, i interface{}, isEC2 bool) error { | ||
19 | q := queryParser{isEC2: isEC2} | ||
20 | return q.parseValue(body, reflect.ValueOf(i), "", "") | ||
21 | } | ||
22 | |||
23 | func elemOf(value reflect.Value) reflect.Value { | ||
24 | for value.Kind() == reflect.Ptr { | ||
25 | value = value.Elem() | ||
26 | } | ||
27 | return value | ||
28 | } | ||
29 | |||
30 | type queryParser struct { | ||
31 | isEC2 bool | ||
32 | } | ||
33 | |||
34 | func (q *queryParser) parseValue(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { | ||
35 | value = elemOf(value) | ||
36 | |||
37 | // no need to handle zero values | ||
38 | if !value.IsValid() { | ||
39 | return nil | ||
40 | } | ||
41 | |||
42 | t := tag.Get("type") | ||
43 | if t == "" { | ||
44 | switch value.Kind() { | ||
45 | case reflect.Struct: | ||
46 | t = "structure" | ||
47 | case reflect.Slice: | ||
48 | t = "list" | ||
49 | case reflect.Map: | ||
50 | t = "map" | ||
51 | } | ||
52 | } | ||
53 | |||
54 | switch t { | ||
55 | case "structure": | ||
56 | return q.parseStruct(v, value, prefix) | ||
57 | case "list": | ||
58 | return q.parseList(v, value, prefix, tag) | ||
59 | case "map": | ||
60 | return q.parseMap(v, value, prefix, tag) | ||
61 | default: | ||
62 | return q.parseScalar(v, value, prefix, tag) | ||
63 | } | ||
64 | } | ||
65 | |||
66 | func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix string) error { | ||
67 | if !value.IsValid() { | ||
68 | return nil | ||
69 | } | ||
70 | |||
71 | t := value.Type() | ||
72 | for i := 0; i < value.NumField(); i++ { | ||
73 | elemValue := elemOf(value.Field(i)) | ||
74 | field := t.Field(i) | ||
75 | |||
76 | if field.PkgPath != "" { | ||
77 | continue // ignore unexported fields | ||
78 | } | ||
79 | if field.Tag.Get("ignore") != "" { | ||
80 | continue | ||
81 | } | ||
82 | |||
83 | if protocol.CanSetIdempotencyToken(value.Field(i), field) { | ||
84 | token := protocol.GetIdempotencyToken() | ||
85 | elemValue = reflect.ValueOf(token) | ||
86 | } | ||
87 | |||
88 | var name string | ||
89 | if q.isEC2 { | ||
90 | name = field.Tag.Get("queryName") | ||
91 | } | ||
92 | if name == "" { | ||
93 | if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" { | ||
94 | name = field.Tag.Get("locationNameList") | ||
95 | } else if locName := field.Tag.Get("locationName"); locName != "" { | ||
96 | name = locName | ||
97 | } | ||
98 | if name != "" && q.isEC2 { | ||
99 | name = strings.ToUpper(name[0:1]) + name[1:] | ||
100 | } | ||
101 | } | ||
102 | if name == "" { | ||
103 | name = field.Name | ||
104 | } | ||
105 | |||
106 | if prefix != "" { | ||
107 | name = prefix + "." + name | ||
108 | } | ||
109 | |||
110 | if err := q.parseValue(v, elemValue, name, field.Tag); err != nil { | ||
111 | return err | ||
112 | } | ||
113 | } | ||
114 | return nil | ||
115 | } | ||
116 | |||
117 | func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { | ||
118 | // If it's empty, generate an empty value | ||
119 | if !value.IsNil() && value.Len() == 0 { | ||
120 | v.Set(prefix, "") | ||
121 | return nil | ||
122 | } | ||
123 | |||
124 | // check for unflattened list member | ||
125 | if !q.isEC2 && tag.Get("flattened") == "" { | ||
126 | if listName := tag.Get("locationNameList"); listName == "" { | ||
127 | prefix += ".member" | ||
128 | } else { | ||
129 | prefix += "." + listName | ||
130 | } | ||
131 | } | ||
132 | |||
133 | for i := 0; i < value.Len(); i++ { | ||
134 | slicePrefix := prefix | ||
135 | if slicePrefix == "" { | ||
136 | slicePrefix = strconv.Itoa(i + 1) | ||
137 | } else { | ||
138 | slicePrefix = slicePrefix + "." + strconv.Itoa(i+1) | ||
139 | } | ||
140 | if err := q.parseValue(v, value.Index(i), slicePrefix, ""); err != nil { | ||
141 | return err | ||
142 | } | ||
143 | } | ||
144 | return nil | ||
145 | } | ||
146 | |||
147 | func (q *queryParser) parseMap(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error { | ||
148 | // If it's empty, generate an empty value | ||
149 | if !value.IsNil() && value.Len() == 0 { | ||
150 | v.Set(prefix, "") | ||
151 | return nil | ||
152 | } | ||
153 | |||
154 | // check for unflattened list member | ||
155 | if !q.isEC2 && tag.Get("flattened") == "" { | ||
156 | prefix += ".entry" | ||
157 | } | ||
158 | |||
159 | // sort keys for improved serialization consistency. | ||
160 | // this is not strictly necessary for protocol support. | ||
161 | mapKeyValues := value.MapKeys() | ||
162 | mapKeys := map[string]reflect.Value{} | ||
163 | mapKeyNames := make([]string, len(mapKeyValues)) | ||
164 | for i, mapKey := range mapKeyValues { | ||
165 | name := mapKey.String() | ||
166 | mapKeys[name] = mapKey | ||
167 | mapKeyNames[i] = name | ||
168 | } | ||
169 | sort.Strings(mapKeyNames) | ||
170 | |||
171 | for i, mapKeyName := range mapKeyNames { | ||
172 | mapKey := mapKeys[mapKeyName] | ||
173 | mapValue := value.MapIndex(mapKey) | ||
174 | |||
175 | kname := tag.Get("locationNameKey") | ||
176 | if kname == "" { | ||
177 | kname = "key" | ||
178 | } | ||
179 | vname := tag.Get("locationNameValue") | ||
180 | if vname == "" { | ||
181 | vname = "value" | ||
182 | } | ||
183 | |||
184 | // serialize key | ||
185 | var keyName string | ||
186 | if prefix == "" { | ||
187 | keyName = strconv.Itoa(i+1) + "." + kname | ||
188 | } else { | ||
189 | keyName = prefix + "." + strconv.Itoa(i+1) + "." + kname | ||
190 | } | ||
191 | |||
192 | if err := q.parseValue(v, mapKey, keyName, ""); err != nil { | ||
193 | return err | ||
194 | } | ||
195 | |||
196 | // serialize value | ||
197 | var valueName string | ||
198 | if prefix == "" { | ||
199 | valueName = strconv.Itoa(i+1) + "." + vname | ||
200 | } else { | ||
201 | valueName = prefix + "." + strconv.Itoa(i+1) + "." + vname | ||
202 | } | ||
203 | |||
204 | if err := q.parseValue(v, mapValue, valueName, ""); err != nil { | ||
205 | return err | ||
206 | } | ||
207 | } | ||
208 | |||
209 | return nil | ||
210 | } | ||
211 | |||
212 | func (q *queryParser) parseScalar(v url.Values, r reflect.Value, name string, tag reflect.StructTag) error { | ||
213 | switch value := r.Interface().(type) { | ||
214 | case string: | ||
215 | v.Set(name, value) | ||
216 | case []byte: | ||
217 | if !r.IsNil() { | ||
218 | v.Set(name, base64.StdEncoding.EncodeToString(value)) | ||
219 | } | ||
220 | case bool: | ||
221 | v.Set(name, strconv.FormatBool(value)) | ||
222 | case int64: | ||
223 | v.Set(name, strconv.FormatInt(value, 10)) | ||
224 | case int: | ||
225 | v.Set(name, strconv.Itoa(value)) | ||
226 | case float64: | ||
227 | v.Set(name, strconv.FormatFloat(value, 'f', -1, 64)) | ||
228 | case float32: | ||
229 | v.Set(name, strconv.FormatFloat(float64(value), 'f', -1, 32)) | ||
230 | case time.Time: | ||
231 | const ISO8601UTC = "2006-01-02T15:04:05Z" | ||
232 | v.Set(name, value.UTC().Format(ISO8601UTC)) | ||
233 | default: | ||
234 | return fmt.Errorf("unsupported value for param %s: %v (%s)", name, r.Interface(), r.Type().Name()) | ||
235 | } | ||
236 | return nil | ||
237 | } | ||