diff options
Diffstat (limited to 'vendor/github.com/mitchellh/mapstructure/mapstructure.go')
-rw-r--r-- | vendor/github.com/mitchellh/mapstructure/mapstructure.go | 823 |
1 files changed, 823 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go new file mode 100644 index 0000000..6dee0ef --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go | |||
@@ -0,0 +1,823 @@ | |||
1 | // The mapstructure package exposes functionality to convert an | ||
2 | // arbitrary map[string]interface{} into a native Go structure. | ||
3 | // | ||
4 | // The Go structure can be arbitrarily complex, containing slices, | ||
5 | // other structs, etc. and the decoder will properly decode nested | ||
6 | // maps and so on into the proper structures in the native Go struct. | ||
7 | // See the examples to see what the decoder is capable of. | ||
8 | package mapstructure | ||
9 | |||
10 | import ( | ||
11 | "encoding/json" | ||
12 | "errors" | ||
13 | "fmt" | ||
14 | "reflect" | ||
15 | "sort" | ||
16 | "strconv" | ||
17 | "strings" | ||
18 | ) | ||
19 | |||
20 | // DecodeHookFunc is the callback function that can be used for | ||
21 | // data transformations. See "DecodeHook" in the DecoderConfig | ||
22 | // struct. | ||
23 | // | ||
24 | // The type should be DecodeHookFuncType or DecodeHookFuncKind. | ||
25 | // Either is accepted. Types are a superset of Kinds (Types can return | ||
26 | // Kinds) and are generally a richer thing to use, but Kinds are simpler | ||
27 | // if you only need those. | ||
28 | // | ||
29 | // The reason DecodeHookFunc is multi-typed is for backwards compatibility: | ||
30 | // we started with Kinds and then realized Types were the better solution, | ||
31 | // but have a promise to not break backwards compat so we now support | ||
32 | // both. | ||
33 | type DecodeHookFunc interface{} | ||
34 | |||
35 | type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) | ||
36 | type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) | ||
37 | |||
38 | // DecoderConfig is the configuration that is used to create a new decoder | ||
39 | // and allows customization of various aspects of decoding. | ||
40 | type DecoderConfig struct { | ||
41 | // DecodeHook, if set, will be called before any decoding and any | ||
42 | // type conversion (if WeaklyTypedInput is on). This lets you modify | ||
43 | // the values before they're set down onto the resulting struct. | ||
44 | // | ||
45 | // If an error is returned, the entire decode will fail with that | ||
46 | // error. | ||
47 | DecodeHook DecodeHookFunc | ||
48 | |||
49 | // If ErrorUnused is true, then it is an error for there to exist | ||
50 | // keys in the original map that were unused in the decoding process | ||
51 | // (extra keys). | ||
52 | ErrorUnused bool | ||
53 | |||
54 | // ZeroFields, if set to true, will zero fields before writing them. | ||
55 | // For example, a map will be emptied before decoded values are put in | ||
56 | // it. If this is false, a map will be merged. | ||
57 | ZeroFields bool | ||
58 | |||
59 | // If WeaklyTypedInput is true, the decoder will make the following | ||
60 | // "weak" conversions: | ||
61 | // | ||
62 | // - bools to string (true = "1", false = "0") | ||
63 | // - numbers to string (base 10) | ||
64 | // - bools to int/uint (true = 1, false = 0) | ||
65 | // - strings to int/uint (base implied by prefix) | ||
66 | // - int to bool (true if value != 0) | ||
67 | // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, | ||
68 | // FALSE, false, False. Anything else is an error) | ||
69 | // - empty array = empty map and vice versa | ||
70 | // - negative numbers to overflowed uint values (base 10) | ||
71 | // - slice of maps to a merged map | ||
72 | // - single values are converted to slices if required. Each | ||
73 | // element is weakly decoded. For example: "4" can become []int{4} | ||
74 | // if the target type is an int slice. | ||
75 | // | ||
76 | WeaklyTypedInput bool | ||
77 | |||
78 | // Metadata is the struct that will contain extra metadata about | ||
79 | // the decoding. If this is nil, then no metadata will be tracked. | ||
80 | Metadata *Metadata | ||
81 | |||
82 | // Result is a pointer to the struct that will contain the decoded | ||
83 | // value. | ||
84 | Result interface{} | ||
85 | |||
86 | // The tag name that mapstructure reads for field names. This | ||
87 | // defaults to "mapstructure" | ||
88 | TagName string | ||
89 | } | ||
90 | |||
91 | // A Decoder takes a raw interface value and turns it into structured | ||
92 | // data, keeping track of rich error information along the way in case | ||
93 | // anything goes wrong. Unlike the basic top-level Decode method, you can | ||
94 | // more finely control how the Decoder behaves using the DecoderConfig | ||
95 | // structure. The top-level Decode method is just a convenience that sets | ||
96 | // up the most basic Decoder. | ||
97 | type Decoder struct { | ||
98 | config *DecoderConfig | ||
99 | } | ||
100 | |||
101 | // Metadata contains information about decoding a structure that | ||
102 | // is tedious or difficult to get otherwise. | ||
103 | type Metadata struct { | ||
104 | // Keys are the keys of the structure which were successfully decoded | ||
105 | Keys []string | ||
106 | |||
107 | // Unused is a slice of keys that were found in the raw value but | ||
108 | // weren't decoded since there was no matching field in the result interface | ||
109 | Unused []string | ||
110 | } | ||
111 | |||
112 | // Decode takes a map and uses reflection to convert it into the | ||
113 | // given Go native structure. val must be a pointer to a struct. | ||
114 | func Decode(m interface{}, rawVal interface{}) error { | ||
115 | config := &DecoderConfig{ | ||
116 | Metadata: nil, | ||
117 | Result: rawVal, | ||
118 | } | ||
119 | |||
120 | decoder, err := NewDecoder(config) | ||
121 | if err != nil { | ||
122 | return err | ||
123 | } | ||
124 | |||
125 | return decoder.Decode(m) | ||
126 | } | ||
127 | |||
128 | // WeakDecode is the same as Decode but is shorthand to enable | ||
129 | // WeaklyTypedInput. See DecoderConfig for more info. | ||
130 | func WeakDecode(input, output interface{}) error { | ||
131 | config := &DecoderConfig{ | ||
132 | Metadata: nil, | ||
133 | Result: output, | ||
134 | WeaklyTypedInput: true, | ||
135 | } | ||
136 | |||
137 | decoder, err := NewDecoder(config) | ||
138 | if err != nil { | ||
139 | return err | ||
140 | } | ||
141 | |||
142 | return decoder.Decode(input) | ||
143 | } | ||
144 | |||
145 | // NewDecoder returns a new decoder for the given configuration. Once | ||
146 | // a decoder has been returned, the same configuration must not be used | ||
147 | // again. | ||
148 | func NewDecoder(config *DecoderConfig) (*Decoder, error) { | ||
149 | val := reflect.ValueOf(config.Result) | ||
150 | if val.Kind() != reflect.Ptr { | ||
151 | return nil, errors.New("result must be a pointer") | ||
152 | } | ||
153 | |||
154 | val = val.Elem() | ||
155 | if !val.CanAddr() { | ||
156 | return nil, errors.New("result must be addressable (a pointer)") | ||
157 | } | ||
158 | |||
159 | if config.Metadata != nil { | ||
160 | if config.Metadata.Keys == nil { | ||
161 | config.Metadata.Keys = make([]string, 0) | ||
162 | } | ||
163 | |||
164 | if config.Metadata.Unused == nil { | ||
165 | config.Metadata.Unused = make([]string, 0) | ||
166 | } | ||
167 | } | ||
168 | |||
169 | if config.TagName == "" { | ||
170 | config.TagName = "mapstructure" | ||
171 | } | ||
172 | |||
173 | result := &Decoder{ | ||
174 | config: config, | ||
175 | } | ||
176 | |||
177 | return result, nil | ||
178 | } | ||
179 | |||
180 | // Decode decodes the given raw interface to the target pointer specified | ||
181 | // by the configuration. | ||
182 | func (d *Decoder) Decode(raw interface{}) error { | ||
183 | return d.decode("", raw, reflect.ValueOf(d.config.Result).Elem()) | ||
184 | } | ||
185 | |||
186 | // Decodes an unknown data type into a specific reflection value. | ||
187 | func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { | ||
188 | if data == nil { | ||
189 | // If the data is nil, then we don't set anything. | ||
190 | return nil | ||
191 | } | ||
192 | |||
193 | dataVal := reflect.ValueOf(data) | ||
194 | if !dataVal.IsValid() { | ||
195 | // If the data value is invalid, then we just set the value | ||
196 | // to be the zero value. | ||
197 | val.Set(reflect.Zero(val.Type())) | ||
198 | return nil | ||
199 | } | ||
200 | |||
201 | if d.config.DecodeHook != nil { | ||
202 | // We have a DecodeHook, so let's pre-process the data. | ||
203 | var err error | ||
204 | data, err = DecodeHookExec( | ||
205 | d.config.DecodeHook, | ||
206 | dataVal.Type(), val.Type(), data) | ||
207 | if err != nil { | ||
208 | return fmt.Errorf("error decoding '%s': %s", name, err) | ||
209 | } | ||
210 | } | ||
211 | |||
212 | var err error | ||
213 | dataKind := getKind(val) | ||
214 | switch dataKind { | ||
215 | case reflect.Bool: | ||
216 | err = d.decodeBool(name, data, val) | ||
217 | case reflect.Interface: | ||
218 | err = d.decodeBasic(name, data, val) | ||
219 | case reflect.String: | ||
220 | err = d.decodeString(name, data, val) | ||
221 | case reflect.Int: | ||
222 | err = d.decodeInt(name, data, val) | ||
223 | case reflect.Uint: | ||
224 | err = d.decodeUint(name, data, val) | ||
225 | case reflect.Float32: | ||
226 | err = d.decodeFloat(name, data, val) | ||
227 | case reflect.Struct: | ||
228 | err = d.decodeStruct(name, data, val) | ||
229 | case reflect.Map: | ||
230 | err = d.decodeMap(name, data, val) | ||
231 | case reflect.Ptr: | ||
232 | err = d.decodePtr(name, data, val) | ||
233 | case reflect.Slice: | ||
234 | err = d.decodeSlice(name, data, val) | ||
235 | case reflect.Func: | ||
236 | err = d.decodeFunc(name, data, val) | ||
237 | default: | ||
238 | // If we reached this point then we weren't able to decode it | ||
239 | return fmt.Errorf("%s: unsupported type: %s", name, dataKind) | ||
240 | } | ||
241 | |||
242 | // If we reached here, then we successfully decoded SOMETHING, so | ||
243 | // mark the key as used if we're tracking metadata. | ||
244 | if d.config.Metadata != nil && name != "" { | ||
245 | d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) | ||
246 | } | ||
247 | |||
248 | return err | ||
249 | } | ||
250 | |||
251 | // This decodes a basic type (bool, int, string, etc.) and sets the | ||
252 | // value to "data" of that type. | ||
253 | func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { | ||
254 | dataVal := reflect.ValueOf(data) | ||
255 | if !dataVal.IsValid() { | ||
256 | dataVal = reflect.Zero(val.Type()) | ||
257 | } | ||
258 | |||
259 | dataValType := dataVal.Type() | ||
260 | if !dataValType.AssignableTo(val.Type()) { | ||
261 | return fmt.Errorf( | ||
262 | "'%s' expected type '%s', got '%s'", | ||
263 | name, val.Type(), dataValType) | ||
264 | } | ||
265 | |||
266 | val.Set(dataVal) | ||
267 | return nil | ||
268 | } | ||
269 | |||
270 | func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { | ||
271 | dataVal := reflect.ValueOf(data) | ||
272 | dataKind := getKind(dataVal) | ||
273 | |||
274 | converted := true | ||
275 | switch { | ||
276 | case dataKind == reflect.String: | ||
277 | val.SetString(dataVal.String()) | ||
278 | case dataKind == reflect.Bool && d.config.WeaklyTypedInput: | ||
279 | if dataVal.Bool() { | ||
280 | val.SetString("1") | ||
281 | } else { | ||
282 | val.SetString("0") | ||
283 | } | ||
284 | case dataKind == reflect.Int && d.config.WeaklyTypedInput: | ||
285 | val.SetString(strconv.FormatInt(dataVal.Int(), 10)) | ||
286 | case dataKind == reflect.Uint && d.config.WeaklyTypedInput: | ||
287 | val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) | ||
288 | case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: | ||
289 | val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) | ||
290 | case dataKind == reflect.Slice && d.config.WeaklyTypedInput: | ||
291 | dataType := dataVal.Type() | ||
292 | elemKind := dataType.Elem().Kind() | ||
293 | switch { | ||
294 | case elemKind == reflect.Uint8: | ||
295 | val.SetString(string(dataVal.Interface().([]uint8))) | ||
296 | default: | ||
297 | converted = false | ||
298 | } | ||
299 | default: | ||
300 | converted = false | ||
301 | } | ||
302 | |||
303 | if !converted { | ||
304 | return fmt.Errorf( | ||
305 | "'%s' expected type '%s', got unconvertible type '%s'", | ||
306 | name, val.Type(), dataVal.Type()) | ||
307 | } | ||
308 | |||
309 | return nil | ||
310 | } | ||
311 | |||
312 | func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { | ||
313 | dataVal := reflect.ValueOf(data) | ||
314 | dataKind := getKind(dataVal) | ||
315 | dataType := dataVal.Type() | ||
316 | |||
317 | switch { | ||
318 | case dataKind == reflect.Int: | ||
319 | val.SetInt(dataVal.Int()) | ||
320 | case dataKind == reflect.Uint: | ||
321 | val.SetInt(int64(dataVal.Uint())) | ||
322 | case dataKind == reflect.Float32: | ||
323 | val.SetInt(int64(dataVal.Float())) | ||
324 | case dataKind == reflect.Bool && d.config.WeaklyTypedInput: | ||
325 | if dataVal.Bool() { | ||
326 | val.SetInt(1) | ||
327 | } else { | ||
328 | val.SetInt(0) | ||
329 | } | ||
330 | case dataKind == reflect.String && d.config.WeaklyTypedInput: | ||
331 | i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) | ||
332 | if err == nil { | ||
333 | val.SetInt(i) | ||
334 | } else { | ||
335 | return fmt.Errorf("cannot parse '%s' as int: %s", name, err) | ||
336 | } | ||
337 | case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": | ||
338 | jn := data.(json.Number) | ||
339 | i, err := jn.Int64() | ||
340 | if err != nil { | ||
341 | return fmt.Errorf( | ||
342 | "error decoding json.Number into %s: %s", name, err) | ||
343 | } | ||
344 | val.SetInt(i) | ||
345 | default: | ||
346 | return fmt.Errorf( | ||
347 | "'%s' expected type '%s', got unconvertible type '%s'", | ||
348 | name, val.Type(), dataVal.Type()) | ||
349 | } | ||
350 | |||
351 | return nil | ||
352 | } | ||
353 | |||
354 | func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { | ||
355 | dataVal := reflect.ValueOf(data) | ||
356 | dataKind := getKind(dataVal) | ||
357 | |||
358 | switch { | ||
359 | case dataKind == reflect.Int: | ||
360 | i := dataVal.Int() | ||
361 | if i < 0 && !d.config.WeaklyTypedInput { | ||
362 | return fmt.Errorf("cannot parse '%s', %d overflows uint", | ||
363 | name, i) | ||
364 | } | ||
365 | val.SetUint(uint64(i)) | ||
366 | case dataKind == reflect.Uint: | ||
367 | val.SetUint(dataVal.Uint()) | ||
368 | case dataKind == reflect.Float32: | ||
369 | f := dataVal.Float() | ||
370 | if f < 0 && !d.config.WeaklyTypedInput { | ||
371 | return fmt.Errorf("cannot parse '%s', %f overflows uint", | ||
372 | name, f) | ||
373 | } | ||
374 | val.SetUint(uint64(f)) | ||
375 | case dataKind == reflect.Bool && d.config.WeaklyTypedInput: | ||
376 | if dataVal.Bool() { | ||
377 | val.SetUint(1) | ||
378 | } else { | ||
379 | val.SetUint(0) | ||
380 | } | ||
381 | case dataKind == reflect.String && d.config.WeaklyTypedInput: | ||
382 | i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) | ||
383 | if err == nil { | ||
384 | val.SetUint(i) | ||
385 | } else { | ||
386 | return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) | ||
387 | } | ||
388 | default: | ||
389 | return fmt.Errorf( | ||
390 | "'%s' expected type '%s', got unconvertible type '%s'", | ||
391 | name, val.Type(), dataVal.Type()) | ||
392 | } | ||
393 | |||
394 | return nil | ||
395 | } | ||
396 | |||
397 | func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { | ||
398 | dataVal := reflect.ValueOf(data) | ||
399 | dataKind := getKind(dataVal) | ||
400 | |||
401 | switch { | ||
402 | case dataKind == reflect.Bool: | ||
403 | val.SetBool(dataVal.Bool()) | ||
404 | case dataKind == reflect.Int && d.config.WeaklyTypedInput: | ||
405 | val.SetBool(dataVal.Int() != 0) | ||
406 | case dataKind == reflect.Uint && d.config.WeaklyTypedInput: | ||
407 | val.SetBool(dataVal.Uint() != 0) | ||
408 | case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: | ||
409 | val.SetBool(dataVal.Float() != 0) | ||
410 | case dataKind == reflect.String && d.config.WeaklyTypedInput: | ||
411 | b, err := strconv.ParseBool(dataVal.String()) | ||
412 | if err == nil { | ||
413 | val.SetBool(b) | ||
414 | } else if dataVal.String() == "" { | ||
415 | val.SetBool(false) | ||
416 | } else { | ||
417 | return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) | ||
418 | } | ||
419 | default: | ||
420 | return fmt.Errorf( | ||
421 | "'%s' expected type '%s', got unconvertible type '%s'", | ||
422 | name, val.Type(), dataVal.Type()) | ||
423 | } | ||
424 | |||
425 | return nil | ||
426 | } | ||
427 | |||
428 | func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { | ||
429 | dataVal := reflect.ValueOf(data) | ||
430 | dataKind := getKind(dataVal) | ||
431 | dataType := dataVal.Type() | ||
432 | |||
433 | switch { | ||
434 | case dataKind == reflect.Int: | ||
435 | val.SetFloat(float64(dataVal.Int())) | ||
436 | case dataKind == reflect.Uint: | ||
437 | val.SetFloat(float64(dataVal.Uint())) | ||
438 | case dataKind == reflect.Float32: | ||
439 | val.SetFloat(float64(dataVal.Float())) | ||
440 | case dataKind == reflect.Bool && d.config.WeaklyTypedInput: | ||
441 | if dataVal.Bool() { | ||
442 | val.SetFloat(1) | ||
443 | } else { | ||
444 | val.SetFloat(0) | ||
445 | } | ||
446 | case dataKind == reflect.String && d.config.WeaklyTypedInput: | ||
447 | f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) | ||
448 | if err == nil { | ||
449 | val.SetFloat(f) | ||
450 | } else { | ||
451 | return fmt.Errorf("cannot parse '%s' as float: %s", name, err) | ||
452 | } | ||
453 | case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": | ||
454 | jn := data.(json.Number) | ||
455 | i, err := jn.Float64() | ||
456 | if err != nil { | ||
457 | return fmt.Errorf( | ||
458 | "error decoding json.Number into %s: %s", name, err) | ||
459 | } | ||
460 | val.SetFloat(i) | ||
461 | default: | ||
462 | return fmt.Errorf( | ||
463 | "'%s' expected type '%s', got unconvertible type '%s'", | ||
464 | name, val.Type(), dataVal.Type()) | ||
465 | } | ||
466 | |||
467 | return nil | ||
468 | } | ||
469 | |||
470 | func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { | ||
471 | valType := val.Type() | ||
472 | valKeyType := valType.Key() | ||
473 | valElemType := valType.Elem() | ||
474 | |||
475 | // By default we overwrite keys in the current map | ||
476 | valMap := val | ||
477 | |||
478 | // If the map is nil or we're purposely zeroing fields, make a new map | ||
479 | if valMap.IsNil() || d.config.ZeroFields { | ||
480 | // Make a new map to hold our result | ||
481 | mapType := reflect.MapOf(valKeyType, valElemType) | ||
482 | valMap = reflect.MakeMap(mapType) | ||
483 | } | ||
484 | |||
485 | // Check input type | ||
486 | dataVal := reflect.Indirect(reflect.ValueOf(data)) | ||
487 | if dataVal.Kind() != reflect.Map { | ||
488 | // In weak mode, we accept a slice of maps as an input... | ||
489 | if d.config.WeaklyTypedInput { | ||
490 | switch dataVal.Kind() { | ||
491 | case reflect.Array, reflect.Slice: | ||
492 | // Special case for BC reasons (covered by tests) | ||
493 | if dataVal.Len() == 0 { | ||
494 | val.Set(valMap) | ||
495 | return nil | ||
496 | } | ||
497 | |||
498 | for i := 0; i < dataVal.Len(); i++ { | ||
499 | err := d.decode( | ||
500 | fmt.Sprintf("%s[%d]", name, i), | ||
501 | dataVal.Index(i).Interface(), val) | ||
502 | if err != nil { | ||
503 | return err | ||
504 | } | ||
505 | } | ||
506 | |||
507 | return nil | ||
508 | } | ||
509 | } | ||
510 | |||
511 | return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) | ||
512 | } | ||
513 | |||
514 | // Accumulate errors | ||
515 | errors := make([]string, 0) | ||
516 | |||
517 | for _, k := range dataVal.MapKeys() { | ||
518 | fieldName := fmt.Sprintf("%s[%s]", name, k) | ||
519 | |||
520 | // First decode the key into the proper type | ||
521 | currentKey := reflect.Indirect(reflect.New(valKeyType)) | ||
522 | if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { | ||
523 | errors = appendErrors(errors, err) | ||
524 | continue | ||
525 | } | ||
526 | |||
527 | // Next decode the data into the proper type | ||
528 | v := dataVal.MapIndex(k).Interface() | ||
529 | currentVal := reflect.Indirect(reflect.New(valElemType)) | ||
530 | if err := d.decode(fieldName, v, currentVal); err != nil { | ||
531 | errors = appendErrors(errors, err) | ||
532 | continue | ||
533 | } | ||
534 | |||
535 | valMap.SetMapIndex(currentKey, currentVal) | ||
536 | } | ||
537 | |||
538 | // Set the built up map to the value | ||
539 | val.Set(valMap) | ||
540 | |||
541 | // If we had errors, return those | ||
542 | if len(errors) > 0 { | ||
543 | return &Error{errors} | ||
544 | } | ||
545 | |||
546 | return nil | ||
547 | } | ||
548 | |||
549 | func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { | ||
550 | // Create an element of the concrete (non pointer) type and decode | ||
551 | // into that. Then set the value of the pointer to this type. | ||
552 | valType := val.Type() | ||
553 | valElemType := valType.Elem() | ||
554 | |||
555 | realVal := val | ||
556 | if realVal.IsNil() || d.config.ZeroFields { | ||
557 | realVal = reflect.New(valElemType) | ||
558 | } | ||
559 | |||
560 | if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { | ||
561 | return err | ||
562 | } | ||
563 | |||
564 | val.Set(realVal) | ||
565 | return nil | ||
566 | } | ||
567 | |||
568 | func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { | ||
569 | // Create an element of the concrete (non pointer) type and decode | ||
570 | // into that. Then set the value of the pointer to this type. | ||
571 | dataVal := reflect.Indirect(reflect.ValueOf(data)) | ||
572 | if val.Type() != dataVal.Type() { | ||
573 | return fmt.Errorf( | ||
574 | "'%s' expected type '%s', got unconvertible type '%s'", | ||
575 | name, val.Type(), dataVal.Type()) | ||
576 | } | ||
577 | val.Set(dataVal) | ||
578 | return nil | ||
579 | } | ||
580 | |||
581 | func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { | ||
582 | dataVal := reflect.Indirect(reflect.ValueOf(data)) | ||
583 | dataValKind := dataVal.Kind() | ||
584 | valType := val.Type() | ||
585 | valElemType := valType.Elem() | ||
586 | sliceType := reflect.SliceOf(valElemType) | ||
587 | |||
588 | valSlice := val | ||
589 | if valSlice.IsNil() || d.config.ZeroFields { | ||
590 | // Check input type | ||
591 | if dataValKind != reflect.Array && dataValKind != reflect.Slice { | ||
592 | if d.config.WeaklyTypedInput { | ||
593 | switch { | ||
594 | // Empty maps turn into empty slices | ||
595 | case dataValKind == reflect.Map: | ||
596 | if dataVal.Len() == 0 { | ||
597 | val.Set(reflect.MakeSlice(sliceType, 0, 0)) | ||
598 | return nil | ||
599 | } | ||
600 | |||
601 | // All other types we try to convert to the slice type | ||
602 | // and "lift" it into it. i.e. a string becomes a string slice. | ||
603 | default: | ||
604 | // Just re-try this function with data as a slice. | ||
605 | return d.decodeSlice(name, []interface{}{data}, val) | ||
606 | } | ||
607 | } | ||
608 | |||
609 | return fmt.Errorf( | ||
610 | "'%s': source data must be an array or slice, got %s", name, dataValKind) | ||
611 | |||
612 | } | ||
613 | |||
614 | // Make a new slice to hold our result, same size as the original data. | ||
615 | valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) | ||
616 | } | ||
617 | |||
618 | // Accumulate any errors | ||
619 | errors := make([]string, 0) | ||
620 | |||
621 | for i := 0; i < dataVal.Len(); i++ { | ||
622 | currentData := dataVal.Index(i).Interface() | ||
623 | for valSlice.Len() <= i { | ||
624 | valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) | ||
625 | } | ||
626 | currentField := valSlice.Index(i) | ||
627 | |||
628 | fieldName := fmt.Sprintf("%s[%d]", name, i) | ||
629 | if err := d.decode(fieldName, currentData, currentField); err != nil { | ||
630 | errors = appendErrors(errors, err) | ||
631 | } | ||
632 | } | ||
633 | |||
634 | // Finally, set the value to the slice we built up | ||
635 | val.Set(valSlice) | ||
636 | |||
637 | // If there were errors, we return those | ||
638 | if len(errors) > 0 { | ||
639 | return &Error{errors} | ||
640 | } | ||
641 | |||
642 | return nil | ||
643 | } | ||
644 | |||
645 | func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { | ||
646 | dataVal := reflect.Indirect(reflect.ValueOf(data)) | ||
647 | |||
648 | // If the type of the value to write to and the data match directly, | ||
649 | // then we just set it directly instead of recursing into the structure. | ||
650 | if dataVal.Type() == val.Type() { | ||
651 | val.Set(dataVal) | ||
652 | return nil | ||
653 | } | ||
654 | |||
655 | dataValKind := dataVal.Kind() | ||
656 | if dataValKind != reflect.Map { | ||
657 | return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind) | ||
658 | } | ||
659 | |||
660 | dataValType := dataVal.Type() | ||
661 | if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { | ||
662 | return fmt.Errorf( | ||
663 | "'%s' needs a map with string keys, has '%s' keys", | ||
664 | name, dataValType.Key().Kind()) | ||
665 | } | ||
666 | |||
667 | dataValKeys := make(map[reflect.Value]struct{}) | ||
668 | dataValKeysUnused := make(map[interface{}]struct{}) | ||
669 | for _, dataValKey := range dataVal.MapKeys() { | ||
670 | dataValKeys[dataValKey] = struct{}{} | ||
671 | dataValKeysUnused[dataValKey.Interface()] = struct{}{} | ||
672 | } | ||
673 | |||
674 | errors := make([]string, 0) | ||
675 | |||
676 | // This slice will keep track of all the structs we'll be decoding. | ||
677 | // There can be more than one struct if there are embedded structs | ||
678 | // that are squashed. | ||
679 | structs := make([]reflect.Value, 1, 5) | ||
680 | structs[0] = val | ||
681 | |||
682 | // Compile the list of all the fields that we're going to be decoding | ||
683 | // from all the structs. | ||
684 | fields := make(map[*reflect.StructField]reflect.Value) | ||
685 | for len(structs) > 0 { | ||
686 | structVal := structs[0] | ||
687 | structs = structs[1:] | ||
688 | |||
689 | structType := structVal.Type() | ||
690 | |||
691 | for i := 0; i < structType.NumField(); i++ { | ||
692 | fieldType := structType.Field(i) | ||
693 | fieldKind := fieldType.Type.Kind() | ||
694 | |||
695 | // If "squash" is specified in the tag, we squash the field down. | ||
696 | squash := false | ||
697 | tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") | ||
698 | for _, tag := range tagParts[1:] { | ||
699 | if tag == "squash" { | ||
700 | squash = true | ||
701 | break | ||
702 | } | ||
703 | } | ||
704 | |||
705 | if squash { | ||
706 | if fieldKind != reflect.Struct { | ||
707 | errors = appendErrors(errors, | ||
708 | fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) | ||
709 | } else { | ||
710 | structs = append(structs, val.FieldByName(fieldType.Name)) | ||
711 | } | ||
712 | continue | ||
713 | } | ||
714 | |||
715 | // Normal struct field, store it away | ||
716 | fields[&fieldType] = structVal.Field(i) | ||
717 | } | ||
718 | } | ||
719 | |||
720 | for fieldType, field := range fields { | ||
721 | fieldName := fieldType.Name | ||
722 | |||
723 | tagValue := fieldType.Tag.Get(d.config.TagName) | ||
724 | tagValue = strings.SplitN(tagValue, ",", 2)[0] | ||
725 | if tagValue != "" { | ||
726 | fieldName = tagValue | ||
727 | } | ||
728 | |||
729 | rawMapKey := reflect.ValueOf(fieldName) | ||
730 | rawMapVal := dataVal.MapIndex(rawMapKey) | ||
731 | if !rawMapVal.IsValid() { | ||
732 | // Do a slower search by iterating over each key and | ||
733 | // doing case-insensitive search. | ||
734 | for dataValKey := range dataValKeys { | ||
735 | mK, ok := dataValKey.Interface().(string) | ||
736 | if !ok { | ||
737 | // Not a string key | ||
738 | continue | ||
739 | } | ||
740 | |||
741 | if strings.EqualFold(mK, fieldName) { | ||
742 | rawMapKey = dataValKey | ||
743 | rawMapVal = dataVal.MapIndex(dataValKey) | ||
744 | break | ||
745 | } | ||
746 | } | ||
747 | |||
748 | if !rawMapVal.IsValid() { | ||
749 | // There was no matching key in the map for the value in | ||
750 | // the struct. Just ignore. | ||
751 | continue | ||
752 | } | ||
753 | } | ||
754 | |||
755 | // Delete the key we're using from the unused map so we stop tracking | ||
756 | delete(dataValKeysUnused, rawMapKey.Interface()) | ||
757 | |||
758 | if !field.IsValid() { | ||
759 | // This should never happen | ||
760 | panic("field is not valid") | ||
761 | } | ||
762 | |||
763 | // If we can't set the field, then it is unexported or something, | ||
764 | // and we just continue onwards. | ||
765 | if !field.CanSet() { | ||
766 | continue | ||
767 | } | ||
768 | |||
769 | // If the name is empty string, then we're at the root, and we | ||
770 | // don't dot-join the fields. | ||
771 | if name != "" { | ||
772 | fieldName = fmt.Sprintf("%s.%s", name, fieldName) | ||
773 | } | ||
774 | |||
775 | if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil { | ||
776 | errors = appendErrors(errors, err) | ||
777 | } | ||
778 | } | ||
779 | |||
780 | if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { | ||
781 | keys := make([]string, 0, len(dataValKeysUnused)) | ||
782 | for rawKey := range dataValKeysUnused { | ||
783 | keys = append(keys, rawKey.(string)) | ||
784 | } | ||
785 | sort.Strings(keys) | ||
786 | |||
787 | err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) | ||
788 | errors = appendErrors(errors, err) | ||
789 | } | ||
790 | |||
791 | if len(errors) > 0 { | ||
792 | return &Error{errors} | ||
793 | } | ||
794 | |||
795 | // Add the unused keys to the list of unused keys if we're tracking metadata | ||
796 | if d.config.Metadata != nil { | ||
797 | for rawKey := range dataValKeysUnused { | ||
798 | key := rawKey.(string) | ||
799 | if name != "" { | ||
800 | key = fmt.Sprintf("%s.%s", name, key) | ||
801 | } | ||
802 | |||
803 | d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) | ||
804 | } | ||
805 | } | ||
806 | |||
807 | return nil | ||
808 | } | ||
809 | |||
810 | func getKind(val reflect.Value) reflect.Kind { | ||
811 | kind := val.Kind() | ||
812 | |||
813 | switch { | ||
814 | case kind >= reflect.Int && kind <= reflect.Int64: | ||
815 | return reflect.Int | ||
816 | case kind >= reflect.Uint && kind <= reflect.Uint64: | ||
817 | return reflect.Uint | ||
818 | case kind >= reflect.Float32 && kind <= reflect.Float64: | ||
819 | return reflect.Float32 | ||
820 | default: | ||
821 | return kind | ||
822 | } | ||
823 | } | ||