diff options
author | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
---|---|---|
committer | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
commit | 107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch) | |
tree | ca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/mitchellh/mapstructure | |
parent | 844b5a68d8af4791755b8f0ad293cc99f5959183 (diff) | |
download | terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip |
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/mitchellh/mapstructure')
6 files changed, 523 insertions, 111 deletions
diff --git a/vendor/github.com/mitchellh/mapstructure/.travis.yml b/vendor/github.com/mitchellh/mapstructure/.travis.yml index 7f3fe9a..1689c7d 100644 --- a/vendor/github.com/mitchellh/mapstructure/.travis.yml +++ b/vendor/github.com/mitchellh/mapstructure/.travis.yml | |||
@@ -1,7 +1,8 @@ | |||
1 | language: go | 1 | language: go |
2 | |||
3 | go: | ||
4 | - "1.11.x" | ||
5 | - tip | ||
2 | 6 | ||
3 | go: | ||
4 | - 1.4 | ||
5 | |||
6 | script: | 7 | script: |
7 | - go test | 8 | - go test |
diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md new file mode 100644 index 0000000..3b3cb72 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md | |||
@@ -0,0 +1,21 @@ | |||
1 | ## 1.1.2 | ||
2 | |||
3 | * Fix error when decode hook decodes interface implementation into interface | ||
4 | type. [GH-140] | ||
5 | |||
6 | ## 1.1.1 | ||
7 | |||
8 | * Fix panic that can happen in `decodePtr` | ||
9 | |||
10 | ## 1.1.0 | ||
11 | |||
12 | * Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133] | ||
13 | * Support struct to struct decoding [GH-137] | ||
14 | * If source map value is nil, then destination map value is nil (instead of empty) | ||
15 | * If source slice value is nil, then destination slice value is nil (instead of empty) | ||
16 | * If source pointer is nil, then destination pointer is set to nil (instead of | ||
17 | allocated zero value of type) | ||
18 | |||
19 | ## 1.0.0 | ||
20 | |||
21 | * Initial tagged stable release. | ||
diff --git a/vendor/github.com/mitchellh/mapstructure/README.md b/vendor/github.com/mitchellh/mapstructure/README.md index 659d688..0018dc7 100644 --- a/vendor/github.com/mitchellh/mapstructure/README.md +++ b/vendor/github.com/mitchellh/mapstructure/README.md | |||
@@ -1,4 +1,4 @@ | |||
1 | # mapstructure | 1 | # mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure) |
2 | 2 | ||
3 | mapstructure is a Go library for decoding generic map values to structures | 3 | mapstructure is a Go library for decoding generic map values to structures |
4 | and vice versa, while providing helpful error handling. | 4 | and vice versa, while providing helpful error handling. |
diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go index 115ae67..1f0abc6 100644 --- a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go +++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go | |||
@@ -2,6 +2,8 @@ package mapstructure | |||
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "errors" | 4 | "errors" |
5 | "fmt" | ||
6 | "net" | ||
5 | "reflect" | 7 | "reflect" |
6 | "strconv" | 8 | "strconv" |
7 | "strings" | 9 | "strings" |
@@ -38,12 +40,6 @@ func DecodeHookExec( | |||
38 | raw DecodeHookFunc, | 40 | raw DecodeHookFunc, |
39 | from reflect.Type, to reflect.Type, | 41 | from reflect.Type, to reflect.Type, |
40 | data interface{}) (interface{}, error) { | 42 | data interface{}) (interface{}, error) { |
41 | // Build our arguments that reflect expects | ||
42 | argVals := make([]reflect.Value, 3) | ||
43 | argVals[0] = reflect.ValueOf(from) | ||
44 | argVals[1] = reflect.ValueOf(to) | ||
45 | argVals[2] = reflect.ValueOf(data) | ||
46 | |||
47 | switch f := typedDecodeHook(raw).(type) { | 43 | switch f := typedDecodeHook(raw).(type) { |
48 | case DecodeHookFuncType: | 44 | case DecodeHookFuncType: |
49 | return f(from, to, data) | 45 | return f(from, to, data) |
@@ -121,6 +117,74 @@ func StringToTimeDurationHookFunc() DecodeHookFunc { | |||
121 | } | 117 | } |
122 | } | 118 | } |
123 | 119 | ||
120 | // StringToIPHookFunc returns a DecodeHookFunc that converts | ||
121 | // strings to net.IP | ||
122 | func StringToIPHookFunc() DecodeHookFunc { | ||
123 | return func( | ||
124 | f reflect.Type, | ||
125 | t reflect.Type, | ||
126 | data interface{}) (interface{}, error) { | ||
127 | if f.Kind() != reflect.String { | ||
128 | return data, nil | ||
129 | } | ||
130 | if t != reflect.TypeOf(net.IP{}) { | ||
131 | return data, nil | ||
132 | } | ||
133 | |||
134 | // Convert it by parsing | ||
135 | ip := net.ParseIP(data.(string)) | ||
136 | if ip == nil { | ||
137 | return net.IP{}, fmt.Errorf("failed parsing ip %v", data) | ||
138 | } | ||
139 | |||
140 | return ip, nil | ||
141 | } | ||
142 | } | ||
143 | |||
144 | // StringToIPNetHookFunc returns a DecodeHookFunc that converts | ||
145 | // strings to net.IPNet | ||
146 | func StringToIPNetHookFunc() DecodeHookFunc { | ||
147 | return func( | ||
148 | f reflect.Type, | ||
149 | t reflect.Type, | ||
150 | data interface{}) (interface{}, error) { | ||
151 | if f.Kind() != reflect.String { | ||
152 | return data, nil | ||
153 | } | ||
154 | if t != reflect.TypeOf(net.IPNet{}) { | ||
155 | return data, nil | ||
156 | } | ||
157 | |||
158 | // Convert it by parsing | ||
159 | _, net, err := net.ParseCIDR(data.(string)) | ||
160 | return net, err | ||
161 | } | ||
162 | } | ||
163 | |||
164 | // StringToTimeHookFunc returns a DecodeHookFunc that converts | ||
165 | // strings to time.Time. | ||
166 | func StringToTimeHookFunc(layout string) DecodeHookFunc { | ||
167 | return func( | ||
168 | f reflect.Type, | ||
169 | t reflect.Type, | ||
170 | data interface{}) (interface{}, error) { | ||
171 | if f.Kind() != reflect.String { | ||
172 | return data, nil | ||
173 | } | ||
174 | if t != reflect.TypeOf(time.Time{}) { | ||
175 | return data, nil | ||
176 | } | ||
177 | |||
178 | // Convert it by parsing | ||
179 | return time.Parse(layout, data.(string)) | ||
180 | } | ||
181 | } | ||
182 | |||
183 | // WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to | ||
184 | // the decoder. | ||
185 | // | ||
186 | // Note that this is significantly different from the WeaklyTypedInput option | ||
187 | // of the DecoderConfig. | ||
124 | func WeaklyTypedHook( | 188 | func WeaklyTypedHook( |
125 | f reflect.Kind, | 189 | f reflect.Kind, |
126 | t reflect.Kind, | 190 | t reflect.Kind, |
@@ -132,9 +196,8 @@ func WeaklyTypedHook( | |||
132 | case reflect.Bool: | 196 | case reflect.Bool: |
133 | if dataVal.Bool() { | 197 | if dataVal.Bool() { |
134 | return "1", nil | 198 | return "1", nil |
135 | } else { | ||
136 | return "0", nil | ||
137 | } | 199 | } |
200 | return "0", nil | ||
138 | case reflect.Float32: | 201 | case reflect.Float32: |
139 | return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil | 202 | return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil |
140 | case reflect.Int: | 203 | case reflect.Int: |
diff --git a/vendor/github.com/mitchellh/mapstructure/go.mod b/vendor/github.com/mitchellh/mapstructure/go.mod new file mode 100644 index 0000000..d2a7125 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/go.mod | |||
@@ -0,0 +1 @@ | |||
module github.com/mitchellh/mapstructure | |||
diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go index 6dee0ef..256ee63 100644 --- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go | |||
@@ -1,5 +1,5 @@ | |||
1 | // The mapstructure package exposes functionality to convert an | 1 | // Package mapstructure exposes functionality to convert an arbitrary |
2 | // arbitrary map[string]interface{} into a native Go structure. | 2 | // map[string]interface{} into a native Go structure. |
3 | // | 3 | // |
4 | // The Go structure can be arbitrarily complex, containing slices, | 4 | // The Go structure can be arbitrarily complex, containing slices, |
5 | // other structs, etc. and the decoder will properly decode nested | 5 | // other structs, etc. and the decoder will properly decode nested |
@@ -32,7 +32,12 @@ import ( | |||
32 | // both. | 32 | // both. |
33 | type DecodeHookFunc interface{} | 33 | type DecodeHookFunc interface{} |
34 | 34 | ||
35 | // DecodeHookFuncType is a DecodeHookFunc which has complete information about | ||
36 | // the source and target types. | ||
35 | type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) | 37 | type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) |
38 | |||
39 | // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the | ||
40 | // source and target types. | ||
36 | type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) | 41 | type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) |
37 | 42 | ||
38 | // DecoderConfig is the configuration that is used to create a new decoder | 43 | // DecoderConfig is the configuration that is used to create a new decoder |
@@ -109,12 +114,12 @@ type Metadata struct { | |||
109 | Unused []string | 114 | Unused []string |
110 | } | 115 | } |
111 | 116 | ||
112 | // Decode takes a map and uses reflection to convert it into the | 117 | // Decode takes an input structure and uses reflection to translate it to |
113 | // given Go native structure. val must be a pointer to a struct. | 118 | // the output structure. output must be a pointer to a map or struct. |
114 | func Decode(m interface{}, rawVal interface{}) error { | 119 | func Decode(input interface{}, output interface{}) error { |
115 | config := &DecoderConfig{ | 120 | config := &DecoderConfig{ |
116 | Metadata: nil, | 121 | Metadata: nil, |
117 | Result: rawVal, | 122 | Result: output, |
118 | } | 123 | } |
119 | 124 | ||
120 | decoder, err := NewDecoder(config) | 125 | decoder, err := NewDecoder(config) |
@@ -122,7 +127,7 @@ func Decode(m interface{}, rawVal interface{}) error { | |||
122 | return err | 127 | return err |
123 | } | 128 | } |
124 | 129 | ||
125 | return decoder.Decode(m) | 130 | return decoder.Decode(input) |
126 | } | 131 | } |
127 | 132 | ||
128 | // WeakDecode is the same as Decode but is shorthand to enable | 133 | // WeakDecode is the same as Decode but is shorthand to enable |
@@ -142,6 +147,40 @@ func WeakDecode(input, output interface{}) error { | |||
142 | return decoder.Decode(input) | 147 | return decoder.Decode(input) |
143 | } | 148 | } |
144 | 149 | ||
150 | // DecodeMetadata is the same as Decode, but is shorthand to | ||
151 | // enable metadata collection. See DecoderConfig for more info. | ||
152 | func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { | ||
153 | config := &DecoderConfig{ | ||
154 | Metadata: metadata, | ||
155 | Result: output, | ||
156 | } | ||
157 | |||
158 | decoder, err := NewDecoder(config) | ||
159 | if err != nil { | ||
160 | return err | ||
161 | } | ||
162 | |||
163 | return decoder.Decode(input) | ||
164 | } | ||
165 | |||
166 | // WeakDecodeMetadata is the same as Decode, but is shorthand to | ||
167 | // enable both WeaklyTypedInput and metadata collection. See | ||
168 | // DecoderConfig for more info. | ||
169 | func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { | ||
170 | config := &DecoderConfig{ | ||
171 | Metadata: metadata, | ||
172 | Result: output, | ||
173 | WeaklyTypedInput: true, | ||
174 | } | ||
175 | |||
176 | decoder, err := NewDecoder(config) | ||
177 | if err != nil { | ||
178 | return err | ||
179 | } | ||
180 | |||
181 | return decoder.Decode(input) | ||
182 | } | ||
183 | |||
145 | // NewDecoder returns a new decoder for the given configuration. Once | 184 | // NewDecoder returns a new decoder for the given configuration. Once |
146 | // a decoder has been returned, the same configuration must not be used | 185 | // a decoder has been returned, the same configuration must not be used |
147 | // again. | 186 | // again. |
@@ -179,68 +218,91 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { | |||
179 | 218 | ||
180 | // Decode decodes the given raw interface to the target pointer specified | 219 | // Decode decodes the given raw interface to the target pointer specified |
181 | // by the configuration. | 220 | // by the configuration. |
182 | func (d *Decoder) Decode(raw interface{}) error { | 221 | func (d *Decoder) Decode(input interface{}) error { |
183 | return d.decode("", raw, reflect.ValueOf(d.config.Result).Elem()) | 222 | return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) |
184 | } | 223 | } |
185 | 224 | ||
186 | // Decodes an unknown data type into a specific reflection value. | 225 | // Decodes an unknown data type into a specific reflection value. |
187 | func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { | 226 | func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { |
188 | if data == nil { | 227 | var inputVal reflect.Value |
189 | // If the data is nil, then we don't set anything. | 228 | if input != nil { |
229 | inputVal = reflect.ValueOf(input) | ||
230 | |||
231 | // We need to check here if input is a typed nil. Typed nils won't | ||
232 | // match the "input == nil" below so we check that here. | ||
233 | if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { | ||
234 | input = nil | ||
235 | } | ||
236 | } | ||
237 | |||
238 | if input == nil { | ||
239 | // If the data is nil, then we don't set anything, unless ZeroFields is set | ||
240 | // to true. | ||
241 | if d.config.ZeroFields { | ||
242 | outVal.Set(reflect.Zero(outVal.Type())) | ||
243 | |||
244 | if d.config.Metadata != nil && name != "" { | ||
245 | d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) | ||
246 | } | ||
247 | } | ||
190 | return nil | 248 | return nil |
191 | } | 249 | } |
192 | 250 | ||
193 | dataVal := reflect.ValueOf(data) | 251 | if !inputVal.IsValid() { |
194 | if !dataVal.IsValid() { | 252 | // If the input value is invalid, then we just set the value |
195 | // If the data value is invalid, then we just set the value | ||
196 | // to be the zero value. | 253 | // to be the zero value. |
197 | val.Set(reflect.Zero(val.Type())) | 254 | outVal.Set(reflect.Zero(outVal.Type())) |
255 | if d.config.Metadata != nil && name != "" { | ||
256 | d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) | ||
257 | } | ||
198 | return nil | 258 | return nil |
199 | } | 259 | } |
200 | 260 | ||
201 | if d.config.DecodeHook != nil { | 261 | if d.config.DecodeHook != nil { |
202 | // We have a DecodeHook, so let's pre-process the data. | 262 | // We have a DecodeHook, so let's pre-process the input. |
203 | var err error | 263 | var err error |
204 | data, err = DecodeHookExec( | 264 | input, err = DecodeHookExec( |
205 | d.config.DecodeHook, | 265 | d.config.DecodeHook, |
206 | dataVal.Type(), val.Type(), data) | 266 | inputVal.Type(), outVal.Type(), input) |
207 | if err != nil { | 267 | if err != nil { |
208 | return fmt.Errorf("error decoding '%s': %s", name, err) | 268 | return fmt.Errorf("error decoding '%s': %s", name, err) |
209 | } | 269 | } |
210 | } | 270 | } |
211 | 271 | ||
212 | var err error | 272 | var err error |
213 | dataKind := getKind(val) | 273 | outputKind := getKind(outVal) |
214 | switch dataKind { | 274 | switch outputKind { |
215 | case reflect.Bool: | 275 | case reflect.Bool: |
216 | err = d.decodeBool(name, data, val) | 276 | err = d.decodeBool(name, input, outVal) |
217 | case reflect.Interface: | 277 | case reflect.Interface: |
218 | err = d.decodeBasic(name, data, val) | 278 | err = d.decodeBasic(name, input, outVal) |
219 | case reflect.String: | 279 | case reflect.String: |
220 | err = d.decodeString(name, data, val) | 280 | err = d.decodeString(name, input, outVal) |
221 | case reflect.Int: | 281 | case reflect.Int: |
222 | err = d.decodeInt(name, data, val) | 282 | err = d.decodeInt(name, input, outVal) |
223 | case reflect.Uint: | 283 | case reflect.Uint: |
224 | err = d.decodeUint(name, data, val) | 284 | err = d.decodeUint(name, input, outVal) |
225 | case reflect.Float32: | 285 | case reflect.Float32: |
226 | err = d.decodeFloat(name, data, val) | 286 | err = d.decodeFloat(name, input, outVal) |
227 | case reflect.Struct: | 287 | case reflect.Struct: |
228 | err = d.decodeStruct(name, data, val) | 288 | err = d.decodeStruct(name, input, outVal) |
229 | case reflect.Map: | 289 | case reflect.Map: |
230 | err = d.decodeMap(name, data, val) | 290 | err = d.decodeMap(name, input, outVal) |
231 | case reflect.Ptr: | 291 | case reflect.Ptr: |
232 | err = d.decodePtr(name, data, val) | 292 | err = d.decodePtr(name, input, outVal) |
233 | case reflect.Slice: | 293 | case reflect.Slice: |
234 | err = d.decodeSlice(name, data, val) | 294 | err = d.decodeSlice(name, input, outVal) |
295 | case reflect.Array: | ||
296 | err = d.decodeArray(name, input, outVal) | ||
235 | case reflect.Func: | 297 | case reflect.Func: |
236 | err = d.decodeFunc(name, data, val) | 298 | err = d.decodeFunc(name, input, outVal) |
237 | default: | 299 | default: |
238 | // If we reached this point then we weren't able to decode it | 300 | // If we reached this point then we weren't able to decode it |
239 | return fmt.Errorf("%s: unsupported type: %s", name, dataKind) | 301 | return fmt.Errorf("%s: unsupported type: %s", name, outputKind) |
240 | } | 302 | } |
241 | 303 | ||
242 | // If we reached here, then we successfully decoded SOMETHING, so | 304 | // If we reached here, then we successfully decoded SOMETHING, so |
243 | // mark the key as used if we're tracking metadata. | 305 | // mark the key as used if we're tracking metainput. |
244 | if d.config.Metadata != nil && name != "" { | 306 | if d.config.Metadata != nil && name != "" { |
245 | d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) | 307 | d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) |
246 | } | 308 | } |
@@ -251,7 +313,19 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error | |||
251 | // This decodes a basic type (bool, int, string, etc.) and sets the | 313 | // This decodes a basic type (bool, int, string, etc.) and sets the |
252 | // value to "data" of that type. | 314 | // value to "data" of that type. |
253 | func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { | 315 | func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { |
316 | if val.IsValid() && val.Elem().IsValid() { | ||
317 | return d.decode(name, data, val.Elem()) | ||
318 | } | ||
319 | |||
254 | dataVal := reflect.ValueOf(data) | 320 | dataVal := reflect.ValueOf(data) |
321 | |||
322 | // If the input data is a pointer, and the assigned type is the dereference | ||
323 | // of that exact pointer, then indirect it so that we can assign it. | ||
324 | // Example: *string to string | ||
325 | if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { | ||
326 | dataVal = reflect.Indirect(dataVal) | ||
327 | } | ||
328 | |||
255 | if !dataVal.IsValid() { | 329 | if !dataVal.IsValid() { |
256 | dataVal = reflect.Zero(val.Type()) | 330 | dataVal = reflect.Zero(val.Type()) |
257 | } | 331 | } |
@@ -268,7 +342,7 @@ func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) | |||
268 | } | 342 | } |
269 | 343 | ||
270 | func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { | 344 | func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { |
271 | dataVal := reflect.ValueOf(data) | 345 | dataVal := reflect.Indirect(reflect.ValueOf(data)) |
272 | dataKind := getKind(dataVal) | 346 | dataKind := getKind(dataVal) |
273 | 347 | ||
274 | converted := true | 348 | converted := true |
@@ -287,12 +361,22 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) | |||
287 | val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) | 361 | val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) |
288 | case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: | 362 | case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: |
289 | val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) | 363 | val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) |
290 | case dataKind == reflect.Slice && d.config.WeaklyTypedInput: | 364 | case dataKind == reflect.Slice && d.config.WeaklyTypedInput, |
365 | dataKind == reflect.Array && d.config.WeaklyTypedInput: | ||
291 | dataType := dataVal.Type() | 366 | dataType := dataVal.Type() |
292 | elemKind := dataType.Elem().Kind() | 367 | elemKind := dataType.Elem().Kind() |
293 | switch { | 368 | switch elemKind { |
294 | case elemKind == reflect.Uint8: | 369 | case reflect.Uint8: |
295 | val.SetString(string(dataVal.Interface().([]uint8))) | 370 | var uints []uint8 |
371 | if dataKind == reflect.Array { | ||
372 | uints = make([]uint8, dataVal.Len(), dataVal.Len()) | ||
373 | for i := range uints { | ||
374 | uints[i] = dataVal.Index(i).Interface().(uint8) | ||
375 | } | ||
376 | } else { | ||
377 | uints = dataVal.Interface().([]uint8) | ||
378 | } | ||
379 | val.SetString(string(uints)) | ||
296 | default: | 380 | default: |
297 | converted = false | 381 | converted = false |
298 | } | 382 | } |
@@ -310,7 +394,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) | |||
310 | } | 394 | } |
311 | 395 | ||
312 | func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { | 396 | func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { |
313 | dataVal := reflect.ValueOf(data) | 397 | dataVal := reflect.Indirect(reflect.ValueOf(data)) |
314 | dataKind := getKind(dataVal) | 398 | dataKind := getKind(dataVal) |
315 | dataType := dataVal.Type() | 399 | dataType := dataVal.Type() |
316 | 400 | ||
@@ -352,7 +436,7 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er | |||
352 | } | 436 | } |
353 | 437 | ||
354 | func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { | 438 | func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { |
355 | dataVal := reflect.ValueOf(data) | 439 | dataVal := reflect.Indirect(reflect.ValueOf(data)) |
356 | dataKind := getKind(dataVal) | 440 | dataKind := getKind(dataVal) |
357 | 441 | ||
358 | switch { | 442 | switch { |
@@ -395,7 +479,7 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e | |||
395 | } | 479 | } |
396 | 480 | ||
397 | func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { | 481 | func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { |
398 | dataVal := reflect.ValueOf(data) | 482 | dataVal := reflect.Indirect(reflect.ValueOf(data)) |
399 | dataKind := getKind(dataVal) | 483 | dataKind := getKind(dataVal) |
400 | 484 | ||
401 | switch { | 485 | switch { |
@@ -426,7 +510,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e | |||
426 | } | 510 | } |
427 | 511 | ||
428 | func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { | 512 | func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { |
429 | dataVal := reflect.ValueOf(data) | 513 | dataVal := reflect.Indirect(reflect.ValueOf(data)) |
430 | dataKind := getKind(dataVal) | 514 | dataKind := getKind(dataVal) |
431 | dataType := dataVal.Type() | 515 | dataType := dataVal.Type() |
432 | 516 | ||
@@ -436,7 +520,7 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) | |||
436 | case dataKind == reflect.Uint: | 520 | case dataKind == reflect.Uint: |
437 | val.SetFloat(float64(dataVal.Uint())) | 521 | val.SetFloat(float64(dataVal.Uint())) |
438 | case dataKind == reflect.Float32: | 522 | case dataKind == reflect.Float32: |
439 | val.SetFloat(float64(dataVal.Float())) | 523 | val.SetFloat(dataVal.Float()) |
440 | case dataKind == reflect.Bool && d.config.WeaklyTypedInput: | 524 | case dataKind == reflect.Bool && d.config.WeaklyTypedInput: |
441 | if dataVal.Bool() { | 525 | if dataVal.Bool() { |
442 | val.SetFloat(1) | 526 | val.SetFloat(1) |
@@ -482,38 +566,68 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er | |||
482 | valMap = reflect.MakeMap(mapType) | 566 | valMap = reflect.MakeMap(mapType) |
483 | } | 567 | } |
484 | 568 | ||
485 | // Check input type | 569 | // Check input type and based on the input type jump to the proper func |
486 | dataVal := reflect.Indirect(reflect.ValueOf(data)) | 570 | dataVal := reflect.Indirect(reflect.ValueOf(data)) |
487 | if dataVal.Kind() != reflect.Map { | 571 | switch dataVal.Kind() { |
488 | // In weak mode, we accept a slice of maps as an input... | 572 | case reflect.Map: |
489 | if d.config.WeaklyTypedInput { | 573 | return d.decodeMapFromMap(name, dataVal, val, valMap) |
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 | 574 | ||
498 | for i := 0; i < dataVal.Len(); i++ { | 575 | case reflect.Struct: |
499 | err := d.decode( | 576 | return d.decodeMapFromStruct(name, dataVal, val, valMap) |
500 | fmt.Sprintf("%s[%d]", name, i), | ||
501 | dataVal.Index(i).Interface(), val) | ||
502 | if err != nil { | ||
503 | return err | ||
504 | } | ||
505 | } | ||
506 | 577 | ||
507 | return nil | 578 | case reflect.Array, reflect.Slice: |
508 | } | 579 | if d.config.WeaklyTypedInput { |
580 | return d.decodeMapFromSlice(name, dataVal, val, valMap) | ||
509 | } | 581 | } |
510 | 582 | ||
583 | fallthrough | ||
584 | |||
585 | default: | ||
511 | return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) | 586 | return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) |
512 | } | 587 | } |
588 | } | ||
589 | |||
590 | func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { | ||
591 | // Special case for BC reasons (covered by tests) | ||
592 | if dataVal.Len() == 0 { | ||
593 | val.Set(valMap) | ||
594 | return nil | ||
595 | } | ||
596 | |||
597 | for i := 0; i < dataVal.Len(); i++ { | ||
598 | err := d.decode( | ||
599 | fmt.Sprintf("%s[%d]", name, i), | ||
600 | dataVal.Index(i).Interface(), val) | ||
601 | if err != nil { | ||
602 | return err | ||
603 | } | ||
604 | } | ||
605 | |||
606 | return nil | ||
607 | } | ||
608 | |||
609 | func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { | ||
610 | valType := val.Type() | ||
611 | valKeyType := valType.Key() | ||
612 | valElemType := valType.Elem() | ||
513 | 613 | ||
514 | // Accumulate errors | 614 | // Accumulate errors |
515 | errors := make([]string, 0) | 615 | errors := make([]string, 0) |
516 | 616 | ||
617 | // If the input data is empty, then we just match what the input data is. | ||
618 | if dataVal.Len() == 0 { | ||
619 | if dataVal.IsNil() { | ||
620 | if !val.IsNil() { | ||
621 | val.Set(dataVal) | ||
622 | } | ||
623 | } else { | ||
624 | // Set to empty allocated value | ||
625 | val.Set(valMap) | ||
626 | } | ||
627 | |||
628 | return nil | ||
629 | } | ||
630 | |||
517 | for _, k := range dataVal.MapKeys() { | 631 | for _, k := range dataVal.MapKeys() { |
518 | fieldName := fmt.Sprintf("%s[%s]", name, k) | 632 | fieldName := fmt.Sprintf("%s[%s]", name, k) |
519 | 633 | ||
@@ -546,22 +660,128 @@ func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) er | |||
546 | return nil | 660 | return nil |
547 | } | 661 | } |
548 | 662 | ||
663 | func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { | ||
664 | typ := dataVal.Type() | ||
665 | for i := 0; i < typ.NumField(); i++ { | ||
666 | // Get the StructField first since this is a cheap operation. If the | ||
667 | // field is unexported, then ignore it. | ||
668 | f := typ.Field(i) | ||
669 | if f.PkgPath != "" { | ||
670 | continue | ||
671 | } | ||
672 | |||
673 | // Next get the actual value of this field and verify it is assignable | ||
674 | // to the map value. | ||
675 | v := dataVal.Field(i) | ||
676 | if !v.Type().AssignableTo(valMap.Type().Elem()) { | ||
677 | return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) | ||
678 | } | ||
679 | |||
680 | tagValue := f.Tag.Get(d.config.TagName) | ||
681 | tagParts := strings.Split(tagValue, ",") | ||
682 | |||
683 | // Determine the name of the key in the map | ||
684 | keyName := f.Name | ||
685 | if tagParts[0] != "" { | ||
686 | if tagParts[0] == "-" { | ||
687 | continue | ||
688 | } | ||
689 | keyName = tagParts[0] | ||
690 | } | ||
691 | |||
692 | // If "squash" is specified in the tag, we squash the field down. | ||
693 | squash := false | ||
694 | for _, tag := range tagParts[1:] { | ||
695 | if tag == "squash" { | ||
696 | squash = true | ||
697 | break | ||
698 | } | ||
699 | } | ||
700 | if squash && v.Kind() != reflect.Struct { | ||
701 | return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) | ||
702 | } | ||
703 | |||
704 | switch v.Kind() { | ||
705 | // this is an embedded struct, so handle it differently | ||
706 | case reflect.Struct: | ||
707 | x := reflect.New(v.Type()) | ||
708 | x.Elem().Set(v) | ||
709 | |||
710 | vType := valMap.Type() | ||
711 | vKeyType := vType.Key() | ||
712 | vElemType := vType.Elem() | ||
713 | mType := reflect.MapOf(vKeyType, vElemType) | ||
714 | vMap := reflect.MakeMap(mType) | ||
715 | |||
716 | err := d.decode(keyName, x.Interface(), vMap) | ||
717 | if err != nil { | ||
718 | return err | ||
719 | } | ||
720 | |||
721 | if squash { | ||
722 | for _, k := range vMap.MapKeys() { | ||
723 | valMap.SetMapIndex(k, vMap.MapIndex(k)) | ||
724 | } | ||
725 | } else { | ||
726 | valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) | ||
727 | } | ||
728 | |||
729 | default: | ||
730 | valMap.SetMapIndex(reflect.ValueOf(keyName), v) | ||
731 | } | ||
732 | } | ||
733 | |||
734 | if val.CanAddr() { | ||
735 | val.Set(valMap) | ||
736 | } | ||
737 | |||
738 | return nil | ||
739 | } | ||
740 | |||
549 | func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { | 741 | func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { |
742 | // If the input data is nil, then we want to just set the output | ||
743 | // pointer to be nil as well. | ||
744 | isNil := data == nil | ||
745 | if !isNil { | ||
746 | switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { | ||
747 | case reflect.Chan, | ||
748 | reflect.Func, | ||
749 | reflect.Interface, | ||
750 | reflect.Map, | ||
751 | reflect.Ptr, | ||
752 | reflect.Slice: | ||
753 | isNil = v.IsNil() | ||
754 | } | ||
755 | } | ||
756 | if isNil { | ||
757 | if !val.IsNil() && val.CanSet() { | ||
758 | nilValue := reflect.New(val.Type()).Elem() | ||
759 | val.Set(nilValue) | ||
760 | } | ||
761 | |||
762 | return nil | ||
763 | } | ||
764 | |||
550 | // Create an element of the concrete (non pointer) type and decode | 765 | // Create an element of the concrete (non pointer) type and decode |
551 | // into that. Then set the value of the pointer to this type. | 766 | // into that. Then set the value of the pointer to this type. |
552 | valType := val.Type() | 767 | valType := val.Type() |
553 | valElemType := valType.Elem() | 768 | valElemType := valType.Elem() |
769 | if val.CanSet() { | ||
770 | realVal := val | ||
771 | if realVal.IsNil() || d.config.ZeroFields { | ||
772 | realVal = reflect.New(valElemType) | ||
773 | } | ||
554 | 774 | ||
555 | realVal := val | 775 | if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { |
556 | if realVal.IsNil() || d.config.ZeroFields { | 776 | return err |
557 | realVal = reflect.New(valElemType) | 777 | } |
558 | } | ||
559 | 778 | ||
560 | if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { | 779 | val.Set(realVal) |
561 | return err | 780 | } else { |
781 | if err := d.decode(name, data, reflect.Indirect(val)); err != nil { | ||
782 | return err | ||
783 | } | ||
562 | } | 784 | } |
563 | |||
564 | val.Set(realVal) | ||
565 | return nil | 785 | return nil |
566 | } | 786 | } |
567 | 787 | ||
@@ -587,22 +807,101 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) | |||
587 | 807 | ||
588 | valSlice := val | 808 | valSlice := val |
589 | if valSlice.IsNil() || d.config.ZeroFields { | 809 | if valSlice.IsNil() || d.config.ZeroFields { |
810 | if d.config.WeaklyTypedInput { | ||
811 | switch { | ||
812 | // Slice and array we use the normal logic | ||
813 | case dataValKind == reflect.Slice, dataValKind == reflect.Array: | ||
814 | break | ||
815 | |||
816 | // Empty maps turn into empty slices | ||
817 | case dataValKind == reflect.Map: | ||
818 | if dataVal.Len() == 0 { | ||
819 | val.Set(reflect.MakeSlice(sliceType, 0, 0)) | ||
820 | return nil | ||
821 | } | ||
822 | // Create slice of maps of other sizes | ||
823 | return d.decodeSlice(name, []interface{}{data}, val) | ||
824 | |||
825 | case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: | ||
826 | return d.decodeSlice(name, []byte(dataVal.String()), val) | ||
827 | |||
828 | // All other types we try to convert to the slice type | ||
829 | // and "lift" it into it. i.e. a string becomes a string slice. | ||
830 | default: | ||
831 | // Just re-try this function with data as a slice. | ||
832 | return d.decodeSlice(name, []interface{}{data}, val) | ||
833 | } | ||
834 | } | ||
835 | |||
836 | // Check input type | ||
837 | if dataValKind != reflect.Array && dataValKind != reflect.Slice { | ||
838 | return fmt.Errorf( | ||
839 | "'%s': source data must be an array or slice, got %s", name, dataValKind) | ||
840 | |||
841 | } | ||
842 | |||
843 | // If the input value is empty, then don't allocate since non-nil != nil | ||
844 | if dataVal.Len() == 0 { | ||
845 | return nil | ||
846 | } | ||
847 | |||
848 | // Make a new slice to hold our result, same size as the original data. | ||
849 | valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) | ||
850 | } | ||
851 | |||
852 | // Accumulate any errors | ||
853 | errors := make([]string, 0) | ||
854 | |||
855 | for i := 0; i < dataVal.Len(); i++ { | ||
856 | currentData := dataVal.Index(i).Interface() | ||
857 | for valSlice.Len() <= i { | ||
858 | valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) | ||
859 | } | ||
860 | currentField := valSlice.Index(i) | ||
861 | |||
862 | fieldName := fmt.Sprintf("%s[%d]", name, i) | ||
863 | if err := d.decode(fieldName, currentData, currentField); err != nil { | ||
864 | errors = appendErrors(errors, err) | ||
865 | } | ||
866 | } | ||
867 | |||
868 | // Finally, set the value to the slice we built up | ||
869 | val.Set(valSlice) | ||
870 | |||
871 | // If there were errors, we return those | ||
872 | if len(errors) > 0 { | ||
873 | return &Error{errors} | ||
874 | } | ||
875 | |||
876 | return nil | ||
877 | } | ||
878 | |||
879 | func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { | ||
880 | dataVal := reflect.Indirect(reflect.ValueOf(data)) | ||
881 | dataValKind := dataVal.Kind() | ||
882 | valType := val.Type() | ||
883 | valElemType := valType.Elem() | ||
884 | arrayType := reflect.ArrayOf(valType.Len(), valElemType) | ||
885 | |||
886 | valArray := val | ||
887 | |||
888 | if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { | ||
590 | // Check input type | 889 | // Check input type |
591 | if dataValKind != reflect.Array && dataValKind != reflect.Slice { | 890 | if dataValKind != reflect.Array && dataValKind != reflect.Slice { |
592 | if d.config.WeaklyTypedInput { | 891 | if d.config.WeaklyTypedInput { |
593 | switch { | 892 | switch { |
594 | // Empty maps turn into empty slices | 893 | // Empty maps turn into empty arrays |
595 | case dataValKind == reflect.Map: | 894 | case dataValKind == reflect.Map: |
596 | if dataVal.Len() == 0 { | 895 | if dataVal.Len() == 0 { |
597 | val.Set(reflect.MakeSlice(sliceType, 0, 0)) | 896 | val.Set(reflect.Zero(arrayType)) |
598 | return nil | 897 | return nil |
599 | } | 898 | } |
600 | 899 | ||
601 | // All other types we try to convert to the slice type | 900 | // All other types we try to convert to the array type |
602 | // and "lift" it into it. i.e. a string becomes a string slice. | 901 | // and "lift" it into it. i.e. a string becomes a string array. |
603 | default: | 902 | default: |
604 | // Just re-try this function with data as a slice. | 903 | // Just re-try this function with data as a slice. |
605 | return d.decodeSlice(name, []interface{}{data}, val) | 904 | return d.decodeArray(name, []interface{}{data}, val) |
606 | } | 905 | } |
607 | } | 906 | } |
608 | 907 | ||
@@ -610,9 +909,14 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) | |||
610 | "'%s': source data must be an array or slice, got %s", name, dataValKind) | 909 | "'%s': source data must be an array or slice, got %s", name, dataValKind) |
611 | 910 | ||
612 | } | 911 | } |
912 | if dataVal.Len() > arrayType.Len() { | ||
913 | return fmt.Errorf( | ||
914 | "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) | ||
613 | 915 | ||
614 | // Make a new slice to hold our result, same size as the original data. | 916 | } |
615 | valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) | 917 | |
918 | // Make a new array to hold our result, same size as the original data. | ||
919 | valArray = reflect.New(arrayType).Elem() | ||
616 | } | 920 | } |
617 | 921 | ||
618 | // Accumulate any errors | 922 | // Accumulate any errors |
@@ -620,10 +924,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) | |||
620 | 924 | ||
621 | for i := 0; i < dataVal.Len(); i++ { | 925 | for i := 0; i < dataVal.Len(); i++ { |
622 | currentData := dataVal.Index(i).Interface() | 926 | currentData := dataVal.Index(i).Interface() |
623 | for valSlice.Len() <= i { | 927 | currentField := valArray.Index(i) |
624 | valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) | ||
625 | } | ||
626 | currentField := valSlice.Index(i) | ||
627 | 928 | ||
628 | fieldName := fmt.Sprintf("%s[%d]", name, i) | 929 | fieldName := fmt.Sprintf("%s[%d]", name, i) |
629 | if err := d.decode(fieldName, currentData, currentField); err != nil { | 930 | if err := d.decode(fieldName, currentData, currentField); err != nil { |
@@ -631,8 +932,8 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) | |||
631 | } | 932 | } |
632 | } | 933 | } |
633 | 934 | ||
634 | // Finally, set the value to the slice we built up | 935 | // Finally, set the value to the array we built up |
635 | val.Set(valSlice) | 936 | val.Set(valArray) |
636 | 937 | ||
637 | // If there were errors, we return those | 938 | // If there were errors, we return those |
638 | if len(errors) > 0 { | 939 | if len(errors) > 0 { |
@@ -653,10 +954,29 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) | |||
653 | } | 954 | } |
654 | 955 | ||
655 | dataValKind := dataVal.Kind() | 956 | dataValKind := dataVal.Kind() |
656 | if dataValKind != reflect.Map { | 957 | switch dataValKind { |
657 | return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind) | 958 | case reflect.Map: |
959 | return d.decodeStructFromMap(name, dataVal, val) | ||
960 | |||
961 | case reflect.Struct: | ||
962 | // Not the most efficient way to do this but we can optimize later if | ||
963 | // we want to. To convert from struct to struct we go to map first | ||
964 | // as an intermediary. | ||
965 | m := make(map[string]interface{}) | ||
966 | mval := reflect.Indirect(reflect.ValueOf(&m)) | ||
967 | if err := d.decodeMapFromStruct(name, dataVal, mval, mval); err != nil { | ||
968 | return err | ||
969 | } | ||
970 | |||
971 | result := d.decodeStructFromMap(name, mval, val) | ||
972 | return result | ||
973 | |||
974 | default: | ||
975 | return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) | ||
658 | } | 976 | } |
977 | } | ||
659 | 978 | ||
979 | func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { | ||
660 | dataValType := dataVal.Type() | 980 | dataValType := dataVal.Type() |
661 | if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { | 981 | if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { |
662 | return fmt.Errorf( | 982 | return fmt.Errorf( |
@@ -681,7 +1001,11 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) | |||
681 | 1001 | ||
682 | // Compile the list of all the fields that we're going to be decoding | 1002 | // Compile the list of all the fields that we're going to be decoding |
683 | // from all the structs. | 1003 | // from all the structs. |
684 | fields := make(map[*reflect.StructField]reflect.Value) | 1004 | type field struct { |
1005 | field reflect.StructField | ||
1006 | val reflect.Value | ||
1007 | } | ||
1008 | fields := []field{} | ||
685 | for len(structs) > 0 { | 1009 | for len(structs) > 0 { |
686 | structVal := structs[0] | 1010 | structVal := structs[0] |
687 | structs = structs[1:] | 1011 | structs = structs[1:] |
@@ -707,20 +1031,22 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) | |||
707 | errors = appendErrors(errors, | 1031 | errors = appendErrors(errors, |
708 | fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) | 1032 | fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) |
709 | } else { | 1033 | } else { |
710 | structs = append(structs, val.FieldByName(fieldType.Name)) | 1034 | structs = append(structs, structVal.FieldByName(fieldType.Name)) |
711 | } | 1035 | } |
712 | continue | 1036 | continue |
713 | } | 1037 | } |
714 | 1038 | ||
715 | // Normal struct field, store it away | 1039 | // Normal struct field, store it away |
716 | fields[&fieldType] = structVal.Field(i) | 1040 | fields = append(fields, field{fieldType, structVal.Field(i)}) |
717 | } | 1041 | } |
718 | } | 1042 | } |
719 | 1043 | ||
720 | for fieldType, field := range fields { | 1044 | // for fieldType, field := range fields { |
721 | fieldName := fieldType.Name | 1045 | for _, f := range fields { |
1046 | field, fieldValue := f.field, f.val | ||
1047 | fieldName := field.Name | ||
722 | 1048 | ||
723 | tagValue := fieldType.Tag.Get(d.config.TagName) | 1049 | tagValue := field.Tag.Get(d.config.TagName) |
724 | tagValue = strings.SplitN(tagValue, ",", 2)[0] | 1050 | tagValue = strings.SplitN(tagValue, ",", 2)[0] |
725 | if tagValue != "" { | 1051 | if tagValue != "" { |
726 | fieldName = tagValue | 1052 | fieldName = tagValue |
@@ -755,14 +1081,14 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) | |||
755 | // Delete the key we're using from the unused map so we stop tracking | 1081 | // Delete the key we're using from the unused map so we stop tracking |
756 | delete(dataValKeysUnused, rawMapKey.Interface()) | 1082 | delete(dataValKeysUnused, rawMapKey.Interface()) |
757 | 1083 | ||
758 | if !field.IsValid() { | 1084 | if !fieldValue.IsValid() { |
759 | // This should never happen | 1085 | // This should never happen |
760 | panic("field is not valid") | 1086 | panic("field is not valid") |
761 | } | 1087 | } |
762 | 1088 | ||
763 | // If we can't set the field, then it is unexported or something, | 1089 | // If we can't set the field, then it is unexported or something, |
764 | // and we just continue onwards. | 1090 | // and we just continue onwards. |
765 | if !field.CanSet() { | 1091 | if !fieldValue.CanSet() { |
766 | continue | 1092 | continue |
767 | } | 1093 | } |
768 | 1094 | ||
@@ -772,7 +1098,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) | |||
772 | fieldName = fmt.Sprintf("%s.%s", name, fieldName) | 1098 | fieldName = fmt.Sprintf("%s.%s", name, fieldName) |
773 | } | 1099 | } |
774 | 1100 | ||
775 | if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil { | 1101 | if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { |
776 | errors = appendErrors(errors, err) | 1102 | errors = appendErrors(errors, err) |
777 | } | 1103 | } |
778 | } | 1104 | } |