aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/mitchellh
diff options
context:
space:
mode:
authorNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
committerNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
commit107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch)
treeca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/mitchellh
parent844b5a68d8af4791755b8f0ad293cc99f5959183 (diff)
downloadterraform-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')
-rw-r--r--vendor/github.com/mitchellh/cli/.travis.yml5
-rw-r--r--vendor/github.com/mitchellh/cli/cli.go7
-rw-r--r--vendor/github.com/mitchellh/cli/go.mod12
-rw-r--r--vendor/github.com/mitchellh/cli/go.sum22
-rw-r--r--vendor/github.com/mitchellh/cli/ui_colored.go32
-rw-r--r--vendor/github.com/mitchellh/colorstring/.travis.yml15
-rw-r--r--vendor/github.com/mitchellh/colorstring/LICENSE21
-rw-r--r--vendor/github.com/mitchellh/colorstring/README.md30
-rw-r--r--vendor/github.com/mitchellh/colorstring/colorstring.go244
-rw-r--r--vendor/github.com/mitchellh/colorstring/go.mod1
-rw-r--r--vendor/github.com/mitchellh/copystructure/go.mod3
-rw-r--r--vendor/github.com/mitchellh/copystructure/go.sum2
-rw-r--r--vendor/github.com/mitchellh/go-homedir/go.mod1
-rw-r--r--vendor/github.com/mitchellh/go-homedir/homedir.go56
-rw-r--r--vendor/github.com/mitchellh/go-testing-interface/.travis.yml1
-rw-r--r--vendor/github.com/mitchellh/go-testing-interface/go.mod1
-rw-r--r--vendor/github.com/mitchellh/go-testing-interface/testing_go19.go60
-rw-r--r--vendor/github.com/mitchellh/go-wordwrap/go.mod1
-rw-r--r--vendor/github.com/mitchellh/hashstructure/README.md56
-rw-r--r--vendor/github.com/mitchellh/hashstructure/go.mod1
-rw-r--r--vendor/github.com/mitchellh/hashstructure/hashstructure.go63
-rw-r--r--vendor/github.com/mitchellh/mapstructure/.travis.yml11
-rw-r--r--vendor/github.com/mitchellh/mapstructure/CHANGELOG.md21
-rw-r--r--vendor/github.com/mitchellh/mapstructure/README.md2
-rw-r--r--vendor/github.com/mitchellh/mapstructure/decode_hooks.go79
-rw-r--r--vendor/github.com/mitchellh/mapstructure/go.mod1
-rw-r--r--vendor/github.com/mitchellh/mapstructure/mapstructure.go520
-rw-r--r--vendor/github.com/mitchellh/reflectwalk/go.mod1
28 files changed, 1067 insertions, 202 deletions
diff --git a/vendor/github.com/mitchellh/cli/.travis.yml b/vendor/github.com/mitchellh/cli/.travis.yml
index 974234b..b8599b3 100644
--- a/vendor/github.com/mitchellh/cli/.travis.yml
+++ b/vendor/github.com/mitchellh/cli/.travis.yml
@@ -3,8 +3,9 @@ sudo: false
3language: go 3language: go
4 4
5go: 5go:
6 - 1.8 6 - "1.8"
7 - 1.9 7 - "1.9"
8 - "1.10"
8 9
9branches: 10branches:
10 only: 11 only:
diff --git a/vendor/github.com/mitchellh/cli/cli.go b/vendor/github.com/mitchellh/cli/cli.go
index a25a582..c2dbe55 100644
--- a/vendor/github.com/mitchellh/cli/cli.go
+++ b/vendor/github.com/mitchellh/cli/cli.go
@@ -87,7 +87,7 @@ type CLI struct {
87 // should be set exactly to the binary name that is autocompleted. 87 // should be set exactly to the binary name that is autocompleted.
88 // 88 //
89 // Autocompletion is supported via the github.com/posener/complete 89 // Autocompletion is supported via the github.com/posener/complete
90 // library. This library supports both bash and zsh. To add support 90 // library. This library supports bash, zsh and fish. To add support
91 // for other shells, please see that library. 91 // for other shells, please see that library.
92 // 92 //
93 // AutocompleteInstall and AutocompleteUninstall are the global flag 93 // AutocompleteInstall and AutocompleteUninstall are the global flag
@@ -419,6 +419,11 @@ func (c *CLI) initAutocomplete() {
419func (c *CLI) initAutocompleteSub(prefix string) complete.Command { 419func (c *CLI) initAutocompleteSub(prefix string) complete.Command {
420 var cmd complete.Command 420 var cmd complete.Command
421 walkFn := func(k string, raw interface{}) bool { 421 walkFn := func(k string, raw interface{}) bool {
422 // Ignore the empty key which can be present for default commands.
423 if k == "" {
424 return false
425 }
426
422 // Keep track of the full key so that we can nest further if necessary 427 // Keep track of the full key so that we can nest further if necessary
423 fullKey := k 428 fullKey := k
424 429
diff --git a/vendor/github.com/mitchellh/cli/go.mod b/vendor/github.com/mitchellh/cli/go.mod
new file mode 100644
index 0000000..675325f
--- /dev/null
+++ b/vendor/github.com/mitchellh/cli/go.mod
@@ -0,0 +1,12 @@
1module github.com/mitchellh/cli
2
3require (
4 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310
5 github.com/bgentry/speakeasy v0.1.0
6 github.com/fatih/color v1.7.0
7 github.com/hashicorp/go-multierror v1.0.0 // indirect
8 github.com/mattn/go-colorable v0.0.9 // indirect
9 github.com/mattn/go-isatty v0.0.3
10 github.com/posener/complete v1.1.1
11 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc // indirect
12)
diff --git a/vendor/github.com/mitchellh/cli/go.sum b/vendor/github.com/mitchellh/cli/go.sum
new file mode 100644
index 0000000..0370875
--- /dev/null
+++ b/vendor/github.com/mitchellh/cli/go.sum
@@ -0,0 +1,22 @@
1github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
2github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
3github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
4github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
5github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
6github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
7github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357 h1:Rem2+U35z1QtPQc6r+WolF7yXiefXqDKyk+lN2pE164=
8github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
9github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
10github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
11github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0 h1:j30noezaCfvNLcdMYSvHLv81DxYRSt1grlpseG67vhU=
12github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
13github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
14github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
15github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
16github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
17github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
18github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
19github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
20github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
21golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc h1:MeuS1UDyZyFH++6vVy44PuufTeFF0d0nfI6XB87YGSk=
22golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/vendor/github.com/mitchellh/cli/ui_colored.go b/vendor/github.com/mitchellh/cli/ui_colored.go
index e3d5131..b0ec448 100644
--- a/vendor/github.com/mitchellh/cli/ui_colored.go
+++ b/vendor/github.com/mitchellh/cli/ui_colored.go
@@ -1,7 +1,11 @@
1package cli 1package cli
2 2
3import ( 3import (
4 "fmt" 4 "github.com/fatih/color"
5)
6
7const (
8 noColor = -1
5) 9)
6 10
7// UiColor is a posix shell color code to use. 11// UiColor is a posix shell color code to use.
@@ -12,13 +16,13 @@ type UiColor struct {
12 16
13// A list of colors that are useful. These are all non-bolded by default. 17// A list of colors that are useful. These are all non-bolded by default.
14var ( 18var (
15 UiColorNone UiColor = UiColor{-1, false} 19 UiColorNone UiColor = UiColor{noColor, false}
16 UiColorRed = UiColor{31, false} 20 UiColorRed = UiColor{int(color.FgHiRed), false}
17 UiColorGreen = UiColor{32, false} 21 UiColorGreen = UiColor{int(color.FgHiGreen), false}
18 UiColorYellow = UiColor{33, false} 22 UiColorYellow = UiColor{int(color.FgHiYellow), false}
19 UiColorBlue = UiColor{34, false} 23 UiColorBlue = UiColor{int(color.FgHiBlue), false}
20 UiColorMagenta = UiColor{35, false} 24 UiColorMagenta = UiColor{int(color.FgHiMagenta), false}
21 UiColorCyan = UiColor{36, false} 25 UiColorCyan = UiColor{int(color.FgHiCyan), false}
22) 26)
23 27
24// ColoredUi is a Ui implementation that colors its output according 28// ColoredUi is a Ui implementation that colors its output according
@@ -55,15 +59,15 @@ func (u *ColoredUi) Warn(message string) {
55 u.Ui.Warn(u.colorize(message, u.WarnColor)) 59 u.Ui.Warn(u.colorize(message, u.WarnColor))
56} 60}
57 61
58func (u *ColoredUi) colorize(message string, color UiColor) string { 62func (u *ColoredUi) colorize(message string, uc UiColor) string {
59 if color.Code == -1 { 63 if uc.Code == noColor {
60 return message 64 return message
61 } 65 }
62 66
63 attr := 0 67 attr := []color.Attribute{color.Attribute(uc.Code)}
64 if color.Bold { 68 if uc.Bold {
65 attr = 1 69 attr = append(attr, color.Bold)
66 } 70 }
67 71
68 return fmt.Sprintf("\033[%d;%dm%s\033[0m", attr, color.Code, message) 72 return color.New(attr...).SprintFunc()(message)
69} 73}
diff --git a/vendor/github.com/mitchellh/colorstring/.travis.yml b/vendor/github.com/mitchellh/colorstring/.travis.yml
new file mode 100644
index 0000000..74e286a
--- /dev/null
+++ b/vendor/github.com/mitchellh/colorstring/.travis.yml
@@ -0,0 +1,15 @@
1language: go
2
3go:
4 - 1.0
5 - 1.1
6 - 1.2
7 - 1.3
8 - tip
9
10script:
11 - go test
12
13matrix:
14 allow_failures:
15 - go: tip
diff --git a/vendor/github.com/mitchellh/colorstring/LICENSE b/vendor/github.com/mitchellh/colorstring/LICENSE
new file mode 100644
index 0000000..2298515
--- /dev/null
+++ b/vendor/github.com/mitchellh/colorstring/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/colorstring/README.md b/vendor/github.com/mitchellh/colorstring/README.md
new file mode 100644
index 0000000..0654d45
--- /dev/null
+++ b/vendor/github.com/mitchellh/colorstring/README.md
@@ -0,0 +1,30 @@
1# colorstring [![Build Status](https://travis-ci.org/mitchellh/colorstring.svg)](https://travis-ci.org/mitchellh/colorstring)
2
3colorstring is a [Go](http://www.golang.org) library for outputting colored
4strings to a console using a simple inline syntax in your string to specify
5the color to print as.
6
7For example, the string `[blue]hello [red]world` would output the text
8"hello world" in two colors. The API of colorstring allows for easily disabling
9colors, adding aliases, etc.
10
11## Installation
12
13Standard `go get`:
14
15```
16$ go get github.com/mitchellh/colorstring
17```
18
19## Usage & Example
20
21For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/colorstring).
22
23Usage is easy enough:
24
25```go
26colorstring.Println("[blue]Hello [red]World!")
27```
28
29Additionally, the `Colorize` struct can be used to set options such as
30custom colors, color disabling, etc.
diff --git a/vendor/github.com/mitchellh/colorstring/colorstring.go b/vendor/github.com/mitchellh/colorstring/colorstring.go
new file mode 100644
index 0000000..3de5b24
--- /dev/null
+++ b/vendor/github.com/mitchellh/colorstring/colorstring.go
@@ -0,0 +1,244 @@
1// colorstring provides functions for colorizing strings for terminal
2// output.
3package colorstring
4
5import (
6 "bytes"
7 "fmt"
8 "io"
9 "regexp"
10 "strings"
11)
12
13// Color colorizes your strings using the default settings.
14//
15// Strings given to Color should use the syntax `[color]` to specify the
16// color for text following. For example: `[blue]Hello` will return "Hello"
17// in blue. See DefaultColors for all the supported colors and attributes.
18//
19// If an unrecognized color is given, it is ignored and assumed to be part
20// of the string. For example: `[hi]world` will result in "[hi]world".
21//
22// A color reset is appended to the end of every string. This will reset
23// the color of following strings when you output this text to the same
24// terminal session.
25//
26// If you want to customize any of this behavior, use the Colorize struct.
27func Color(v string) string {
28 return def.Color(v)
29}
30
31// ColorPrefix returns the color sequence that prefixes the given text.
32//
33// This is useful when wrapping text if you want to inherit the color
34// of the wrapped text. For example, "[green]foo" will return "[green]".
35// If there is no color sequence, then this will return "".
36func ColorPrefix(v string) string {
37 return def.ColorPrefix(v)
38}
39
40// Colorize colorizes your strings, giving you the ability to customize
41// some of the colorization process.
42//
43// The options in Colorize can be set to customize colorization. If you're
44// only interested in the defaults, just use the top Color function directly,
45// which creates a default Colorize.
46type Colorize struct {
47 // Colors maps a color string to the code for that color. The code
48 // is a string so that you can use more complex colors to set foreground,
49 // background, attributes, etc. For example, "boldblue" might be
50 // "1;34"
51 Colors map[string]string
52
53 // If true, color attributes will be ignored. This is useful if you're
54 // outputting to a location that doesn't support colors and you just
55 // want the strings returned.
56 Disable bool
57
58 // Reset, if true, will reset the color after each colorization by
59 // adding a reset code at the end.
60 Reset bool
61}
62
63// Color colorizes a string according to the settings setup in the struct.
64//
65// For more details on the syntax, see the top-level Color function.
66func (c *Colorize) Color(v string) string {
67 matches := parseRe.FindAllStringIndex(v, -1)
68 if len(matches) == 0 {
69 return v
70 }
71
72 result := new(bytes.Buffer)
73 colored := false
74 m := []int{0, 0}
75 for _, nm := range matches {
76 // Write the text in between this match and the last
77 result.WriteString(v[m[1]:nm[0]])
78 m = nm
79
80 var replace string
81 if code, ok := c.Colors[v[m[0]+1:m[1]-1]]; ok {
82 colored = true
83
84 if !c.Disable {
85 replace = fmt.Sprintf("\033[%sm", code)
86 }
87 } else {
88 replace = v[m[0]:m[1]]
89 }
90
91 result.WriteString(replace)
92 }
93 result.WriteString(v[m[1]:])
94
95 if colored && c.Reset && !c.Disable {
96 // Write the clear byte at the end
97 result.WriteString("\033[0m")
98 }
99
100 return result.String()
101}
102
103// ColorPrefix returns the first color sequence that exists in this string.
104//
105// For example: "[green]foo" would return "[green]". If no color sequence
106// exists, then "" is returned. This is especially useful when wrapping
107// colored texts to inherit the color of the wrapped text.
108func (c *Colorize) ColorPrefix(v string) string {
109 return prefixRe.FindString(strings.TrimSpace(v))
110}
111
112// DefaultColors are the default colors used when colorizing.
113//
114// If the color is surrounded in underscores, such as "_blue_", then that
115// color will be used for the background color.
116var DefaultColors map[string]string
117
118func init() {
119 DefaultColors = map[string]string{
120 // Default foreground/background colors
121 "default": "39",
122 "_default_": "49",
123
124 // Foreground colors
125 "black": "30",
126 "red": "31",
127 "green": "32",
128 "yellow": "33",
129 "blue": "34",
130 "magenta": "35",
131 "cyan": "36",
132 "light_gray": "37",
133 "dark_gray": "90",
134 "light_red": "91",
135 "light_green": "92",
136 "light_yellow": "93",
137 "light_blue": "94",
138 "light_magenta": "95",
139 "light_cyan": "96",
140 "white": "97",
141
142 // Background colors
143 "_black_": "40",
144 "_red_": "41",
145 "_green_": "42",
146 "_yellow_": "43",
147 "_blue_": "44",
148 "_magenta_": "45",
149 "_cyan_": "46",
150 "_light_gray_": "47",
151 "_dark_gray_": "100",
152 "_light_red_": "101",
153 "_light_green_": "102",
154 "_light_yellow_": "103",
155 "_light_blue_": "104",
156 "_light_magenta_": "105",
157 "_light_cyan_": "106",
158 "_white_": "107",
159
160 // Attributes
161 "bold": "1",
162 "dim": "2",
163 "underline": "4",
164 "blink_slow": "5",
165 "blink_fast": "6",
166 "invert": "7",
167 "hidden": "8",
168
169 // Reset to reset everything to their defaults
170 "reset": "0",
171 "reset_bold": "21",
172 }
173
174 def = Colorize{
175 Colors: DefaultColors,
176 Reset: true,
177 }
178}
179
180var def Colorize
181var parseReRaw = `\[[a-z0-9_-]+\]`
182var parseRe = regexp.MustCompile(`(?i)` + parseReRaw)
183var prefixRe = regexp.MustCompile(`^(?i)(` + parseReRaw + `)+`)
184
185// Print is a convenience wrapper for fmt.Print with support for color codes.
186//
187// Print formats using the default formats for its operands and writes to
188// standard output with support for color codes. Spaces are added between
189// operands when neither is a string. It returns the number of bytes written
190// and any write error encountered.
191func Print(a string) (n int, err error) {
192 return fmt.Print(Color(a))
193}
194
195// Println is a convenience wrapper for fmt.Println with support for color
196// codes.
197//
198// Println formats using the default formats for its operands and writes to
199// standard output with support for color codes. Spaces are always added
200// between operands and a newline is appended. It returns the number of bytes
201// written and any write error encountered.
202func Println(a string) (n int, err error) {
203 return fmt.Println(Color(a))
204}
205
206// Printf is a convenience wrapper for fmt.Printf with support for color codes.
207//
208// Printf formats according to a format specifier and writes to standard output
209// with support for color codes. It returns the number of bytes written and any
210// write error encountered.
211func Printf(format string, a ...interface{}) (n int, err error) {
212 return fmt.Printf(Color(format), a...)
213}
214
215// Fprint is a convenience wrapper for fmt.Fprint with support for color codes.
216//
217// Fprint formats using the default formats for its operands and writes to w
218// with support for color codes. Spaces are added between operands when neither
219// is a string. It returns the number of bytes written and any write error
220// encountered.
221func Fprint(w io.Writer, a string) (n int, err error) {
222 return fmt.Fprint(w, Color(a))
223}
224
225// Fprintln is a convenience wrapper for fmt.Fprintln with support for color
226// codes.
227//
228// Fprintln formats using the default formats for its operands and writes to w
229// with support for color codes. Spaces are always added between operands and a
230// newline is appended. It returns the number of bytes written and any write
231// error encountered.
232func Fprintln(w io.Writer, a string) (n int, err error) {
233 return fmt.Fprintln(w, Color(a))
234}
235
236// Fprintf is a convenience wrapper for fmt.Fprintf with support for color
237// codes.
238//
239// Fprintf formats according to a format specifier and writes to w with support
240// for color codes. It returns the number of bytes written and any write error
241// encountered.
242func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
243 return fmt.Fprintf(w, Color(format), a...)
244}
diff --git a/vendor/github.com/mitchellh/colorstring/go.mod b/vendor/github.com/mitchellh/colorstring/go.mod
new file mode 100644
index 0000000..446ff8d
--- /dev/null
+++ b/vendor/github.com/mitchellh/colorstring/go.mod
@@ -0,0 +1 @@
module github.com/mitchellh/colorstring
diff --git a/vendor/github.com/mitchellh/copystructure/go.mod b/vendor/github.com/mitchellh/copystructure/go.mod
new file mode 100644
index 0000000..d018643
--- /dev/null
+++ b/vendor/github.com/mitchellh/copystructure/go.mod
@@ -0,0 +1,3 @@
1module github.com/mitchellh/copystructure
2
3require github.com/mitchellh/reflectwalk v1.0.0
diff --git a/vendor/github.com/mitchellh/copystructure/go.sum b/vendor/github.com/mitchellh/copystructure/go.sum
new file mode 100644
index 0000000..be57245
--- /dev/null
+++ b/vendor/github.com/mitchellh/copystructure/go.sum
@@ -0,0 +1,2 @@
1github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
2github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
diff --git a/vendor/github.com/mitchellh/go-homedir/go.mod b/vendor/github.com/mitchellh/go-homedir/go.mod
new file mode 100644
index 0000000..7efa09a
--- /dev/null
+++ b/vendor/github.com/mitchellh/go-homedir/go.mod
@@ -0,0 +1 @@
module github.com/mitchellh/go-homedir
diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go
index 47e1f9e..fb87bef 100644
--- a/vendor/github.com/mitchellh/go-homedir/homedir.go
+++ b/vendor/github.com/mitchellh/go-homedir/homedir.go
@@ -77,33 +77,51 @@ func Expand(path string) (string, error) {
77} 77}
78 78
79func dirUnix() (string, error) { 79func dirUnix() (string, error) {
80 homeEnv := "HOME"
81 if runtime.GOOS == "plan9" {
82 // On plan9, env vars are lowercase.
83 homeEnv = "home"
84 }
85
80 // First prefer the HOME environmental variable 86 // First prefer the HOME environmental variable
81 if home := os.Getenv("HOME"); home != "" { 87 if home := os.Getenv(homeEnv); home != "" {
82 return home, nil 88 return home, nil
83 } 89 }
84 90
85 // If that fails, try getent
86 var stdout bytes.Buffer 91 var stdout bytes.Buffer
87 cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) 92
88 cmd.Stdout = &stdout 93 // If that fails, try OS specific commands
89 if err := cmd.Run(); err != nil { 94 if runtime.GOOS == "darwin" {
90 // If the error is ErrNotFound, we ignore it. Otherwise, return it. 95 cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`)
91 if err != exec.ErrNotFound { 96 cmd.Stdout = &stdout
92 return "", err 97 if err := cmd.Run(); err == nil {
98 result := strings.TrimSpace(stdout.String())
99 if result != "" {
100 return result, nil
101 }
93 } 102 }
94 } else { 103 } else {
95 if passwd := strings.TrimSpace(stdout.String()); passwd != "" { 104 cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
96 // username:password:uid:gid:gecos:home:shell 105 cmd.Stdout = &stdout
97 passwdParts := strings.SplitN(passwd, ":", 7) 106 if err := cmd.Run(); err != nil {
98 if len(passwdParts) > 5 { 107 // If the error is ErrNotFound, we ignore it. Otherwise, return it.
99 return passwdParts[5], nil 108 if err != exec.ErrNotFound {
109 return "", err
110 }
111 } else {
112 if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
113 // username:password:uid:gid:gecos:home:shell
114 passwdParts := strings.SplitN(passwd, ":", 7)
115 if len(passwdParts) > 5 {
116 return passwdParts[5], nil
117 }
100 } 118 }
101 } 119 }
102 } 120 }
103 121
104 // If all else fails, try the shell 122 // If all else fails, try the shell
105 stdout.Reset() 123 stdout.Reset()
106 cmd = exec.Command("sh", "-c", "cd && pwd") 124 cmd := exec.Command("sh", "-c", "cd && pwd")
107 cmd.Stdout = &stdout 125 cmd.Stdout = &stdout
108 if err := cmd.Run(); err != nil { 126 if err := cmd.Run(); err != nil {
109 return "", err 127 return "", err
@@ -123,14 +141,16 @@ func dirWindows() (string, error) {
123 return home, nil 141 return home, nil
124 } 142 }
125 143
144 // Prefer standard environment variable USERPROFILE
145 if home := os.Getenv("USERPROFILE"); home != "" {
146 return home, nil
147 }
148
126 drive := os.Getenv("HOMEDRIVE") 149 drive := os.Getenv("HOMEDRIVE")
127 path := os.Getenv("HOMEPATH") 150 path := os.Getenv("HOMEPATH")
128 home := drive + path 151 home := drive + path
129 if drive == "" || path == "" { 152 if drive == "" || path == "" {
130 home = os.Getenv("USERPROFILE") 153 return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank")
131 }
132 if home == "" {
133 return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
134 } 154 }
135 155
136 return home, nil 156 return home, nil
diff --git a/vendor/github.com/mitchellh/go-testing-interface/.travis.yml b/vendor/github.com/mitchellh/go-testing-interface/.travis.yml
index 4c83109..928d000 100644
--- a/vendor/github.com/mitchellh/go-testing-interface/.travis.yml
+++ b/vendor/github.com/mitchellh/go-testing-interface/.travis.yml
@@ -2,6 +2,7 @@ language: go
2 2
3go: 3go:
4 - 1.8 4 - 1.8
5 - 1.x
5 - tip 6 - tip
6 7
7script: 8script:
diff --git a/vendor/github.com/mitchellh/go-testing-interface/go.mod b/vendor/github.com/mitchellh/go-testing-interface/go.mod
new file mode 100644
index 0000000..062796d
--- /dev/null
+++ b/vendor/github.com/mitchellh/go-testing-interface/go.mod
@@ -0,0 +1 @@
module github.com/mitchellh/go-testing-interface
diff --git a/vendor/github.com/mitchellh/go-testing-interface/testing_go19.go b/vendor/github.com/mitchellh/go-testing-interface/testing_go19.go
index 07fbcb5..31b42ca 100644
--- a/vendor/github.com/mitchellh/go-testing-interface/testing_go19.go
+++ b/vendor/github.com/mitchellh/go-testing-interface/testing_go19.go
@@ -19,14 +19,19 @@ import (
19type T interface { 19type T interface {
20 Error(args ...interface{}) 20 Error(args ...interface{})
21 Errorf(format string, args ...interface{}) 21 Errorf(format string, args ...interface{})
22 Fatal(args ...interface{})
23 Fatalf(format string, args ...interface{})
24 Fail() 22 Fail()
25 FailNow() 23 FailNow()
26 Failed() bool 24 Failed() bool
27 Helper() 25 Fatal(args ...interface{})
26 Fatalf(format string, args ...interface{})
28 Log(args ...interface{}) 27 Log(args ...interface{})
29 Logf(format string, args ...interface{}) 28 Logf(format string, args ...interface{})
29 Name() string
30 Skip(args ...interface{})
31 SkipNow()
32 Skipf(format string, args ...interface{})
33 Skipped() bool
34 Helper()
30} 35}
31 36
32// RuntimeT implements T and can be instantiated and run at runtime to 37// RuntimeT implements T and can be instantiated and run at runtime to
@@ -34,7 +39,8 @@ type T interface {
34// for calls to Fatal. For calls to Error, you'll have to check the errors 39// for calls to Fatal. For calls to Error, you'll have to check the errors
35// list to determine whether to exit yourself. 40// list to determine whether to exit yourself.
36type RuntimeT struct { 41type RuntimeT struct {
37 failed bool 42 skipped bool
43 failed bool
38} 44}
39 45
40func (t *RuntimeT) Error(args ...interface{}) { 46func (t *RuntimeT) Error(args ...interface{}) {
@@ -43,20 +49,10 @@ func (t *RuntimeT) Error(args ...interface{}) {
43} 49}
44 50
45func (t *RuntimeT) Errorf(format string, args ...interface{}) { 51func (t *RuntimeT) Errorf(format string, args ...interface{}) {
46 log.Println(fmt.Sprintf(format, args...)) 52 log.Printf(format, args...)
47 t.Fail() 53 t.Fail()
48} 54}
49 55
50func (t *RuntimeT) Fatal(args ...interface{}) {
51 log.Println(fmt.Sprintln(args...))
52 t.FailNow()
53}
54
55func (t *RuntimeT) Fatalf(format string, args ...interface{}) {
56 log.Println(fmt.Sprintf(format, args...))
57 t.FailNow()
58}
59
60func (t *RuntimeT) Fail() { 56func (t *RuntimeT) Fail() {
61 t.failed = true 57 t.failed = true
62} 58}
@@ -69,7 +65,15 @@ func (t *RuntimeT) Failed() bool {
69 return t.failed 65 return t.failed
70} 66}
71 67
72func (t *RuntimeT) Helper() {} 68func (t *RuntimeT) Fatal(args ...interface{}) {
69 log.Print(args...)
70 t.FailNow()
71}
72
73func (t *RuntimeT) Fatalf(format string, args ...interface{}) {
74 log.Printf(format, args...)
75 t.FailNow()
76}
73 77
74func (t *RuntimeT) Log(args ...interface{}) { 78func (t *RuntimeT) Log(args ...interface{}) {
75 log.Println(fmt.Sprintln(args...)) 79 log.Println(fmt.Sprintln(args...))
@@ -78,3 +82,27 @@ func (t *RuntimeT) Log(args ...interface{}) {
78func (t *RuntimeT) Logf(format string, args ...interface{}) { 82func (t *RuntimeT) Logf(format string, args ...interface{}) {
79 log.Println(fmt.Sprintf(format, args...)) 83 log.Println(fmt.Sprintf(format, args...))
80} 84}
85
86func (t *RuntimeT) Name() string {
87 return ""
88}
89
90func (t *RuntimeT) Skip(args ...interface{}) {
91 log.Print(args...)
92 t.SkipNow()
93}
94
95func (t *RuntimeT) SkipNow() {
96 t.skipped = true
97}
98
99func (t *RuntimeT) Skipf(format string, args ...interface{}) {
100 log.Printf(format, args...)
101 t.SkipNow()
102}
103
104func (t *RuntimeT) Skipped() bool {
105 return t.skipped
106}
107
108func (t *RuntimeT) Helper() {}
diff --git a/vendor/github.com/mitchellh/go-wordwrap/go.mod b/vendor/github.com/mitchellh/go-wordwrap/go.mod
new file mode 100644
index 0000000..2ae411b
--- /dev/null
+++ b/vendor/github.com/mitchellh/go-wordwrap/go.mod
@@ -0,0 +1 @@
module github.com/mitchellh/go-wordwrap
diff --git a/vendor/github.com/mitchellh/hashstructure/README.md b/vendor/github.com/mitchellh/hashstructure/README.md
index 7d0de5b..28ce45a 100644
--- a/vendor/github.com/mitchellh/hashstructure/README.md
+++ b/vendor/github.com/mitchellh/hashstructure/README.md
@@ -1,4 +1,4 @@
1# hashstructure 1# hashstructure [![GoDoc](https://godoc.org/github.com/mitchellh/hashstructure?status.svg)](https://godoc.org/github.com/mitchellh/hashstructure)
2 2
3hashstructure is a Go library for creating a unique hash value 3hashstructure is a Go library for creating a unique hash value
4for arbitrary values in Go. 4for arbitrary values in Go.
@@ -19,6 +19,9 @@ sending data across the network, caching values locally (de-dup), and so on.
19 19
20 * Optionally specify a custom hash function to optimize for speed, collision 20 * Optionally specify a custom hash function to optimize for speed, collision
21 avoidance for your data set, etc. 21 avoidance for your data set, etc.
22
23 * Optionally hash the output of `.String()` on structs that implement fmt.Stringer,
24 allowing effective hashing of time.Time
22 25
23## Installation 26## Installation
24 27
@@ -34,28 +37,29 @@ For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/has
34 37
35A quick code example is shown below: 38A quick code example is shown below:
36 39
37 40```go
38 type ComplexStruct struct { 41type ComplexStruct struct {
39 Name string 42 Name string
40 Age uint 43 Age uint
41 Metadata map[string]interface{} 44 Metadata map[string]interface{}
42 } 45}
43 46
44 v := ComplexStruct{ 47v := ComplexStruct{
45 Name: "mitchellh", 48 Name: "mitchellh",
46 Age: 64, 49 Age: 64,
47 Metadata: map[string]interface{}{ 50 Metadata: map[string]interface{}{
48 "car": true, 51 "car": true,
49 "location": "California", 52 "location": "California",
50 "siblings": []string{"Bob", "John"}, 53 "siblings": []string{"Bob", "John"},
51 }, 54 },
52 } 55}
53 56
54 hash, err := hashstructure.Hash(v, nil) 57hash, err := hashstructure.Hash(v, nil)
55 if err != nil { 58if err != nil {
56 panic(err) 59 panic(err)
57 } 60}
58 61
59 fmt.Printf("%d", hash) 62fmt.Printf("%d", hash)
60 // Output: 63// Output:
61 // 2307517237273902113 64// 2307517237273902113
65```
diff --git a/vendor/github.com/mitchellh/hashstructure/go.mod b/vendor/github.com/mitchellh/hashstructure/go.mod
new file mode 100644
index 0000000..966582a
--- /dev/null
+++ b/vendor/github.com/mitchellh/hashstructure/go.mod
@@ -0,0 +1 @@
module github.com/mitchellh/hashstructure
diff --git a/vendor/github.com/mitchellh/hashstructure/hashstructure.go b/vendor/github.com/mitchellh/hashstructure/hashstructure.go
index 6f586fa..ea13a15 100644
--- a/vendor/github.com/mitchellh/hashstructure/hashstructure.go
+++ b/vendor/github.com/mitchellh/hashstructure/hashstructure.go
@@ -8,6 +8,16 @@ import (
8 "reflect" 8 "reflect"
9) 9)
10 10
11// ErrNotStringer is returned when there's an error with hash:"string"
12type ErrNotStringer struct {
13 Field string
14}
15
16// Error implements error for ErrNotStringer
17func (ens *ErrNotStringer) Error() string {
18 return fmt.Sprintf("hashstructure: %s has hash:\"string\" set, but does not implement fmt.Stringer", ens.Field)
19}
20
11// HashOptions are options that are available for hashing. 21// HashOptions are options that are available for hashing.
12type HashOptions struct { 22type HashOptions struct {
13 // Hasher is the hash function to use. If this isn't set, it will 23 // Hasher is the hash function to use. If this isn't set, it will
@@ -17,12 +27,18 @@ type HashOptions struct {
17 // TagName is the struct tag to look at when hashing the structure. 27 // TagName is the struct tag to look at when hashing the structure.
18 // By default this is "hash". 28 // By default this is "hash".
19 TagName string 29 TagName string
30
31 // ZeroNil is flag determining if nil pointer should be treated equal
32 // to a zero value of pointed type. By default this is false.
33 ZeroNil bool
20} 34}
21 35
22// Hash returns the hash value of an arbitrary value. 36// Hash returns the hash value of an arbitrary value.
23// 37//
24// If opts is nil, then default options will be used. See HashOptions 38// If opts is nil, then default options will be used. See HashOptions
25// for the default values. 39// for the default values. The same *HashOptions value cannot be used
40// concurrently. None of the values within a *HashOptions struct are
41// safe to read/write while hashing is being done.
26// 42//
27// Notes on the value: 43// Notes on the value:
28// 44//
@@ -41,11 +57,14 @@ type HashOptions struct {
41// 57//
42// The available tag values are: 58// The available tag values are:
43// 59//
44// * "ignore" - The field will be ignored and not affect the hash code. 60// * "ignore" or "-" - The field will be ignored and not affect the hash code.
45// 61//
46// * "set" - The field will be treated as a set, where ordering doesn't 62// * "set" - The field will be treated as a set, where ordering doesn't
47// affect the hash code. This only works for slices. 63// affect the hash code. This only works for slices.
48// 64//
65// * "string" - The field will be hashed as a string, only works when the
66// field implements fmt.Stringer
67//
49func Hash(v interface{}, opts *HashOptions) (uint64, error) { 68func Hash(v interface{}, opts *HashOptions) (uint64, error) {
50 // Create default options 69 // Create default options
51 if opts == nil { 70 if opts == nil {
@@ -63,15 +82,17 @@ func Hash(v interface{}, opts *HashOptions) (uint64, error) {
63 82
64 // Create our walker and walk the structure 83 // Create our walker and walk the structure
65 w := &walker{ 84 w := &walker{
66 h: opts.Hasher, 85 h: opts.Hasher,
67 tag: opts.TagName, 86 tag: opts.TagName,
87 zeronil: opts.ZeroNil,
68 } 88 }
69 return w.visit(reflect.ValueOf(v), nil) 89 return w.visit(reflect.ValueOf(v), nil)
70} 90}
71 91
72type walker struct { 92type walker struct {
73 h hash.Hash64 93 h hash.Hash64
74 tag string 94 tag string
95 zeronil bool
75} 96}
76 97
77type visitOpts struct { 98type visitOpts struct {
@@ -84,6 +105,8 @@ type visitOpts struct {
84} 105}
85 106
86func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { 107func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
108 t := reflect.TypeOf(0)
109
87 // Loop since these can be wrapped in multiple layers of pointers 110 // Loop since these can be wrapped in multiple layers of pointers
88 // and interfaces. 111 // and interfaces.
89 for { 112 for {
@@ -96,6 +119,9 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
96 } 119 }
97 120
98 if v.Kind() == reflect.Ptr { 121 if v.Kind() == reflect.Ptr {
122 if w.zeronil {
123 t = v.Type().Elem()
124 }
99 v = reflect.Indirect(v) 125 v = reflect.Indirect(v)
100 continue 126 continue
101 } 127 }
@@ -105,8 +131,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
105 131
106 // If it is nil, treat it like a zero. 132 // If it is nil, treat it like a zero.
107 if !v.IsValid() { 133 if !v.IsValid() {
108 var tmp int8 134 v = reflect.Zero(t)
109 v = reflect.ValueOf(tmp)
110 } 135 }
111 136
112 // Binary writing can use raw ints, we have to convert to 137 // Binary writing can use raw ints, we have to convert to
@@ -189,8 +214,8 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
189 return h, nil 214 return h, nil
190 215
191 case reflect.Struct: 216 case reflect.Struct:
192 var include Includable
193 parent := v.Interface() 217 parent := v.Interface()
218 var include Includable
194 if impl, ok := parent.(Includable); ok { 219 if impl, ok := parent.(Includable); ok {
195 include = impl 220 include = impl
196 } 221 }
@@ -203,7 +228,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
203 228
204 l := v.NumField() 229 l := v.NumField()
205 for i := 0; i < l; i++ { 230 for i := 0; i < l; i++ {
206 if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" { 231 if innerV := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
207 var f visitFlag 232 var f visitFlag
208 fieldType := t.Field(i) 233 fieldType := t.Field(i)
209 if fieldType.PkgPath != "" { 234 if fieldType.PkgPath != "" {
@@ -212,14 +237,25 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
212 } 237 }
213 238
214 tag := fieldType.Tag.Get(w.tag) 239 tag := fieldType.Tag.Get(w.tag)
215 if tag == "ignore" { 240 if tag == "ignore" || tag == "-" {
216 // Ignore this field 241 // Ignore this field
217 continue 242 continue
218 } 243 }
219 244
245 // if string is set, use the string value
246 if tag == "string" {
247 if impl, ok := innerV.Interface().(fmt.Stringer); ok {
248 innerV = reflect.ValueOf(impl.String())
249 } else {
250 return 0, &ErrNotStringer{
251 Field: v.Type().Field(i).Name,
252 }
253 }
254 }
255
220 // Check if we implement includable and check it 256 // Check if we implement includable and check it
221 if include != nil { 257 if include != nil {
222 incl, err := include.HashInclude(fieldType.Name, v) 258 incl, err := include.HashInclude(fieldType.Name, innerV)
223 if err != nil { 259 if err != nil {
224 return 0, err 260 return 0, err
225 } 261 }
@@ -238,7 +274,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
238 return 0, err 274 return 0, err
239 } 275 }
240 276
241 vh, err := w.visit(v, &visitOpts{ 277 vh, err := w.visit(innerV, &visitOpts{
242 Flags: f, 278 Flags: f,
243 Struct: parent, 279 Struct: parent,
244 StructField: fieldType.Name, 280 StructField: fieldType.Name,
@@ -289,7 +325,6 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
289 return 0, fmt.Errorf("unknown kind to hash: %s", k) 325 return 0, fmt.Errorf("unknown kind to hash: %s", k)
290 } 326 }
291 327
292 return 0, nil
293} 328}
294 329
295func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 { 330func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 {
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 @@
1language: go 1language: go
2
3go:
4 - "1.11.x"
5 - tip
2 6
3go:
4 - 1.4
5
6script: 7script:
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
3mapstructure is a Go library for decoding generic map values to structures 3mapstructure is a Go library for decoding generic map values to structures
4and vice versa, while providing helpful error handling. 4and 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
3import ( 3import (
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
122func 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
146func 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.
166func 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.
124func WeaklyTypedHook( 188func 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.
33type DecodeHookFunc interface{} 33type DecodeHookFunc interface{}
34 34
35// DecodeHookFuncType is a DecodeHookFunc which has complete information about
36// the source and target types.
35type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) 37type 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.
36type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) 41type 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.
114func Decode(m interface{}, rawVal interface{}) error { 119func 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.
152func 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.
169func 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.
182func (d *Decoder) Decode(raw interface{}) error { 221func (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.
187func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { 226func (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.
253func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { 315func (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
270func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { 344func (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
312func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { 396func (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
354func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { 438func (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
397func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { 481func (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
428func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { 512func (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
590func (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
609func (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
663func (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
549func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { 741func (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
879func (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
979func (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 }
diff --git a/vendor/github.com/mitchellh/reflectwalk/go.mod b/vendor/github.com/mitchellh/reflectwalk/go.mod
new file mode 100644
index 0000000..52bb7c4
--- /dev/null
+++ b/vendor/github.com/mitchellh/reflectwalk/go.mod
@@ -0,0 +1 @@
module github.com/mitchellh/reflectwalk