aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/mitchellh
diff options
context:
space:
mode:
authorJake Champlin <jake.champlin.27@gmail.com>2017-06-06 12:40:07 -0400
committerJake Champlin <jake.champlin.27@gmail.com>2017-06-06 12:40:07 -0400
commitbae9f6d2fd5eb5bc80929bd393932b23f14d7c93 (patch)
treeca9ab12a7d78b1fc27a8f734729081357ce6d252 /vendor/github.com/mitchellh
parent254c495b6bebab3fb72a243c4bce858d79e6ee99 (diff)
downloadterraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.gz
terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.zst
terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.zip
Initial transfer of provider code
Diffstat (limited to 'vendor/github.com/mitchellh')
-rw-r--r--vendor/github.com/mitchellh/copystructure/LICENSE21
-rw-r--r--vendor/github.com/mitchellh/copystructure/README.md21
-rw-r--r--vendor/github.com/mitchellh/copystructure/copier_time.go15
-rw-r--r--vendor/github.com/mitchellh/copystructure/copystructure.go477
-rw-r--r--vendor/github.com/mitchellh/go-homedir/LICENSE21
-rw-r--r--vendor/github.com/mitchellh/go-homedir/README.md14
-rw-r--r--vendor/github.com/mitchellh/go-homedir/homedir.go137
-rw-r--r--vendor/github.com/mitchellh/hashstructure/LICENSE21
-rw-r--r--vendor/github.com/mitchellh/hashstructure/README.md61
-rw-r--r--vendor/github.com/mitchellh/hashstructure/hashstructure.go323
-rw-r--r--vendor/github.com/mitchellh/hashstructure/include.go15
-rw-r--r--vendor/github.com/mitchellh/mapstructure/LICENSE21
-rw-r--r--vendor/github.com/mitchellh/mapstructure/README.md46
-rw-r--r--vendor/github.com/mitchellh/mapstructure/decode_hooks.go154
-rw-r--r--vendor/github.com/mitchellh/mapstructure/error.go50
-rw-r--r--vendor/github.com/mitchellh/mapstructure/mapstructure.go823
-rw-r--r--vendor/github.com/mitchellh/reflectwalk/LICENSE21
-rw-r--r--vendor/github.com/mitchellh/reflectwalk/README.md6
-rw-r--r--vendor/github.com/mitchellh/reflectwalk/location.go17
-rw-r--r--vendor/github.com/mitchellh/reflectwalk/location_string.go16
-rw-r--r--vendor/github.com/mitchellh/reflectwalk/reflectwalk.go339
21 files changed, 2619 insertions, 0 deletions
diff --git a/vendor/github.com/mitchellh/copystructure/LICENSE b/vendor/github.com/mitchellh/copystructure/LICENSE
new file mode 100644
index 0000000..2298515
--- /dev/null
+++ b/vendor/github.com/mitchellh/copystructure/LICENSE
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2014 Mitchell Hashimoto
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
diff --git a/vendor/github.com/mitchellh/copystructure/README.md b/vendor/github.com/mitchellh/copystructure/README.md
new file mode 100644
index 0000000..bcb8c8d
--- /dev/null
+++ b/vendor/github.com/mitchellh/copystructure/README.md
@@ -0,0 +1,21 @@
1# copystructure
2
3copystructure is a Go library for deep copying values in Go.
4
5This allows you to copy Go values that may contain reference values
6such as maps, slices, or pointers, and copy their data as well instead
7of just their references.
8
9## Installation
10
11Standard `go get`:
12
13```
14$ go get github.com/mitchellh/copystructure
15```
16
17## Usage & Example
18
19For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/copystructure).
20
21The `Copy` function has examples associated with it there.
diff --git a/vendor/github.com/mitchellh/copystructure/copier_time.go b/vendor/github.com/mitchellh/copystructure/copier_time.go
new file mode 100644
index 0000000..db6a6aa
--- /dev/null
+++ b/vendor/github.com/mitchellh/copystructure/copier_time.go
@@ -0,0 +1,15 @@
1package copystructure
2
3import (
4 "reflect"
5 "time"
6)
7
8func init() {
9 Copiers[reflect.TypeOf(time.Time{})] = timeCopier
10}
11
12func timeCopier(v interface{}) (interface{}, error) {
13 // Just... copy it.
14 return v.(time.Time), nil
15}
diff --git a/vendor/github.com/mitchellh/copystructure/copystructure.go b/vendor/github.com/mitchellh/copystructure/copystructure.go
new file mode 100644
index 0000000..0e725ea
--- /dev/null
+++ b/vendor/github.com/mitchellh/copystructure/copystructure.go
@@ -0,0 +1,477 @@
1package copystructure
2
3import (
4 "errors"
5 "reflect"
6 "sync"
7
8 "github.com/mitchellh/reflectwalk"
9)
10
11// Copy returns a deep copy of v.
12func Copy(v interface{}) (interface{}, error) {
13 return Config{}.Copy(v)
14}
15
16// CopierFunc is a function that knows how to deep copy a specific type.
17// Register these globally with the Copiers variable.
18type CopierFunc func(interface{}) (interface{}, error)
19
20// Copiers is a map of types that behave specially when they are copied.
21// If a type is found in this map while deep copying, this function
22// will be called to copy it instead of attempting to copy all fields.
23//
24// The key should be the type, obtained using: reflect.TypeOf(value with type).
25//
26// It is unsafe to write to this map after Copies have started. If you
27// are writing to this map while also copying, wrap all modifications to
28// this map as well as to Copy in a mutex.
29var Copiers map[reflect.Type]CopierFunc = make(map[reflect.Type]CopierFunc)
30
31// Must is a helper that wraps a call to a function returning
32// (interface{}, error) and panics if the error is non-nil. It is intended
33// for use in variable initializations and should only be used when a copy
34// error should be a crashing case.
35func Must(v interface{}, err error) interface{} {
36 if err != nil {
37 panic("copy error: " + err.Error())
38 }
39
40 return v
41}
42
43var errPointerRequired = errors.New("Copy argument must be a pointer when Lock is true")
44
45type Config struct {
46 // Lock any types that are a sync.Locker and are not a mutex while copying.
47 // If there is an RLocker method, use that to get the sync.Locker.
48 Lock bool
49
50 // Copiers is a map of types associated with a CopierFunc. Use the global
51 // Copiers map if this is nil.
52 Copiers map[reflect.Type]CopierFunc
53}
54
55func (c Config) Copy(v interface{}) (interface{}, error) {
56 if c.Lock && reflect.ValueOf(v).Kind() != reflect.Ptr {
57 return nil, errPointerRequired
58 }
59
60 w := new(walker)
61 if c.Lock {
62 w.useLocks = true
63 }
64
65 if c.Copiers == nil {
66 c.Copiers = Copiers
67 }
68
69 err := reflectwalk.Walk(v, w)
70 if err != nil {
71 return nil, err
72 }
73
74 // Get the result. If the result is nil, then we want to turn it
75 // into a typed nil if we can.
76 result := w.Result
77 if result == nil {
78 val := reflect.ValueOf(v)
79 result = reflect.Indirect(reflect.New(val.Type())).Interface()
80 }
81
82 return result, nil
83}
84
85// Return the key used to index interfaces types we've seen. Store the number
86// of pointers in the upper 32bits, and the depth in the lower 32bits. This is
87// easy to calculate, easy to match a key with our current depth, and we don't
88// need to deal with initializing and cleaning up nested maps or slices.
89func ifaceKey(pointers, depth int) uint64 {
90 return uint64(pointers)<<32 | uint64(depth)
91}
92
93type walker struct {
94 Result interface{}
95
96 depth int
97 ignoreDepth int
98 vals []reflect.Value
99 cs []reflect.Value
100
101 // This stores the number of pointers we've walked over, indexed by depth.
102 ps []int
103
104 // If an interface is indirected by a pointer, we need to know the type of
105 // interface to create when creating the new value. Store the interface
106 // types here, indexed by both the walk depth and the number of pointers
107 // already seen at that depth. Use ifaceKey to calculate the proper uint64
108 // value.
109 ifaceTypes map[uint64]reflect.Type
110
111 // any locks we've taken, indexed by depth
112 locks []sync.Locker
113 // take locks while walking the structure
114 useLocks bool
115}
116
117func (w *walker) Enter(l reflectwalk.Location) error {
118 w.depth++
119
120 // ensure we have enough elements to index via w.depth
121 for w.depth >= len(w.locks) {
122 w.locks = append(w.locks, nil)
123 }
124
125 for len(w.ps) < w.depth+1 {
126 w.ps = append(w.ps, 0)
127 }
128
129 return nil
130}
131
132func (w *walker) Exit(l reflectwalk.Location) error {
133 locker := w.locks[w.depth]
134 w.locks[w.depth] = nil
135 if locker != nil {
136 defer locker.Unlock()
137 }
138
139 // clear out pointers and interfaces as we exit the stack
140 w.ps[w.depth] = 0
141
142 for k := range w.ifaceTypes {
143 mask := uint64(^uint32(0))
144 if k&mask == uint64(w.depth) {
145 delete(w.ifaceTypes, k)
146 }
147 }
148
149 w.depth--
150 if w.ignoreDepth > w.depth {
151 w.ignoreDepth = 0
152 }
153
154 if w.ignoring() {
155 return nil
156 }
157
158 switch l {
159 case reflectwalk.Map:
160 fallthrough
161 case reflectwalk.Slice:
162 // Pop map off our container
163 w.cs = w.cs[:len(w.cs)-1]
164 case reflectwalk.MapValue:
165 // Pop off the key and value
166 mv := w.valPop()
167 mk := w.valPop()
168 m := w.cs[len(w.cs)-1]
169
170 // If mv is the zero value, SetMapIndex deletes the key form the map,
171 // or in this case never adds it. We need to create a properly typed
172 // zero value so that this key can be set.
173 if !mv.IsValid() {
174 mv = reflect.Zero(m.Type().Elem())
175 }
176 m.SetMapIndex(mk, mv)
177 case reflectwalk.SliceElem:
178 // Pop off the value and the index and set it on the slice
179 v := w.valPop()
180 i := w.valPop().Interface().(int)
181 if v.IsValid() {
182 s := w.cs[len(w.cs)-1]
183 se := s.Index(i)
184 if se.CanSet() {
185 se.Set(v)
186 }
187 }
188 case reflectwalk.Struct:
189 w.replacePointerMaybe()
190
191 // Remove the struct from the container stack
192 w.cs = w.cs[:len(w.cs)-1]
193 case reflectwalk.StructField:
194 // Pop off the value and the field
195 v := w.valPop()
196 f := w.valPop().Interface().(reflect.StructField)
197 if v.IsValid() {
198 s := w.cs[len(w.cs)-1]
199 sf := reflect.Indirect(s).FieldByName(f.Name)
200
201 if sf.CanSet() {
202 sf.Set(v)
203 }
204 }
205 case reflectwalk.WalkLoc:
206 // Clear out the slices for GC
207 w.cs = nil
208 w.vals = nil
209 }
210
211 return nil
212}
213
214func (w *walker) Map(m reflect.Value) error {
215 if w.ignoring() {
216 return nil
217 }
218 w.lock(m)
219
220 // Create the map. If the map itself is nil, then just make a nil map
221 var newMap reflect.Value
222 if m.IsNil() {
223 newMap = reflect.Indirect(reflect.New(m.Type()))
224 } else {
225 newMap = reflect.MakeMap(m.Type())
226 }
227
228 w.cs = append(w.cs, newMap)
229 w.valPush(newMap)
230 return nil
231}
232
233func (w *walker) MapElem(m, k, v reflect.Value) error {
234 return nil
235}
236
237func (w *walker) PointerEnter(v bool) error {
238 if v {
239 w.ps[w.depth]++
240 }
241 return nil
242}
243
244func (w *walker) PointerExit(v bool) error {
245 if v {
246 w.ps[w.depth]--
247 }
248 return nil
249}
250
251func (w *walker) Interface(v reflect.Value) error {
252 if !v.IsValid() {
253 return nil
254 }
255 if w.ifaceTypes == nil {
256 w.ifaceTypes = make(map[uint64]reflect.Type)
257 }
258
259 w.ifaceTypes[ifaceKey(w.ps[w.depth], w.depth)] = v.Type()
260 return nil
261}
262
263func (w *walker) Primitive(v reflect.Value) error {
264 if w.ignoring() {
265 return nil
266 }
267 w.lock(v)
268
269 // IsValid verifies the v is non-zero and CanInterface verifies
270 // that we're allowed to read this value (unexported fields).
271 var newV reflect.Value
272 if v.IsValid() && v.CanInterface() {
273 newV = reflect.New(v.Type())
274 newV.Elem().Set(v)
275 }
276
277 w.valPush(newV)
278 w.replacePointerMaybe()
279 return nil
280}
281
282func (w *walker) Slice(s reflect.Value) error {
283 if w.ignoring() {
284 return nil
285 }
286 w.lock(s)
287
288 var newS reflect.Value
289 if s.IsNil() {
290 newS = reflect.Indirect(reflect.New(s.Type()))
291 } else {
292 newS = reflect.MakeSlice(s.Type(), s.Len(), s.Cap())
293 }
294
295 w.cs = append(w.cs, newS)
296 w.valPush(newS)
297 return nil
298}
299
300func (w *walker) SliceElem(i int, elem reflect.Value) error {
301 if w.ignoring() {
302 return nil
303 }
304
305 // We don't write the slice here because elem might still be
306 // arbitrarily complex. Just record the index and continue on.
307 w.valPush(reflect.ValueOf(i))
308
309 return nil
310}
311
312func (w *walker) Struct(s reflect.Value) error {
313 if w.ignoring() {
314 return nil
315 }
316 w.lock(s)
317
318 var v reflect.Value
319 if c, ok := Copiers[s.Type()]; ok {
320 // We have a Copier for this struct, so we use that copier to
321 // get the copy, and we ignore anything deeper than this.
322 w.ignoreDepth = w.depth
323
324 dup, err := c(s.Interface())
325 if err != nil {
326 return err
327 }
328
329 v = reflect.ValueOf(dup)
330 } else {
331 // No copier, we copy ourselves and allow reflectwalk to guide
332 // us deeper into the structure for copying.
333 v = reflect.New(s.Type())
334 }
335
336 // Push the value onto the value stack for setting the struct field,
337 // and add the struct itself to the containers stack in case we walk
338 // deeper so that its own fields can be modified.
339 w.valPush(v)
340 w.cs = append(w.cs, v)
341
342 return nil
343}
344
345func (w *walker) StructField(f reflect.StructField, v reflect.Value) error {
346 if w.ignoring() {
347 return nil
348 }
349
350 // If PkgPath is non-empty, this is a private (unexported) field.
351 // We do not set this unexported since the Go runtime doesn't allow us.
352 if f.PkgPath != "" {
353 return reflectwalk.SkipEntry
354 }
355
356 // Push the field onto the stack, we'll handle it when we exit
357 // the struct field in Exit...
358 w.valPush(reflect.ValueOf(f))
359 return nil
360}
361
362// ignore causes the walker to ignore any more values until we exit this on
363func (w *walker) ignore() {
364 w.ignoreDepth = w.depth
365}
366
367func (w *walker) ignoring() bool {
368 return w.ignoreDepth > 0 && w.depth >= w.ignoreDepth
369}
370
371func (w *walker) pointerPeek() bool {
372 return w.ps[w.depth] > 0
373}
374
375func (w *walker) valPop() reflect.Value {
376 result := w.vals[len(w.vals)-1]
377 w.vals = w.vals[:len(w.vals)-1]
378
379 // If we're out of values, that means we popped everything off. In
380 // this case, we reset the result so the next pushed value becomes
381 // the result.
382 if len(w.vals) == 0 {
383 w.Result = nil
384 }
385
386 return result
387}
388
389func (w *walker) valPush(v reflect.Value) {
390 w.vals = append(w.vals, v)
391
392 // If we haven't set the result yet, then this is the result since
393 // it is the first (outermost) value we're seeing.
394 if w.Result == nil && v.IsValid() {
395 w.Result = v.Interface()
396 }
397}
398
399func (w *walker) replacePointerMaybe() {
400 // Determine the last pointer value. If it is NOT a pointer, then
401 // we need to push that onto the stack.
402 if !w.pointerPeek() {
403 w.valPush(reflect.Indirect(w.valPop()))
404 return
405 }
406
407 v := w.valPop()
408 for i := 1; i < w.ps[w.depth]; i++ {
409 if iType, ok := w.ifaceTypes[ifaceKey(w.ps[w.depth]-i, w.depth)]; ok {
410 iface := reflect.New(iType).Elem()
411 iface.Set(v)
412 v = iface
413 }
414
415 p := reflect.New(v.Type())
416 p.Elem().Set(v)
417 v = p
418 }
419
420 w.valPush(v)
421}
422
423// if this value is a Locker, lock it and add it to the locks slice
424func (w *walker) lock(v reflect.Value) {
425 if !w.useLocks {
426 return
427 }
428
429 if !v.IsValid() || !v.CanInterface() {
430 return
431 }
432
433 type rlocker interface {
434 RLocker() sync.Locker
435 }
436
437 var locker sync.Locker
438
439 // We can't call Interface() on a value directly, since that requires
440 // a copy. This is OK, since the pointer to a value which is a sync.Locker
441 // is also a sync.Locker.
442 if v.Kind() == reflect.Ptr {
443 switch l := v.Interface().(type) {
444 case rlocker:
445 // don't lock a mutex directly
446 if _, ok := l.(*sync.RWMutex); !ok {
447 locker = l.RLocker()
448 }
449 case sync.Locker:
450 locker = l
451 }
452 } else if v.CanAddr() {
453 switch l := v.Addr().Interface().(type) {
454 case rlocker:
455 // don't lock a mutex directly
456 if _, ok := l.(*sync.RWMutex); !ok {
457 locker = l.RLocker()
458 }
459 case sync.Locker:
460 locker = l
461 }
462 }
463
464 // still no callable locker
465 if locker == nil {
466 return
467 }
468
469 // don't lock a mutex directly
470 switch locker.(type) {
471 case *sync.Mutex, *sync.RWMutex:
472 return
473 }
474
475 locker.Lock()
476 w.locks[w.depth] = locker
477}
diff --git a/vendor/github.com/mitchellh/go-homedir/LICENSE b/vendor/github.com/mitchellh/go-homedir/LICENSE
new file mode 100644
index 0000000..f9c841a
--- /dev/null
+++ b/vendor/github.com/mitchellh/go-homedir/LICENSE
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2013 Mitchell Hashimoto
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
diff --git a/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md
new file mode 100644
index 0000000..d70706d
--- /dev/null
+++ b/vendor/github.com/mitchellh/go-homedir/README.md
@@ -0,0 +1,14 @@
1# go-homedir
2
3This is a Go library for detecting the user's home directory without
4the use of cgo, so the library can be used in cross-compilation environments.
5
6Usage is incredibly simple, just call `homedir.Dir()` to get the home directory
7for a user, and `homedir.Expand()` to expand the `~` in a path to the home
8directory.
9
10**Why not just use `os/user`?** The built-in `os/user` package requires
11cgo on Darwin systems. This means that any Go code that uses that package
12cannot cross compile. But 99% of the time the use for `os/user` is just to
13retrieve the home directory, which we can do for the current user without
14cgo. This library does that, enabling cross-compilation.
diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go
new file mode 100644
index 0000000..47e1f9e
--- /dev/null
+++ b/vendor/github.com/mitchellh/go-homedir/homedir.go
@@ -0,0 +1,137 @@
1package homedir
2
3import (
4 "bytes"
5 "errors"
6 "os"
7 "os/exec"
8 "path/filepath"
9 "runtime"
10 "strconv"
11 "strings"
12 "sync"
13)
14
15// DisableCache will disable caching of the home directory. Caching is enabled
16// by default.
17var DisableCache bool
18
19var homedirCache string
20var cacheLock sync.RWMutex
21
22// Dir returns the home directory for the executing user.
23//
24// This uses an OS-specific method for discovering the home directory.
25// An error is returned if a home directory cannot be detected.
26func Dir() (string, error) {
27 if !DisableCache {
28 cacheLock.RLock()
29 cached := homedirCache
30 cacheLock.RUnlock()
31 if cached != "" {
32 return cached, nil
33 }
34 }
35
36 cacheLock.Lock()
37 defer cacheLock.Unlock()
38
39 var result string
40 var err error
41 if runtime.GOOS == "windows" {
42 result, err = dirWindows()
43 } else {
44 // Unix-like system, so just assume Unix
45 result, err = dirUnix()
46 }
47
48 if err != nil {
49 return "", err
50 }
51 homedirCache = result
52 return result, nil
53}
54
55// Expand expands the path to include the home directory if the path
56// is prefixed with `~`. If it isn't prefixed with `~`, the path is
57// returned as-is.
58func Expand(path string) (string, error) {
59 if len(path) == 0 {
60 return path, nil
61 }
62
63 if path[0] != '~' {
64 return path, nil
65 }
66
67 if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
68 return "", errors.New("cannot expand user-specific home dir")
69 }
70
71 dir, err := Dir()
72 if err != nil {
73 return "", err
74 }
75
76 return filepath.Join(dir, path[1:]), nil
77}
78
79func dirUnix() (string, error) {
80 // First prefer the HOME environmental variable
81 if home := os.Getenv("HOME"); home != "" {
82 return home, nil
83 }
84
85 // If that fails, try getent
86 var stdout bytes.Buffer
87 cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
88 cmd.Stdout = &stdout
89 if err := cmd.Run(); err != nil {
90 // If the error is ErrNotFound, we ignore it. Otherwise, return it.
91 if err != exec.ErrNotFound {
92 return "", err
93 }
94 } else {
95 if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
96 // username:password:uid:gid:gecos:home:shell
97 passwdParts := strings.SplitN(passwd, ":", 7)
98 if len(passwdParts) > 5 {
99 return passwdParts[5], nil
100 }
101 }
102 }
103
104 // If all else fails, try the shell
105 stdout.Reset()
106 cmd = exec.Command("sh", "-c", "cd && pwd")
107 cmd.Stdout = &stdout
108 if err := cmd.Run(); err != nil {
109 return "", err
110 }
111
112 result := strings.TrimSpace(stdout.String())
113 if result == "" {
114 return "", errors.New("blank output when reading home directory")
115 }
116
117 return result, nil
118}
119
120func dirWindows() (string, error) {
121 // First prefer the HOME environmental variable
122 if home := os.Getenv("HOME"); home != "" {
123 return home, nil
124 }
125
126 drive := os.Getenv("HOMEDRIVE")
127 path := os.Getenv("HOMEPATH")
128 home := drive + path
129 if drive == "" || path == "" {
130 home = os.Getenv("USERPROFILE")
131 }
132 if home == "" {
133 return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
134 }
135
136 return home, nil
137}
diff --git a/vendor/github.com/mitchellh/hashstructure/LICENSE b/vendor/github.com/mitchellh/hashstructure/LICENSE
new file mode 100644
index 0000000..a3866a2
--- /dev/null
+++ b/vendor/github.com/mitchellh/hashstructure/LICENSE
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2016 Mitchell Hashimoto
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
diff --git a/vendor/github.com/mitchellh/hashstructure/README.md b/vendor/github.com/mitchellh/hashstructure/README.md
new file mode 100644
index 0000000..7d0de5b
--- /dev/null
+++ b/vendor/github.com/mitchellh/hashstructure/README.md
@@ -0,0 +1,61 @@
1# hashstructure
2
3hashstructure is a Go library for creating a unique hash value
4for arbitrary values in Go.
5
6This can be used to key values in a hash (for use in a map, set, etc.)
7that are complex. The most common use case is comparing two values without
8sending data across the network, caching values locally (de-dup), and so on.
9
10## Features
11
12 * Hash any arbitrary Go value, including complex types.
13
14 * Tag a struct field to ignore it and not affect the hash value.
15
16 * Tag a slice type struct field to treat it as a set where ordering
17 doesn't affect the hash code but the field itself is still taken into
18 account to create the hash value.
19
20 * Optionally specify a custom hash function to optimize for speed, collision
21 avoidance for your data set, etc.
22
23## Installation
24
25Standard `go get`:
26
27```
28$ go get github.com/mitchellh/hashstructure
29```
30
31## Usage & Example
32
33For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/hashstructure).
34
35A quick code example is shown below:
36
37
38 type ComplexStruct struct {
39 Name string
40 Age uint
41 Metadata map[string]interface{}
42 }
43
44 v := ComplexStruct{
45 Name: "mitchellh",
46 Age: 64,
47 Metadata: map[string]interface{}{
48 "car": true,
49 "location": "California",
50 "siblings": []string{"Bob", "John"},
51 },
52 }
53
54 hash, err := hashstructure.Hash(v, nil)
55 if err != nil {
56 panic(err)
57 }
58
59 fmt.Printf("%d", hash)
60 // Output:
61 // 2307517237273902113
diff --git a/vendor/github.com/mitchellh/hashstructure/hashstructure.go b/vendor/github.com/mitchellh/hashstructure/hashstructure.go
new file mode 100644
index 0000000..6f586fa
--- /dev/null
+++ b/vendor/github.com/mitchellh/hashstructure/hashstructure.go
@@ -0,0 +1,323 @@
1package hashstructure
2
3import (
4 "encoding/binary"
5 "fmt"
6 "hash"
7 "hash/fnv"
8 "reflect"
9)
10
11// HashOptions are options that are available for hashing.
12type HashOptions struct {
13 // Hasher is the hash function to use. If this isn't set, it will
14 // default to FNV.
15 Hasher hash.Hash64
16
17 // TagName is the struct tag to look at when hashing the structure.
18 // By default this is "hash".
19 TagName string
20}
21
22// Hash returns the hash value of an arbitrary value.
23//
24// If opts is nil, then default options will be used. See HashOptions
25// for the default values.
26//
27// Notes on the value:
28//
29// * Unexported fields on structs are ignored and do not affect the
30// hash value.
31//
32// * Adding an exported field to a struct with the zero value will change
33// the hash value.
34//
35// For structs, the hashing can be controlled using tags. For example:
36//
37// struct {
38// Name string
39// UUID string `hash:"ignore"`
40// }
41//
42// The available tag values are:
43//
44// * "ignore" - The field will be ignored and not affect the hash code.
45//
46// * "set" - The field will be treated as a set, where ordering doesn't
47// affect the hash code. This only works for slices.
48//
49func Hash(v interface{}, opts *HashOptions) (uint64, error) {
50 // Create default options
51 if opts == nil {
52 opts = &HashOptions{}
53 }
54 if opts.Hasher == nil {
55 opts.Hasher = fnv.New64()
56 }
57 if opts.TagName == "" {
58 opts.TagName = "hash"
59 }
60
61 // Reset the hash
62 opts.Hasher.Reset()
63
64 // Create our walker and walk the structure
65 w := &walker{
66 h: opts.Hasher,
67 tag: opts.TagName,
68 }
69 return w.visit(reflect.ValueOf(v), nil)
70}
71
72type walker struct {
73 h hash.Hash64
74 tag string
75}
76
77type visitOpts struct {
78 // Flags are a bitmask of flags to affect behavior of this visit
79 Flags visitFlag
80
81 // Information about the struct containing this field
82 Struct interface{}
83 StructField string
84}
85
86func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
87 // Loop since these can be wrapped in multiple layers of pointers
88 // and interfaces.
89 for {
90 // If we have an interface, dereference it. We have to do this up
91 // here because it might be a nil in there and the check below must
92 // catch that.
93 if v.Kind() == reflect.Interface {
94 v = v.Elem()
95 continue
96 }
97
98 if v.Kind() == reflect.Ptr {
99 v = reflect.Indirect(v)
100 continue
101 }
102
103 break
104 }
105
106 // If it is nil, treat it like a zero.
107 if !v.IsValid() {
108 var tmp int8
109 v = reflect.ValueOf(tmp)
110 }
111
112 // Binary writing can use raw ints, we have to convert to
113 // a sized-int, we'll choose the largest...
114 switch v.Kind() {
115 case reflect.Int:
116 v = reflect.ValueOf(int64(v.Int()))
117 case reflect.Uint:
118 v = reflect.ValueOf(uint64(v.Uint()))
119 case reflect.Bool:
120 var tmp int8
121 if v.Bool() {
122 tmp = 1
123 }
124 v = reflect.ValueOf(tmp)
125 }
126
127 k := v.Kind()
128
129 // We can shortcut numeric values by directly binary writing them
130 if k >= reflect.Int && k <= reflect.Complex64 {
131 // A direct hash calculation
132 w.h.Reset()
133 err := binary.Write(w.h, binary.LittleEndian, v.Interface())
134 return w.h.Sum64(), err
135 }
136
137 switch k {
138 case reflect.Array:
139 var h uint64
140 l := v.Len()
141 for i := 0; i < l; i++ {
142 current, err := w.visit(v.Index(i), nil)
143 if err != nil {
144 return 0, err
145 }
146
147 h = hashUpdateOrdered(w.h, h, current)
148 }
149
150 return h, nil
151
152 case reflect.Map:
153 var includeMap IncludableMap
154 if opts != nil && opts.Struct != nil {
155 if v, ok := opts.Struct.(IncludableMap); ok {
156 includeMap = v
157 }
158 }
159
160 // Build the hash for the map. We do this by XOR-ing all the key
161 // and value hashes. This makes it deterministic despite ordering.
162 var h uint64
163 for _, k := range v.MapKeys() {
164 v := v.MapIndex(k)
165 if includeMap != nil {
166 incl, err := includeMap.HashIncludeMap(
167 opts.StructField, k.Interface(), v.Interface())
168 if err != nil {
169 return 0, err
170 }
171 if !incl {
172 continue
173 }
174 }
175
176 kh, err := w.visit(k, nil)
177 if err != nil {
178 return 0, err
179 }
180 vh, err := w.visit(v, nil)
181 if err != nil {
182 return 0, err
183 }
184
185 fieldHash := hashUpdateOrdered(w.h, kh, vh)
186 h = hashUpdateUnordered(h, fieldHash)
187 }
188
189 return h, nil
190
191 case reflect.Struct:
192 var include Includable
193 parent := v.Interface()
194 if impl, ok := parent.(Includable); ok {
195 include = impl
196 }
197
198 t := v.Type()
199 h, err := w.visit(reflect.ValueOf(t.Name()), nil)
200 if err != nil {
201 return 0, err
202 }
203
204 l := v.NumField()
205 for i := 0; i < l; i++ {
206 if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
207 var f visitFlag
208 fieldType := t.Field(i)
209 if fieldType.PkgPath != "" {
210 // Unexported
211 continue
212 }
213
214 tag := fieldType.Tag.Get(w.tag)
215 if tag == "ignore" {
216 // Ignore this field
217 continue
218 }
219
220 // Check if we implement includable and check it
221 if include != nil {
222 incl, err := include.HashInclude(fieldType.Name, v)
223 if err != nil {
224 return 0, err
225 }
226 if !incl {
227 continue
228 }
229 }
230
231 switch tag {
232 case "set":
233 f |= visitFlagSet
234 }
235
236 kh, err := w.visit(reflect.ValueOf(fieldType.Name), nil)
237 if err != nil {
238 return 0, err
239 }
240
241 vh, err := w.visit(v, &visitOpts{
242 Flags: f,
243 Struct: parent,
244 StructField: fieldType.Name,
245 })
246 if err != nil {
247 return 0, err
248 }
249
250 fieldHash := hashUpdateOrdered(w.h, kh, vh)
251 h = hashUpdateUnordered(h, fieldHash)
252 }
253 }
254
255 return h, nil
256
257 case reflect.Slice:
258 // We have two behaviors here. If it isn't a set, then we just
259 // visit all the elements. If it is a set, then we do a deterministic
260 // hash code.
261 var h uint64
262 var set bool
263 if opts != nil {
264 set = (opts.Flags & visitFlagSet) != 0
265 }
266 l := v.Len()
267 for i := 0; i < l; i++ {
268 current, err := w.visit(v.Index(i), nil)
269 if err != nil {
270 return 0, err
271 }
272
273 if set {
274 h = hashUpdateUnordered(h, current)
275 } else {
276 h = hashUpdateOrdered(w.h, h, current)
277 }
278 }
279
280 return h, nil
281
282 case reflect.String:
283 // Directly hash
284 w.h.Reset()
285 _, err := w.h.Write([]byte(v.String()))
286 return w.h.Sum64(), err
287
288 default:
289 return 0, fmt.Errorf("unknown kind to hash: %s", k)
290 }
291
292 return 0, nil
293}
294
295func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 {
296 // For ordered updates, use a real hash function
297 h.Reset()
298
299 // We just panic if the binary writes fail because we are writing
300 // an int64 which should never be fail-able.
301 e1 := binary.Write(h, binary.LittleEndian, a)
302 e2 := binary.Write(h, binary.LittleEndian, b)
303 if e1 != nil {
304 panic(e1)
305 }
306 if e2 != nil {
307 panic(e2)
308 }
309
310 return h.Sum64()
311}
312
313func hashUpdateUnordered(a, b uint64) uint64 {
314 return a ^ b
315}
316
317// visitFlag is used as a bitmask for affecting visit behavior
318type visitFlag uint
319
320const (
321 visitFlagInvalid visitFlag = iota
322 visitFlagSet = iota << 1
323)
diff --git a/vendor/github.com/mitchellh/hashstructure/include.go b/vendor/github.com/mitchellh/hashstructure/include.go
new file mode 100644
index 0000000..b6289c0
--- /dev/null
+++ b/vendor/github.com/mitchellh/hashstructure/include.go
@@ -0,0 +1,15 @@
1package hashstructure
2
3// Includable is an interface that can optionally be implemented by
4// a struct. It will be called for each field in the struct to check whether
5// it should be included in the hash.
6type Includable interface {
7 HashInclude(field string, v interface{}) (bool, error)
8}
9
10// IncludableMap is an interface that can optionally be implemented by
11// a struct. It will be called when a map-type field is found to ask the
12// struct if the map item should be included in the hash.
13type IncludableMap interface {
14 HashIncludeMap(field string, k, v interface{}) (bool, error)
15}
diff --git a/vendor/github.com/mitchellh/mapstructure/LICENSE b/vendor/github.com/mitchellh/mapstructure/LICENSE
new file mode 100644
index 0000000..f9c841a
--- /dev/null
+++ b/vendor/github.com/mitchellh/mapstructure/LICENSE
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2013 Mitchell Hashimoto
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
diff --git a/vendor/github.com/mitchellh/mapstructure/README.md b/vendor/github.com/mitchellh/mapstructure/README.md
new file mode 100644
index 0000000..659d688
--- /dev/null
+++ b/vendor/github.com/mitchellh/mapstructure/README.md
@@ -0,0 +1,46 @@
1# mapstructure
2
3mapstructure is a Go library for decoding generic map values to structures
4and vice versa, while providing helpful error handling.
5
6This library is most useful when decoding values from some data stream (JSON,
7Gob, etc.) where you don't _quite_ know the structure of the underlying data
8until you read a part of it. You can therefore read a `map[string]interface{}`
9and use this library to decode it into the proper underlying native Go
10structure.
11
12## Installation
13
14Standard `go get`:
15
16```
17$ go get github.com/mitchellh/mapstructure
18```
19
20## Usage & Example
21
22For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure).
23
24The `Decode` function has examples associated with it there.
25
26## But Why?!
27
28Go offers fantastic standard libraries for decoding formats such as JSON.
29The standard method is to have a struct pre-created, and populate that struct
30from the bytes of the encoded format. This is great, but the problem is if
31you have configuration or an encoding that changes slightly depending on
32specific fields. For example, consider this JSON:
33
34```json
35{
36 "type": "person",
37 "name": "Mitchell"
38}
39```
40
41Perhaps we can't populate a specific structure without first reading
42the "type" field from the JSON. We could always do two passes over the
43decoding of the JSON (reading the "type" first, and the rest later).
44However, it is much simpler to just decode this into a `map[string]interface{}`
45structure, read the "type" key, then use something like this library
46to decode it into the proper structure.
diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
new file mode 100644
index 0000000..115ae67
--- /dev/null
+++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
@@ -0,0 +1,154 @@
1package mapstructure
2
3import (
4 "errors"
5 "reflect"
6 "strconv"
7 "strings"
8 "time"
9)
10
11// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
12// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
13func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
14 // Create variables here so we can reference them with the reflect pkg
15 var f1 DecodeHookFuncType
16 var f2 DecodeHookFuncKind
17
18 // Fill in the variables into this interface and the rest is done
19 // automatically using the reflect package.
20 potential := []interface{}{f1, f2}
21
22 v := reflect.ValueOf(h)
23 vt := v.Type()
24 for _, raw := range potential {
25 pt := reflect.ValueOf(raw).Type()
26 if vt.ConvertibleTo(pt) {
27 return v.Convert(pt).Interface()
28 }
29 }
30
31 return nil
32}
33
34// DecodeHookExec executes the given decode hook. This should be used
35// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
36// that took reflect.Kind instead of reflect.Type.
37func DecodeHookExec(
38 raw DecodeHookFunc,
39 from reflect.Type, to reflect.Type,
40 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) {
48 case DecodeHookFuncType:
49 return f(from, to, data)
50 case DecodeHookFuncKind:
51 return f(from.Kind(), to.Kind(), data)
52 default:
53 return nil, errors.New("invalid decode hook signature")
54 }
55}
56
57// ComposeDecodeHookFunc creates a single DecodeHookFunc that
58// automatically composes multiple DecodeHookFuncs.
59//
60// The composed funcs are called in order, with the result of the
61// previous transformation.
62func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
63 return func(
64 f reflect.Type,
65 t reflect.Type,
66 data interface{}) (interface{}, error) {
67 var err error
68 for _, f1 := range fs {
69 data, err = DecodeHookExec(f1, f, t, data)
70 if err != nil {
71 return nil, err
72 }
73
74 // Modify the from kind to be correct with the new data
75 f = nil
76 if val := reflect.ValueOf(data); val.IsValid() {
77 f = val.Type()
78 }
79 }
80
81 return data, nil
82 }
83}
84
85// StringToSliceHookFunc returns a DecodeHookFunc that converts
86// string to []string by splitting on the given sep.
87func StringToSliceHookFunc(sep string) DecodeHookFunc {
88 return func(
89 f reflect.Kind,
90 t reflect.Kind,
91 data interface{}) (interface{}, error) {
92 if f != reflect.String || t != reflect.Slice {
93 return data, nil
94 }
95
96 raw := data.(string)
97 if raw == "" {
98 return []string{}, nil
99 }
100
101 return strings.Split(raw, sep), nil
102 }
103}
104
105// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
106// strings to time.Duration.
107func StringToTimeDurationHookFunc() DecodeHookFunc {
108 return func(
109 f reflect.Type,
110 t reflect.Type,
111 data interface{}) (interface{}, error) {
112 if f.Kind() != reflect.String {
113 return data, nil
114 }
115 if t != reflect.TypeOf(time.Duration(5)) {
116 return data, nil
117 }
118
119 // Convert it by parsing
120 return time.ParseDuration(data.(string))
121 }
122}
123
124func WeaklyTypedHook(
125 f reflect.Kind,
126 t reflect.Kind,
127 data interface{}) (interface{}, error) {
128 dataVal := reflect.ValueOf(data)
129 switch t {
130 case reflect.String:
131 switch f {
132 case reflect.Bool:
133 if dataVal.Bool() {
134 return "1", nil
135 } else {
136 return "0", nil
137 }
138 case reflect.Float32:
139 return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
140 case reflect.Int:
141 return strconv.FormatInt(dataVal.Int(), 10), nil
142 case reflect.Slice:
143 dataType := dataVal.Type()
144 elemKind := dataType.Elem().Kind()
145 if elemKind == reflect.Uint8 {
146 return string(dataVal.Interface().([]uint8)), nil
147 }
148 case reflect.Uint:
149 return strconv.FormatUint(dataVal.Uint(), 10), nil
150 }
151 }
152
153 return data, nil
154}
diff --git a/vendor/github.com/mitchellh/mapstructure/error.go b/vendor/github.com/mitchellh/mapstructure/error.go
new file mode 100644
index 0000000..47a99e5
--- /dev/null
+++ b/vendor/github.com/mitchellh/mapstructure/error.go
@@ -0,0 +1,50 @@
1package mapstructure
2
3import (
4 "errors"
5 "fmt"
6 "sort"
7 "strings"
8)
9
10// Error implements the error interface and can represents multiple
11// errors that occur in the course of a single decode.
12type Error struct {
13 Errors []string
14}
15
16func (e *Error) Error() string {
17 points := make([]string, len(e.Errors))
18 for i, err := range e.Errors {
19 points[i] = fmt.Sprintf("* %s", err)
20 }
21
22 sort.Strings(points)
23 return fmt.Sprintf(
24 "%d error(s) decoding:\n\n%s",
25 len(e.Errors), strings.Join(points, "\n"))
26}
27
28// WrappedErrors implements the errwrap.Wrapper interface to make this
29// return value more useful with the errwrap and go-multierror libraries.
30func (e *Error) WrappedErrors() []error {
31 if e == nil {
32 return nil
33 }
34
35 result := make([]error, len(e.Errors))
36 for i, e := range e.Errors {
37 result[i] = errors.New(e)
38 }
39
40 return result
41}
42
43func appendErrors(errors []string, err error) []string {
44 switch e := err.(type) {
45 case *Error:
46 return append(errors, e.Errors...)
47 default:
48 return append(errors, e.Error())
49 }
50}
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.
8package mapstructure
9
10import (
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.
33type DecodeHookFunc interface{}
34
35type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error)
36type 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.
40type 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.
97type Decoder struct {
98 config *DecoderConfig
99}
100
101// Metadata contains information about decoding a structure that
102// is tedious or difficult to get otherwise.
103type 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.
114func 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.
130func 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.
148func 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.
182func (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.
187func (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.
253func (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
270func (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
312func (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
354func (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
397func (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
428func (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
470func (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
549func (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
568func (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
581func (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
645func (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
810func 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}
diff --git a/vendor/github.com/mitchellh/reflectwalk/LICENSE b/vendor/github.com/mitchellh/reflectwalk/LICENSE
new file mode 100644
index 0000000..f9c841a
--- /dev/null
+++ b/vendor/github.com/mitchellh/reflectwalk/LICENSE
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2013 Mitchell Hashimoto
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
diff --git a/vendor/github.com/mitchellh/reflectwalk/README.md b/vendor/github.com/mitchellh/reflectwalk/README.md
new file mode 100644
index 0000000..ac82cd2
--- /dev/null
+++ b/vendor/github.com/mitchellh/reflectwalk/README.md
@@ -0,0 +1,6 @@
1# reflectwalk
2
3reflectwalk is a Go library for "walking" a value in Go using reflection,
4in the same way a directory tree can be "walked" on the filesystem. Walking
5a complex structure can allow you to do manipulations on unknown structures
6such as those decoded from JSON.
diff --git a/vendor/github.com/mitchellh/reflectwalk/location.go b/vendor/github.com/mitchellh/reflectwalk/location.go
new file mode 100644
index 0000000..7c59d76
--- /dev/null
+++ b/vendor/github.com/mitchellh/reflectwalk/location.go
@@ -0,0 +1,17 @@
1package reflectwalk
2
3//go:generate stringer -type=Location location.go
4
5type Location uint
6
7const (
8 None Location = iota
9 Map
10 MapKey
11 MapValue
12 Slice
13 SliceElem
14 Struct
15 StructField
16 WalkLoc
17)
diff --git a/vendor/github.com/mitchellh/reflectwalk/location_string.go b/vendor/github.com/mitchellh/reflectwalk/location_string.go
new file mode 100644
index 0000000..d3cfe85
--- /dev/null
+++ b/vendor/github.com/mitchellh/reflectwalk/location_string.go
@@ -0,0 +1,16 @@
1// generated by stringer -type=Location location.go; DO NOT EDIT
2
3package reflectwalk
4
5import "fmt"
6
7const _Location_name = "NoneMapMapKeyMapValueSliceSliceElemStructStructFieldWalkLoc"
8
9var _Location_index = [...]uint8{0, 4, 7, 13, 21, 26, 35, 41, 52, 59}
10
11func (i Location) String() string {
12 if i+1 >= Location(len(_Location_index)) {
13 return fmt.Sprintf("Location(%d)", i)
14 }
15 return _Location_name[_Location_index[i]:_Location_index[i+1]]
16}
diff --git a/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
new file mode 100644
index 0000000..ec0a623
--- /dev/null
+++ b/vendor/github.com/mitchellh/reflectwalk/reflectwalk.go
@@ -0,0 +1,339 @@
1// reflectwalk is a package that allows you to "walk" complex structures
2// similar to how you may "walk" a filesystem: visiting every element one
3// by one and calling callback functions allowing you to handle and manipulate
4// those elements.
5package reflectwalk
6
7import (
8 "errors"
9 "reflect"
10)
11
12// PrimitiveWalker implementations are able to handle primitive values
13// within complex structures. Primitive values are numbers, strings,
14// booleans, funcs, chans.
15//
16// These primitive values are often members of more complex
17// structures (slices, maps, etc.) that are walkable by other interfaces.
18type PrimitiveWalker interface {
19 Primitive(reflect.Value) error
20}
21
22// InterfaceWalker implementations are able to handle interface values as they
23// are encountered during the walk.
24type InterfaceWalker interface {
25 Interface(reflect.Value) error
26}
27
28// MapWalker implementations are able to handle individual elements
29// found within a map structure.
30type MapWalker interface {
31 Map(m reflect.Value) error
32 MapElem(m, k, v reflect.Value) error
33}
34
35// SliceWalker implementations are able to handle slice elements found
36// within complex structures.
37type SliceWalker interface {
38 Slice(reflect.Value) error
39 SliceElem(int, reflect.Value) error
40}
41
42// StructWalker is an interface that has methods that are called for
43// structs when a Walk is done.
44type StructWalker interface {
45 Struct(reflect.Value) error
46 StructField(reflect.StructField, reflect.Value) error
47}
48
49// EnterExitWalker implementations are notified before and after
50// they walk deeper into complex structures (into struct fields,
51// into slice elements, etc.)
52type EnterExitWalker interface {
53 Enter(Location) error
54 Exit(Location) error
55}
56
57// PointerWalker implementations are notified when the value they're
58// walking is a pointer or not. Pointer is called for _every_ value whether
59// it is a pointer or not.
60type PointerWalker interface {
61 PointerEnter(bool) error
62 PointerExit(bool) error
63}
64
65// SkipEntry can be returned from walk functions to skip walking
66// the value of this field. This is only valid in the following functions:
67//
68// - StructField: skips walking the struct value
69//
70var SkipEntry = errors.New("skip this entry")
71
72// Walk takes an arbitrary value and an interface and traverses the
73// value, calling callbacks on the interface if they are supported.
74// The interface should implement one or more of the walker interfaces
75// in this package, such as PrimitiveWalker, StructWalker, etc.
76func Walk(data, walker interface{}) (err error) {
77 v := reflect.ValueOf(data)
78 ew, ok := walker.(EnterExitWalker)
79 if ok {
80 err = ew.Enter(WalkLoc)
81 }
82
83 if err == nil {
84 err = walk(v, walker)
85 }
86
87 if ok && err == nil {
88 err = ew.Exit(WalkLoc)
89 }
90
91 return
92}
93
94func walk(v reflect.Value, w interface{}) (err error) {
95 // Determine if we're receiving a pointer and if so notify the walker.
96 // The logic here is convoluted but very important (tests will fail if
97 // almost any part is changed). I will try to explain here.
98 //
99 // First, we check if the value is an interface, if so, we really need
100 // to check the interface's VALUE to see whether it is a pointer.
101 //
102 // Check whether the value is then a pointer. If so, then set pointer
103 // to true to notify the user.
104 //
105 // If we still have a pointer or an interface after the indirections, then
106 // we unwrap another level
107 //
108 // At this time, we also set "v" to be the dereferenced value. This is
109 // because once we've unwrapped the pointer we want to use that value.
110 pointer := false
111 pointerV := v
112
113 for {
114 if pointerV.Kind() == reflect.Interface {
115 if iw, ok := w.(InterfaceWalker); ok {
116 if err = iw.Interface(pointerV); err != nil {
117 return
118 }
119 }
120
121 pointerV = pointerV.Elem()
122 }
123
124 if pointerV.Kind() == reflect.Ptr {
125 pointer = true
126 v = reflect.Indirect(pointerV)
127 }
128 if pw, ok := w.(PointerWalker); ok {
129 if err = pw.PointerEnter(pointer); err != nil {
130 return
131 }
132
133 defer func(pointer bool) {
134 if err != nil {
135 return
136 }
137
138 err = pw.PointerExit(pointer)
139 }(pointer)
140 }
141
142 if pointer {
143 pointerV = v
144 }
145 pointer = false
146
147 // If we still have a pointer or interface we have to indirect another level.
148 switch pointerV.Kind() {
149 case reflect.Ptr, reflect.Interface:
150 continue
151 }
152 break
153 }
154
155 // We preserve the original value here because if it is an interface
156 // type, we want to pass that directly into the walkPrimitive, so that
157 // we can set it.
158 originalV := v
159 if v.Kind() == reflect.Interface {
160 v = v.Elem()
161 }
162
163 k := v.Kind()
164 if k >= reflect.Int && k <= reflect.Complex128 {
165 k = reflect.Int
166 }
167
168 switch k {
169 // Primitives
170 case reflect.Bool, reflect.Chan, reflect.Func, reflect.Int, reflect.String, reflect.Invalid:
171 err = walkPrimitive(originalV, w)
172 return
173 case reflect.Map:
174 err = walkMap(v, w)
175 return
176 case reflect.Slice:
177 err = walkSlice(v, w)
178 return
179 case reflect.Struct:
180 err = walkStruct(v, w)
181 return
182 default:
183 panic("unsupported type: " + k.String())
184 }
185}
186
187func walkMap(v reflect.Value, w interface{}) error {
188 ew, ewok := w.(EnterExitWalker)
189 if ewok {
190 ew.Enter(Map)
191 }
192
193 if mw, ok := w.(MapWalker); ok {
194 if err := mw.Map(v); err != nil {
195 return err
196 }
197 }
198
199 for _, k := range v.MapKeys() {
200 kv := v.MapIndex(k)
201
202 if mw, ok := w.(MapWalker); ok {
203 if err := mw.MapElem(v, k, kv); err != nil {
204 return err
205 }
206 }
207
208 ew, ok := w.(EnterExitWalker)
209 if ok {
210 ew.Enter(MapKey)
211 }
212
213 if err := walk(k, w); err != nil {
214 return err
215 }
216
217 if ok {
218 ew.Exit(MapKey)
219 ew.Enter(MapValue)
220 }
221
222 if err := walk(kv, w); err != nil {
223 return err
224 }
225
226 if ok {
227 ew.Exit(MapValue)
228 }
229 }
230
231 if ewok {
232 ew.Exit(Map)
233 }
234
235 return nil
236}
237
238func walkPrimitive(v reflect.Value, w interface{}) error {
239 if pw, ok := w.(PrimitiveWalker); ok {
240 return pw.Primitive(v)
241 }
242
243 return nil
244}
245
246func walkSlice(v reflect.Value, w interface{}) (err error) {
247 ew, ok := w.(EnterExitWalker)
248 if ok {
249 ew.Enter(Slice)
250 }
251
252 if sw, ok := w.(SliceWalker); ok {
253 if err := sw.Slice(v); err != nil {
254 return err
255 }
256 }
257
258 for i := 0; i < v.Len(); i++ {
259 elem := v.Index(i)
260
261 if sw, ok := w.(SliceWalker); ok {
262 if err := sw.SliceElem(i, elem); err != nil {
263 return err
264 }
265 }
266
267 ew, ok := w.(EnterExitWalker)
268 if ok {
269 ew.Enter(SliceElem)
270 }
271
272 if err := walk(elem, w); err != nil {
273 return err
274 }
275
276 if ok {
277 ew.Exit(SliceElem)
278 }
279 }
280
281 ew, ok = w.(EnterExitWalker)
282 if ok {
283 ew.Exit(Slice)
284 }
285
286 return nil
287}
288
289func walkStruct(v reflect.Value, w interface{}) (err error) {
290 ew, ewok := w.(EnterExitWalker)
291 if ewok {
292 ew.Enter(Struct)
293 }
294
295 if sw, ok := w.(StructWalker); ok {
296 if err = sw.Struct(v); err != nil {
297 return
298 }
299 }
300
301 vt := v.Type()
302 for i := 0; i < vt.NumField(); i++ {
303 sf := vt.Field(i)
304 f := v.FieldByIndex([]int{i})
305
306 if sw, ok := w.(StructWalker); ok {
307 err = sw.StructField(sf, f)
308
309 // SkipEntry just pretends this field doesn't even exist
310 if err == SkipEntry {
311 continue
312 }
313
314 if err != nil {
315 return
316 }
317 }
318
319 ew, ok := w.(EnterExitWalker)
320 if ok {
321 ew.Enter(StructField)
322 }
323
324 err = walk(f, w)
325 if err != nil {
326 return
327 }
328
329 if ok {
330 ew.Exit(StructField)
331 }
332 }
333
334 if ewok {
335 ew.Exit(Struct)
336 }
337
338 return nil
339}