├── .githooks └── pre-commit ├── .github └── workflows │ ├── lint.yaml │ ├── test.yaml │ └── validation.yaml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── command.go ├── command_darwin.go ├── command_darwin_test.go ├── command_linux.go ├── command_linux_test.go ├── command_test.go ├── command_windows.go ├── command_windows_test.go ├── examples ├── standard_streams.go └── working_dir.go ├── go.mod ├── go.sum ├── utils_test.go └── vendor ├── github.com ├── davecgh │ └── go-spew │ │ ├── LICENSE │ │ └── spew │ │ ├── bypass.go │ │ ├── bypasssafe.go │ │ ├── common.go │ │ ├── config.go │ │ ├── doc.go │ │ ├── dump.go │ │ ├── format.go │ │ └── spew.go ├── pmezard │ └── go-difflib │ │ ├── LICENSE │ │ └── difflib │ │ └── difflib.go └── stretchr │ └── testify │ ├── LICENSE │ ├── assert │ ├── assertion_compare.go │ ├── assertion_compare_can_convert.go │ ├── assertion_compare_legacy.go │ ├── assertion_format.go │ ├── assertion_format.go.tmpl │ ├── assertion_forward.go │ ├── assertion_forward.go.tmpl │ ├── assertion_order.go │ ├── assertions.go │ ├── doc.go │ ├── errors.go │ ├── forward_assertions.go │ └── http_assertions.go │ └── require │ ├── doc.go │ ├── forward_requirements.go │ ├── require.go │ ├── require.go.tmpl │ ├── require_forward.go │ ├── require_forward.go.tmpl │ └── requirements.go ├── gopkg.in └── yaml.v3 │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── emitterc.go │ ├── encode.go │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── modules.txt /.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Run gofmt..." 4 | FMT_FILES=`gofmt -l . | grep -v "vendor/"` 5 | if [[ $FMT_FILES != "" ]]; then 6 | echo "Some files aren't formatted, please run 'go fmt ./...' to format your source code before committing" 7 | echo "${FMT_FILES}" 8 | exit 1 9 | fi 10 | 11 | echo "Run go vet..." 12 | vetcount=`go vet ./... 2>&1 | wc -l` 13 | if [ $vetcount -gt 0 ]; then 14 | echo "Some files aren't passing vet heuristics, please run 'go vet ./...' to see the errors it flags and correct your source code before committing" 15 | exit 1 16 | fi -------------------------------------------------------------------------------- /.github/workflows/lint.yaml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - "main" 8 | 9 | jobs: 10 | staticcheck: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-go@v3 15 | - run: go install honnef.co/go/tools/cmd/staticcheck@latest 16 | - run: ~/go/bin/staticcheck -checks all 17 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - "main" 8 | 9 | jobs: 10 | test: 11 | strategy: 12 | matrix: 13 | platform: [ubuntu-latest, macos-latest, windows-latest] 14 | runs-on: ${{ matrix.platform }} 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | - uses: actions/setup-go@v3 19 | with: 20 | go-version: '1.18' 21 | check-latest: true 22 | - run: make test 23 | 24 | coverage: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v3 28 | - name: Test & publish code coverage 29 | uses: paambaati/codeclimate-action@v3.0.0 30 | env: 31 | CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} 32 | with: 33 | coverageCommand: make test-coverage 34 | coverageLocations: ${{github.workspace}}/c.out:gocov 35 | prefix: github.com/commander-cli/cmd 36 | -------------------------------------------------------------------------------- /.github/workflows/validation.yaml: -------------------------------------------------------------------------------- 1 | name: validation 2 | 3 | on: [pull_request] 4 | 5 | permissions: 6 | contents: read 7 | pull-requests: read 8 | 9 | jobs: 10 | commitlint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: wagoid/commitlint-github-action@v5 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Svett Ralchev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: deps lint test test-coverage 3 | 4 | init: git-hooks 5 | 6 | git-hooks: 7 | $(info INFO: Starting build $@) 8 | ln -sf ../../.githooks/pre-commit .git/hooks/pre-commit 9 | 10 | deps: 11 | $(info INFO: Starting build $@) 12 | go mod vendor 13 | 14 | test: 15 | $(info INFO: Starting build $@) 16 | go test `go list ./... | grep -v examples` 17 | 18 | test-coverage: 19 | $(info INFO: Starting build $@) 20 | go test -coverprofile c.out `go list ./... | grep -v examples` 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/commander-cli/cmd/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/commander-cli/cmd/actions/workflows/ci.yml) 2 | [![GoDoc](https://godoc.org/github.com/commander-cli/cmd?status.svg)](https://godoc.org/github.com/commander-cli/cmd) 3 | [![Test Coverage](https://api.codeclimate.com/v1/badges/31911138f62cea099c31/test_coverage)](https://codeclimate.com/github/commander-cli/cmd/test_coverage) 4 | [![Maintainability](https://api.codeclimate.com/v1/badges/af3487439a313d580619/maintainability)](https://codeclimate.com/github/commander-cli/cmd/maintainability) 5 | [![Go Report Card](https://goreportcard.com/badge/github.com/commander-cli/cmd)](https://goreportcard.com/report/github.com/commander-cli/cmd) 6 | 7 | # cmd package 8 | 9 | A simple package to execute shell commands on linux, darwin and windows. 10 | 11 | ## Installation 12 | 13 | Install the latest version with: 14 | 15 | ```bash 16 | $ go get -u github.com/commander-cli/cmd 17 | ``` 18 | 19 | or an exact version: 20 | 21 | ```bash 22 | $ go get -u github.com/commander-cli/cmd@v1.0.0 23 | ``` 24 | 25 | ## Usage 26 | 27 | ```go 28 | c := cmd.NewCommand("echo hello") 29 | 30 | err := c.Execute() 31 | if err != nil { 32 | panic(err.Error()) 33 | } 34 | 35 | fmt.Println(c.Stdout()) 36 | fmt.Println(c.Stderr()) 37 | ``` 38 | 39 | ### Configure the command 40 | 41 | To configure the command an option function can be passed which receives the 42 | command object as an argument passed by reference. 43 | 44 | Default option functions: 45 | 46 | ``` 47 | cmd.WithCustomBaseCommand(*exec.Cmd) 48 | cmd.WithStandardStreams 49 | cmd.WithCustomStdout(...io.Writers) 50 | cmd.WithCustomStderr(...io.Writers) 51 | cmd.WithTimeout(time.Duration) 52 | cmd.WithoutTimeout 53 | cmd.WithWorkingDir(string) 54 | cmd.WithEnvironmentVariables(cmd.EnvVars) 55 | cmd.WithInheritedEnvironment(cmd.EnvVars) 56 | ``` 57 | 58 | See [godocs for details][]. 59 | 60 | #### Example 61 | 62 | ```go 63 | c := cmd.NewCommand("echo hello", cmd.WithStandardStreams) 64 | c.Execute() 65 | ``` 66 | 67 | #### Set custom options 68 | 69 | ```go 70 | setWorkingDir := func (c *Command) { 71 | c.WorkingDir = "/tmp/test" 72 | } 73 | 74 | c := cmd.NewCommand("pwd", setWorkingDir) 75 | c.Execute() 76 | ``` 77 | 78 | ## Contributing 79 | 80 | If you would like to contribute please submit a pull request. 81 | For bug fixes/minor changes a simple pull request will 82 | suffice. If the change is large or you would like to have a feature 83 | discussion before implementation feel free to open an issue. 84 | 85 | If you have a feature request or bug report please open an issue. 86 | 87 | ### Development 88 | 89 | Please fork the project and do your development there. Please use a 90 | meaningful branch name as well as adhere to [commitlint rules][]. 91 | 92 | If you would like the precommit hooks run: 93 | 94 | ``` 95 | make init 96 | ``` 97 | 98 | To run the test suite: 99 | 100 | ``` 101 | make test 102 | ``` 103 | 104 | *Reminder:* The goal of this project is to ensure we abstract the OS specific 105 | command execution as mush as possible. Ensure your change is compatible 106 | with linux, windows and osx. If unable to test on every operating system 107 | (help needed for windows (:) the CI will take care of that for you. 108 | 109 | [commitlint rules]: https://www.conventionalcommits.org/en/v1.0.0/ 110 | [godocs for details]: https://godoc.org/github.com/commander-cli/cmd 111 | 112 | -------------------------------------------------------------------------------- /command.go: -------------------------------------------------------------------------------- 1 | // Package cmd is a simple package 2 | // to execute shell commeand on linux, 3 | // windows, and osx. 4 | package cmd 5 | 6 | import ( 7 | "bytes" 8 | "context" 9 | "fmt" 10 | "io" 11 | "os" 12 | "os/exec" 13 | "syscall" 14 | "time" 15 | ) 16 | 17 | type CommandInterface interface { 18 | AddEnv(string, string) 19 | Stdout() string 20 | Stderr() string 21 | Combined() string 22 | ExitCode() int 23 | Executed() bool 24 | ExecuteContext(context.Context) error 25 | Execute() error 26 | } 27 | 28 | var _ CommandInterface = (*Command)(nil) 29 | 30 | // Command represents a single command which can be executed 31 | type Command struct { 32 | Command string 33 | Env []string 34 | Dir string 35 | Timeout time.Duration 36 | StderrWriter io.Writer 37 | StdoutWriter io.Writer 38 | WorkingDir string 39 | baseCommand *exec.Cmd 40 | executed bool 41 | exitCode int 42 | // stderr and stdout retrieve the output after the command was executed 43 | stderr bytes.Buffer 44 | stdout bytes.Buffer 45 | combined bytes.Buffer 46 | } 47 | 48 | // EnvVars represents a map where the key is the name of the env variable 49 | // and the value is the value of the variable 50 | // 51 | // Example: 52 | // 53 | // env := map[string]string{"ENV": "VALUE"} 54 | type EnvVars map[string]string 55 | 56 | // NewCommand creates a new command 57 | // You can add option with variadic option argument 58 | // Default timeout is set to 30 minutes 59 | // 60 | // Example: 61 | // 62 | // c := cmd.NewCommand("echo hello", function (c *Command) { 63 | // c.WorkingDir = "/tmp" 64 | // }) 65 | // c.Execute() 66 | // 67 | // or you can use existing options functions 68 | // 69 | // c := cmd.NewCommand("echo hello", cmd.WithStandardStreams) 70 | // c.Execute() 71 | func NewCommand(cmd string, options ...func(*Command)) *Command { 72 | c := &Command{ 73 | Command: cmd, 74 | Timeout: 30 * time.Minute, 75 | executed: false, 76 | Env: []string{}, 77 | } 78 | 79 | c.baseCommand = createBaseCommand(c) 80 | c.StdoutWriter = io.MultiWriter(&c.stdout, &c.combined) 81 | c.StderrWriter = io.MultiWriter(&c.stderr, &c.combined) 82 | 83 | for _, o := range options { 84 | o(c) 85 | } 86 | 87 | return c 88 | } 89 | 90 | // WithCustomBaseCommand allows the OS specific generated baseCommand 91 | // to be overridden by an *os/exec.Cmd. 92 | // 93 | // Example: 94 | // 95 | // c := cmd.NewCommand( 96 | // "echo hello", 97 | // cmd.WithCustomBaseCommand(exec.Command("/bin/bash", "-c")), 98 | // ) 99 | // c.Execute() 100 | func WithCustomBaseCommand(baseCommand *exec.Cmd) func(c *Command) { 101 | return func(c *Command) { 102 | baseCommand.Args = append(baseCommand.Args, c.Command) 103 | c.baseCommand = baseCommand 104 | } 105 | } 106 | 107 | // WithStandardStreams is used as an option by the NewCommand constructor function and writes the output streams 108 | // to stderr and stdout of the operating system 109 | // 110 | // Example: 111 | // 112 | // c := cmd.NewCommand("echo hello", cmd.WithStandardStreams) 113 | // c.Execute() 114 | func WithStandardStreams(c *Command) { 115 | c.StdoutWriter = io.MultiWriter(os.Stdout, &c.stdout, &c.combined) 116 | c.StderrWriter = io.MultiWriter(os.Stderr, &c.stderr, &c.combined) 117 | } 118 | 119 | // WithCustomStdout allows to add custom writers to stdout 120 | func WithCustomStdout(writers ...io.Writer) func(c *Command) { 121 | return func(c *Command) { 122 | writers = append(writers, &c.stdout, &c.combined) 123 | c.StdoutWriter = io.MultiWriter(writers...) 124 | } 125 | } 126 | 127 | // WithCustomStderr allows to add custom writers to stderr 128 | func WithCustomStderr(writers ...io.Writer) func(c *Command) { 129 | return func(c *Command) { 130 | writers = append(writers, &c.stderr, &c.combined) 131 | c.StderrWriter = io.MultiWriter(writers...) 132 | } 133 | } 134 | 135 | // WithTimeout sets the timeout of the command 136 | // 137 | // Example: 138 | // 139 | // cmd.NewCommand("sleep 10;", cmd.WithTimeout(500)) 140 | func WithTimeout(t time.Duration) func(c *Command) { 141 | return func(c *Command) { 142 | c.Timeout = t 143 | } 144 | } 145 | 146 | // WithoutTimeout disables the timeout for the command 147 | func WithoutTimeout(c *Command) { 148 | c.Timeout = 0 149 | } 150 | 151 | // WithWorkingDir sets the current working directory 152 | func WithWorkingDir(dir string) func(c *Command) { 153 | return func(c *Command) { 154 | c.WorkingDir = dir 155 | } 156 | } 157 | 158 | // WithInheritedEnvironment uses the env from the current process and 159 | // allow to add more variables. 160 | func WithInheritedEnvironment(env EnvVars) func(c *Command) { 161 | return func(c *Command) { 162 | c.Env = os.Environ() 163 | 164 | // Set custom variables 165 | fn := WithEnvironmentVariables(env) 166 | fn(c) 167 | } 168 | } 169 | 170 | // WithEnvironmentVariables sets environment variables for the executed command 171 | func WithEnvironmentVariables(env EnvVars) func(c *Command) { 172 | return func(c *Command) { 173 | for key, value := range env { 174 | c.AddEnv(key, value) 175 | } 176 | } 177 | } 178 | 179 | // AddEnv adds an environment variable to the command 180 | // If a variable gets passed like ${VAR_NAME} the env variable will be read out by the current shell 181 | func (c *Command) AddEnv(key, value string) { 182 | value = os.ExpandEnv(value) 183 | c.Env = append(c.Env, fmt.Sprintf("%s=%s", key, value)) 184 | } 185 | 186 | // Stdout returns the output to stdout 187 | func (c *Command) Stdout() string { 188 | c.isExecuted("Stdout") 189 | return c.stdout.String() 190 | } 191 | 192 | // Stderr returns the output to stderr 193 | func (c *Command) Stderr() string { 194 | c.isExecuted("Stderr") 195 | return c.stderr.String() 196 | } 197 | 198 | // Combined returns the combined output of stderr and stdout according to their timeline 199 | func (c *Command) Combined() string { 200 | c.isExecuted("Combined") 201 | return c.combined.String() 202 | } 203 | 204 | // ExitCode returns the exit code of the command 205 | func (c *Command) ExitCode() int { 206 | c.isExecuted("ExitCode") 207 | return c.exitCode 208 | } 209 | 210 | // Executed returns if the command was already executed 211 | func (c *Command) Executed() bool { 212 | return c.executed 213 | } 214 | 215 | func (c *Command) isExecuted(property string) { 216 | if !c.executed { 217 | panic("Can not read " + property + " if command was not executed.") 218 | } 219 | } 220 | 221 | // ExecuteContext runs Execute but with Context 222 | func (c *Command) ExecuteContext(ctx context.Context) error { 223 | cmd := c.baseCommand 224 | cmd.Env = c.Env 225 | cmd.Dir = c.Dir 226 | cmd.Stdout = c.StdoutWriter 227 | cmd.Stderr = c.StderrWriter 228 | cmd.Dir = c.WorkingDir 229 | 230 | // Respect legacy timer setting only if timeout was set > 0 231 | // and context does not have a deadline 232 | _, hasDeadline := ctx.Deadline() 233 | if c.Timeout > 0 && !hasDeadline { 234 | subCtx, cancel := context.WithTimeout(ctx, c.Timeout) 235 | defer cancel() 236 | ctx = subCtx 237 | } 238 | 239 | err := cmd.Start() 240 | if err != nil { 241 | return err 242 | } 243 | 244 | done := make(chan error, 1) 245 | go func() { done <- cmd.Wait() }() 246 | c.executed = true 247 | 248 | select { 249 | case <-ctx.Done(): 250 | if err := cmd.Process.Kill(); err != nil { 251 | return fmt.Errorf("timeout occurred and can not kill process with pid %v", cmd.Process.Pid) 252 | } 253 | 254 | err := ctx.Err() 255 | if c.Timeout > 0 && !hasDeadline { 256 | err = fmt.Errorf("command timed out after %v", c.Timeout) 257 | } 258 | return err 259 | case err := <-done: 260 | c.getExitCode(err) 261 | } 262 | 263 | return nil 264 | } 265 | 266 | // Execute executes the command and writes the results into it's own instance 267 | // The results can be received with the Stdout(), Stderr() and ExitCode() methods 268 | func (c *Command) Execute() error { 269 | return c.ExecuteContext(context.Background()) 270 | } 271 | 272 | func (c *Command) getExitCode(err error) { 273 | if exitErr, ok := err.(*exec.ExitError); ok { 274 | if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { 275 | c.exitCode = status.ExitStatus() 276 | } 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /command_darwin.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os/exec" 5 | "syscall" 6 | ) 7 | 8 | func createBaseCommand(c *Command) *exec.Cmd { 9 | cmd := exec.Command("/bin/sh", "-c", c.Command) 10 | return cmd 11 | } 12 | 13 | // WithUser allows the command to be run as a different 14 | // user. 15 | // 16 | // Example: 17 | // 18 | // cred := syscall.Credential{Uid: 1000, Gid: 1000} 19 | // c := NewCommand("echo hello", cred) 20 | // c.Execute() 21 | func WithUser(credential syscall.Credential) func(c *Command) { 22 | return func(c *Command) { 23 | c.baseCommand.SysProcAttr = &syscall.SysProcAttr{ 24 | Credential: &credential, 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /command_darwin_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "syscall" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestCommand_ExecuteStderr(t *testing.T) { 12 | cmd := NewCommand(">&2 echo hello") 13 | err := cmd.Execute() 14 | 15 | assert.Nil(t, err) 16 | assert.Equal(t, "hello\n", cmd.Stderr()) 17 | } 18 | 19 | func TestCommand_WithTimeout(t *testing.T) { 20 | cmd := NewCommand("sleep 0.5;", WithTimeout(5*time.Millisecond)) 21 | 22 | err := cmd.Execute() 23 | 24 | assert.NotNil(t, err) 25 | assert.Equal(t, "command timed out after 5ms", err.Error()) 26 | } 27 | 28 | func TestCommand_WithValidTimeout(t *testing.T) { 29 | cmd := NewCommand("sleep 0.01;", WithTimeout(500*time.Millisecond)) 30 | 31 | err := cmd.Execute() 32 | 33 | assert.Nil(t, err) 34 | } 35 | 36 | // I really don't see the point of mocking this 37 | // as the stdlib does so already. So testing here 38 | // seems redundant. This simple check if we're compliant 39 | // with an api changes 40 | func TestCommand_WithUser(t *testing.T) { 41 | cmd := NewCommand("echo hello", WithUser(syscall.Credential{Uid: 1111})) 42 | err := cmd.Execute() 43 | assert.Equal(t, uint32(1111), cmd.baseCommand.SysProcAttr.Credential.Uid) 44 | assert.Error(t, err) 45 | } 46 | -------------------------------------------------------------------------------- /command_linux.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os/exec" 5 | "syscall" 6 | ) 7 | 8 | func createBaseCommand(c *Command) *exec.Cmd { 9 | cmd := exec.Command("/bin/sh", "-c", c.Command) 10 | return cmd 11 | } 12 | 13 | // WithUser allows the command to be run as a different 14 | // user. 15 | // 16 | // Example: 17 | // 18 | // cred := syscall.Credential{Uid: 1000, Gid: 1000} 19 | // c := NewCommand("echo hello", WithUser(cred)) 20 | // c.Execute() 21 | func WithUser(credential syscall.Credential) func(c *Command) { 22 | return func(c *Command) { 23 | c.baseCommand.SysProcAttr = &syscall.SysProcAttr{ 24 | Credential: &credential, 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /command_linux_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | "syscall" 10 | "testing" 11 | "time" 12 | 13 | "github.com/stretchr/testify/assert" 14 | "github.com/stretchr/testify/require" 15 | ) 16 | 17 | func TestCommand_ExecuteStderr(t *testing.T) { 18 | cmd := NewCommand(">&2 echo hello") 19 | 20 | err := cmd.Execute() 21 | 22 | assert.Nil(t, err) 23 | assert.Equal(t, "hello\n", cmd.Stderr()) 24 | } 25 | 26 | func TestCommand_WithTimeout(t *testing.T) { 27 | cmd := NewCommand("sleep 0.1;", WithTimeout(1*time.Millisecond)) 28 | 29 | err := cmd.Execute() 30 | assert.NotNil(t, err) 31 | // Sadly a process can not be killed every time :( 32 | containsMsg := strings.Contains(err.Error(), "timeout occurred and can not kill process with pid") || strings.Contains(err.Error(), "command timed out after 1ms") 33 | assert.True(t, containsMsg) 34 | } 35 | 36 | func TestCommand_WithValidTimeout(t *testing.T) { 37 | cmd := NewCommand("sleep 0.01;", WithTimeout(500*time.Millisecond)) 38 | 39 | err := cmd.Execute() 40 | 41 | assert.Nil(t, err) 42 | } 43 | 44 | func TestCommand_WithWorkingDir(t *testing.T) { 45 | setWorkingDir := func(c *Command) { 46 | c.WorkingDir = "/tmp" 47 | } 48 | 49 | cmd := NewCommand("pwd", setWorkingDir) 50 | cmd.Execute() 51 | 52 | assert.Equal(t, "/tmp\n", cmd.Stdout()) 53 | } 54 | 55 | func TestCommand_WithStandardStreams(t *testing.T) { 56 | tmpFile, err := os.CreateTemp("/tmp", "stdout_") 57 | require.NoError(t, err) 58 | originalStdout := os.Stdout 59 | os.Stdout = tmpFile 60 | 61 | // Reset os.Stdout to its original value 62 | defer func() { 63 | os.Stdout = originalStdout 64 | }() 65 | 66 | cmd := NewCommand("echo hey", WithStandardStreams) 67 | cmd.Execute() 68 | 69 | r, err := os.ReadFile(tmpFile.Name()) 70 | require.NoError(t, err) 71 | assert.Equal(t, "hey\n", string(r)) 72 | } 73 | 74 | func TestCommand_WithoutTimeout(t *testing.T) { 75 | cmd := NewCommand("sleep 0.001; echo hello", WithoutTimeout) 76 | 77 | err := cmd.Execute() 78 | 79 | assert.Nil(t, err) 80 | assert.Equal(t, "hello\n", cmd.Stdout()) 81 | } 82 | 83 | func TestCommand_WithInvalidDir(t *testing.T) { 84 | cmd := NewCommand("echo hello", WithWorkingDir("/invalid")) 85 | err := cmd.Execute() 86 | assert.NotNil(t, err) 87 | assert.Equal(t, "chdir /invalid: no such file or directory", err.Error()) 88 | } 89 | 90 | func TestWithInheritedEnvironment(t *testing.T) { 91 | os.Setenv("FROM_OS", "is on os") 92 | os.Setenv("OVERWRITE", "is on os but should be overwritten") 93 | defer func() { 94 | os.Unsetenv("FROM_OS") 95 | os.Unsetenv("OVERWRITE") 96 | }() 97 | 98 | c := NewCommand( 99 | "echo $FROM_OS $OVERWRITE", 100 | WithInheritedEnvironment(map[string]string{"OVERWRITE": "overwritten"})) 101 | c.Execute() 102 | 103 | assertEqualWithLineBreak(t, "is on os overwritten", c.Stdout()) 104 | } 105 | 106 | func TestWithCustomStderr(t *testing.T) { 107 | writer := bytes.Buffer{} 108 | c := NewCommand(">&2 echo stderr; sleep 0.01; echo stdout;", WithCustomStderr(&writer)) 109 | c.Execute() 110 | 111 | assertEqualWithLineBreak(t, "stderr", writer.String()) 112 | assertEqualWithLineBreak(t, "stdout", c.Stdout()) 113 | assertEqualWithLineBreak(t, "stderr", c.Stderr()) 114 | assertEqualWithLineBreak(t, "stderr\nstdout", c.Combined()) 115 | } 116 | 117 | func TestWithCustomStdout(t *testing.T) { 118 | writer := bytes.Buffer{} 119 | c := NewCommand(">&2 echo stderr; sleep 0.01; echo stdout;", WithCustomStdout(&writer)) 120 | c.Execute() 121 | 122 | assertEqualWithLineBreak(t, "stdout", writer.String()) 123 | assertEqualWithLineBreak(t, "stdout", c.Stdout()) 124 | assertEqualWithLineBreak(t, "stderr", c.Stderr()) 125 | assertEqualWithLineBreak(t, "stderr\nstdout", c.Combined()) 126 | } 127 | 128 | func TestWithEnvironmentVariables(t *testing.T) { 129 | c := NewCommand("echo $env", WithEnvironmentVariables(map[string]string{"env": "value"})) 130 | c.Execute() 131 | 132 | assertEqualWithLineBreak(t, "value", c.Stdout()) 133 | } 134 | 135 | func TestCommand_WithContext(t *testing.T) { 136 | // ensure legacy timeout is honored 137 | cmd := NewCommand("sleep 3;", WithTimeout(1*time.Second)) 138 | err := cmd.Execute() 139 | assert.NotNil(t, err) 140 | assert.Equal(t, "command timed out after 1s", err.Error()) 141 | 142 | // set context timeout to 2 seconds to ensure 143 | // context takes precedence over timeout 144 | ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 145 | defer cancel() 146 | cmd = NewCommand("sleep 3;", WithTimeout(1*time.Second)) 147 | err = cmd.ExecuteContext(ctx) 148 | assert.NotNil(t, err) 149 | assert.Equal(t, "context deadline exceeded", err.Error()) 150 | } 151 | 152 | func TestCommand_WithCustomBaseCommand(t *testing.T) { 153 | cmd := NewCommand( 154 | "echo $0", 155 | WithCustomBaseCommand(exec.Command("/bin/bash", "-c")), 156 | ) 157 | 158 | err := cmd.Execute() 159 | assert.Nil(t, err) 160 | // on darwin we use /bin/sh by default test if we're using bash 161 | assert.NotEqual(t, "/bin/sh\n", cmd.Stdout()) 162 | assert.Equal(t, "/bin/bash\n", cmd.Stdout()) 163 | } 164 | 165 | func TestCommand_WithUser(t *testing.T) { 166 | cred := syscall.Credential{} 167 | cmd := NewCommand("echo hello", WithUser(cred)) 168 | err := cmd.Execute() 169 | assert.Error(t, err) 170 | } 171 | -------------------------------------------------------------------------------- /command_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "runtime" 8 | "testing" 9 | "time" 10 | 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | func TestCommand_NewCommand(t *testing.T) { 15 | cmd := NewCommand("echo hello") 16 | cmd.Execute() 17 | 18 | assertEqualWithLineBreak(t, "hello", cmd.Combined()) 19 | assertEqualWithLineBreak(t, "hello", cmd.Stdout()) 20 | } 21 | 22 | func TestCommand_Execute(t *testing.T) { 23 | cmd := NewCommand("echo hello") 24 | 25 | err := cmd.Execute() 26 | 27 | assert.Nil(t, err) 28 | assert.True(t, cmd.Executed()) 29 | assertEqualWithLineBreak(t, "hello", cmd.Stdout()) 30 | } 31 | 32 | func TestCommand_ExitCode(t *testing.T) { 33 | cmd := NewCommand("exit 120") 34 | 35 | err := cmd.Execute() 36 | 37 | assert.Nil(t, err) 38 | assert.Equal(t, 120, cmd.ExitCode()) 39 | } 40 | 41 | func TestCommand_WithEnvVariables(t *testing.T) { 42 | envVar := "$TEST" 43 | if runtime.GOOS == "windows" { 44 | envVar = "%TEST%" 45 | } 46 | cmd := NewCommand(fmt.Sprintf("echo %s", envVar)) 47 | cmd.Env = []string{"TEST=hey"} 48 | 49 | _ = cmd.Execute() 50 | 51 | assertEqualWithLineBreak(t, "hey", cmd.Stdout()) 52 | } 53 | 54 | func TestCommand_Executed(t *testing.T) { 55 | defer func() { 56 | r := recover() 57 | if r != nil { 58 | assert.Contains(t, r, "Can not read Stdout if command was not executed") 59 | } 60 | assert.NotNil(t, r) 61 | }() 62 | 63 | c := NewCommand("echo will not be executed") 64 | _ = c.Stdout() 65 | } 66 | 67 | func TestCommand_AddEnv(t *testing.T) { 68 | c := NewCommand("echo test") 69 | c.AddEnv("key", "value") 70 | assert.Equal(t, []string{"key=value"}, c.Env) 71 | } 72 | 73 | func TestCommand_AddEnvWithShellVariable(t *testing.T) { 74 | const TestEnvKey = "COMMANDER_TEST_SOME_KEY" 75 | os.Setenv(TestEnvKey, "test from shell") 76 | defer os.Unsetenv(TestEnvKey) 77 | 78 | c := NewCommand(getCommand()) 79 | c.AddEnv("SOME_KEY", fmt.Sprintf("${%s}", TestEnvKey)) 80 | 81 | err := c.Execute() 82 | 83 | assert.Nil(t, err) 84 | assertEqualWithLineBreak(t, "test from shell", c.Stdout()) 85 | } 86 | 87 | func TestCommand_AddMultipleEnvWithShellVariable(t *testing.T) { 88 | const TestEnvKeyPlanet = "CMD_TEST_PLANET" 89 | const TestEnvKeyName = "CMD_TEST_NAME" 90 | os.Setenv(TestEnvKeyPlanet, "world") 91 | os.Setenv(TestEnvKeyName, "Simon") 92 | defer func() { 93 | os.Unsetenv(TestEnvKeyPlanet) 94 | os.Unsetenv(TestEnvKeyName) 95 | }() 96 | 97 | c := NewCommand(getCommand()) 98 | envValue := fmt.Sprintf("Hello ${%s}, I am ${%s}", TestEnvKeyPlanet, TestEnvKeyName) 99 | c.AddEnv("SOME_KEY", envValue) 100 | 101 | err := c.Execute() 102 | 103 | assert.Nil(t, err) 104 | assertEqualWithLineBreak(t, "Hello world, I am Simon", c.Stdout()) 105 | } 106 | 107 | func getCommand() string { 108 | command := "echo $SOME_KEY" 109 | if runtime.GOOS == "windows" { 110 | command = "echo %SOME_KEY%" 111 | } 112 | return command 113 | } 114 | 115 | func TestCommand_SetOptions(t *testing.T) { 116 | writer := &bytes.Buffer{} 117 | 118 | setWriter := func(c *Command) { 119 | c.StdoutWriter = writer 120 | } 121 | 122 | setTimeout := func(c *Command) { 123 | c.Timeout = 1 * time.Second 124 | } 125 | 126 | c := NewCommand("echo test", setTimeout, setWriter) 127 | err := c.Execute() 128 | 129 | assert.Nil(t, err) 130 | assert.Equal(t, time.Duration(1000000000), c.Timeout) 131 | assertEqualWithLineBreak(t, "test", writer.String()) 132 | } 133 | -------------------------------------------------------------------------------- /command_windows.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os/exec" 5 | "syscall" 6 | ) 7 | 8 | func createBaseCommand(c *Command) *exec.Cmd { 9 | cmd := exec.Command(`C:\windows\system32\cmd.exe`, "/C", c.Command) 10 | return cmd 11 | } 12 | 13 | // WithUser allows the command to be run as a different 14 | // user. 15 | // 16 | // Example: 17 | // 18 | // token := syscall.Token(handle) 19 | // c := NewCommand("echo hello", WithUser(token)) 20 | // c.Execute() 21 | func WithUser(token syscall.Token) func(c *Command) { 22 | return func(c *Command) { 23 | c.baseCommand.SysProcAttr = &syscall.SysProcAttr{ 24 | Token: token, 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /command_windows_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "strings" 5 | "syscall" 6 | "testing" 7 | "time" 8 | "unsafe" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestCommand_ExecuteStderr(t *testing.T) { 14 | cmd := NewCommand("echo hello 1>&2") 15 | 16 | err := cmd.Execute() 17 | 18 | assert.Nil(t, err) 19 | assertEqualWithLineBreak(t, "hello ", cmd.Stderr()) 20 | } 21 | 22 | func TestCommand_WithTimeout(t *testing.T) { 23 | cmd := NewCommand("timeout 0.005;", WithTimeout(5*time.Millisecond)) 24 | err := cmd.Execute() 25 | 26 | assert.NotNil(t, err) 27 | // This is needed because windows sometimes can not kill the process :( 28 | containsMsg := strings.Contains(err.Error(), "timeout occurred and can not kill process with pid") || strings.Contains(err.Error(), "command timed out after 5ms") 29 | assert.True(t, containsMsg) 30 | } 31 | 32 | func TestCommand_WithValidTimeout(t *testing.T) { 33 | cmd := NewCommand("timeout 0.01;", WithTimeout(1000*time.Millisecond)) 34 | 35 | err := cmd.Execute() 36 | 37 | assert.Nil(t, err) 38 | } 39 | 40 | func TestCommand_WithUser(t *testing.T) { 41 | onehundred := 100 42 | token := syscall.Token(uintptr(unsafe.Pointer(&onehundred))) 43 | cmd := NewCommand("echo hello", WithUser(token)) 44 | err := cmd.Execute() 45 | assert.Error(t, err) 46 | } 47 | -------------------------------------------------------------------------------- /examples/standard_streams.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import "github.com/commander-cli/cmd" 4 | 5 | // CreateNewCommandWithStandardStream create new standard stream example 6 | func CreateNewCommandWithStandardStream() { 7 | c := cmd.NewCommand("echo hello; sleep 1; echo another;", cmd.WithStandardStreams) 8 | c.Execute() 9 | } 10 | -------------------------------------------------------------------------------- /examples/working_dir.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import "github.com/commander-cli/cmd" 4 | 5 | // CreateWithWorkingDir sets the current working directory 6 | func CreateWithWorkingDir() { 7 | setWorkingDir := func(c *cmd.Command) { 8 | c.WorkingDir = "/tmp" 9 | } 10 | c := cmd.NewCommand("pwd", cmd.WithStandardStreams, setWorkingDir) 11 | c.Execute() 12 | } 13 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/commander-cli/cmd 2 | 3 | go 1.21 4 | 5 | require github.com/stretchr/testify v1.8.4 6 | 7 | require ( 8 | github.com/davecgh/go-spew v1.1.1 // indirect 9 | github.com/pmezard/go-difflib v1.0.0 // indirect 10 | gopkg.in/yaml.v3 v3.0.1 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 6 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 7 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 8 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 9 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 10 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 11 | -------------------------------------------------------------------------------- /utils_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "runtime" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func assertEqualWithLineBreak(t *testing.T, expected string, actual string) { 11 | if runtime.GOOS == "windows" { 12 | expected = expected + "\r\n" 13 | } else { 14 | expected = expected + "\n" 15 | } 16 | 17 | assert.Equal(t, expected, actual) 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2012-2016 Dave Collins 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypass.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2016 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when the code is not running on Google App Engine, compiled by GopherJS, and 17 | // "-tags safe" is not added to the go build command line. The "disableunsafe" 18 | // tag is deprecated and thus should not be used. 19 | // Go versions prior to 1.4 are disabled because they use a different layout 20 | // for interfaces which make the implementation of unsafeReflectValue more complex. 21 | // +build !js,!appengine,!safe,!disableunsafe,go1.4 22 | 23 | package spew 24 | 25 | import ( 26 | "reflect" 27 | "unsafe" 28 | ) 29 | 30 | const ( 31 | // UnsafeDisabled is a build-time constant which specifies whether or 32 | // not access to the unsafe package is available. 33 | UnsafeDisabled = false 34 | 35 | // ptrSize is the size of a pointer on the current arch. 36 | ptrSize = unsafe.Sizeof((*byte)(nil)) 37 | ) 38 | 39 | type flag uintptr 40 | 41 | var ( 42 | // flagRO indicates whether the value field of a reflect.Value 43 | // is read-only. 44 | flagRO flag 45 | 46 | // flagAddr indicates whether the address of the reflect.Value's 47 | // value may be taken. 48 | flagAddr flag 49 | ) 50 | 51 | // flagKindMask holds the bits that make up the kind 52 | // part of the flags field. In all the supported versions, 53 | // it is in the lower 5 bits. 54 | const flagKindMask = flag(0x1f) 55 | 56 | // Different versions of Go have used different 57 | // bit layouts for the flags type. This table 58 | // records the known combinations. 59 | var okFlags = []struct { 60 | ro, addr flag 61 | }{{ 62 | // From Go 1.4 to 1.5 63 | ro: 1 << 5, 64 | addr: 1 << 7, 65 | }, { 66 | // Up to Go tip. 67 | ro: 1<<5 | 1<<6, 68 | addr: 1 << 8, 69 | }} 70 | 71 | var flagValOffset = func() uintptr { 72 | field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") 73 | if !ok { 74 | panic("reflect.Value has no flag field") 75 | } 76 | return field.Offset 77 | }() 78 | 79 | // flagField returns a pointer to the flag field of a reflect.Value. 80 | func flagField(v *reflect.Value) *flag { 81 | return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) 82 | } 83 | 84 | // unsafeReflectValue converts the passed reflect.Value into a one that bypasses 85 | // the typical safety restrictions preventing access to unaddressable and 86 | // unexported data. It works by digging the raw pointer to the underlying 87 | // value out of the protected value and generating a new unprotected (unsafe) 88 | // reflect.Value to it. 89 | // 90 | // This allows us to check for implementations of the Stringer and error 91 | // interfaces to be used for pretty printing ordinarily unaddressable and 92 | // inaccessible values such as unexported struct fields. 93 | func unsafeReflectValue(v reflect.Value) reflect.Value { 94 | if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { 95 | return v 96 | } 97 | flagFieldPtr := flagField(&v) 98 | *flagFieldPtr &^= flagRO 99 | *flagFieldPtr |= flagAddr 100 | return v 101 | } 102 | 103 | // Sanity checks against future reflect package changes 104 | // to the type or semantics of the Value.flag field. 105 | func init() { 106 | field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") 107 | if !ok { 108 | panic("reflect.Value has no flag field") 109 | } 110 | if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { 111 | panic("reflect.Value flag field has changed kind") 112 | } 113 | type t0 int 114 | var t struct { 115 | A t0 116 | // t0 will have flagEmbedRO set. 117 | t0 118 | // a will have flagStickyRO set 119 | a t0 120 | } 121 | vA := reflect.ValueOf(t).FieldByName("A") 122 | va := reflect.ValueOf(t).FieldByName("a") 123 | vt0 := reflect.ValueOf(t).FieldByName("t0") 124 | 125 | // Infer flagRO from the difference between the flags 126 | // for the (otherwise identical) fields in t. 127 | flagPublic := *flagField(&vA) 128 | flagWithRO := *flagField(&va) | *flagField(&vt0) 129 | flagRO = flagPublic ^ flagWithRO 130 | 131 | // Infer flagAddr from the difference between a value 132 | // taken from a pointer and not. 133 | vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") 134 | flagNoPtr := *flagField(&vA) 135 | flagPtr := *flagField(&vPtrA) 136 | flagAddr = flagNoPtr ^ flagPtr 137 | 138 | // Check that the inferred flags tally with one of the known versions. 139 | for _, f := range okFlags { 140 | if flagRO == f.ro && flagAddr == f.addr { 141 | return 142 | } 143 | } 144 | panic("reflect.Value read-only flag has changed semantics") 145 | } 146 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypasssafe.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2016 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when the code is running on Google App Engine, compiled by GopherJS, or 17 | // "-tags safe" is added to the go build command line. The "disableunsafe" 18 | // tag is deprecated and thus should not be used. 19 | // +build js appengine safe disableunsafe !go1.4 20 | 21 | package spew 22 | 23 | import "reflect" 24 | 25 | const ( 26 | // UnsafeDisabled is a build-time constant which specifies whether or 27 | // not access to the unsafe package is available. 28 | UnsafeDisabled = true 29 | ) 30 | 31 | // unsafeReflectValue typically converts the passed reflect.Value into a one 32 | // that bypasses the typical safety restrictions preventing access to 33 | // unaddressable and unexported data. However, doing this relies on access to 34 | // the unsafe package. This is a stub version which simply returns the passed 35 | // reflect.Value when the unsafe package is not available. 36 | func unsafeReflectValue(v reflect.Value) reflect.Value { 37 | return v 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/common.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2016 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package spew 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | "reflect" 24 | "sort" 25 | "strconv" 26 | ) 27 | 28 | // Some constants in the form of bytes to avoid string overhead. This mirrors 29 | // the technique used in the fmt package. 30 | var ( 31 | panicBytes = []byte("(PANIC=") 32 | plusBytes = []byte("+") 33 | iBytes = []byte("i") 34 | trueBytes = []byte("true") 35 | falseBytes = []byte("false") 36 | interfaceBytes = []byte("(interface {})") 37 | commaNewlineBytes = []byte(",\n") 38 | newlineBytes = []byte("\n") 39 | openBraceBytes = []byte("{") 40 | openBraceNewlineBytes = []byte("{\n") 41 | closeBraceBytes = []byte("}") 42 | asteriskBytes = []byte("*") 43 | colonBytes = []byte(":") 44 | colonSpaceBytes = []byte(": ") 45 | openParenBytes = []byte("(") 46 | closeParenBytes = []byte(")") 47 | spaceBytes = []byte(" ") 48 | pointerChainBytes = []byte("->") 49 | nilAngleBytes = []byte("") 50 | maxNewlineBytes = []byte("\n") 51 | maxShortBytes = []byte("") 52 | circularBytes = []byte("") 53 | circularShortBytes = []byte("") 54 | invalidAngleBytes = []byte("") 55 | openBracketBytes = []byte("[") 56 | closeBracketBytes = []byte("]") 57 | percentBytes = []byte("%") 58 | precisionBytes = []byte(".") 59 | openAngleBytes = []byte("<") 60 | closeAngleBytes = []byte(">") 61 | openMapBytes = []byte("map[") 62 | closeMapBytes = []byte("]") 63 | lenEqualsBytes = []byte("len=") 64 | capEqualsBytes = []byte("cap=") 65 | ) 66 | 67 | // hexDigits is used to map a decimal value to a hex digit. 68 | var hexDigits = "0123456789abcdef" 69 | 70 | // catchPanic handles any panics that might occur during the handleMethods 71 | // calls. 72 | func catchPanic(w io.Writer, v reflect.Value) { 73 | if err := recover(); err != nil { 74 | w.Write(panicBytes) 75 | fmt.Fprintf(w, "%v", err) 76 | w.Write(closeParenBytes) 77 | } 78 | } 79 | 80 | // handleMethods attempts to call the Error and String methods on the underlying 81 | // type the passed reflect.Value represents and outputes the result to Writer w. 82 | // 83 | // It handles panics in any called methods by catching and displaying the error 84 | // as the formatted value. 85 | func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { 86 | // We need an interface to check if the type implements the error or 87 | // Stringer interface. However, the reflect package won't give us an 88 | // interface on certain things like unexported struct fields in order 89 | // to enforce visibility rules. We use unsafe, when it's available, 90 | // to bypass these restrictions since this package does not mutate the 91 | // values. 92 | if !v.CanInterface() { 93 | if UnsafeDisabled { 94 | return false 95 | } 96 | 97 | v = unsafeReflectValue(v) 98 | } 99 | 100 | // Choose whether or not to do error and Stringer interface lookups against 101 | // the base type or a pointer to the base type depending on settings. 102 | // Technically calling one of these methods with a pointer receiver can 103 | // mutate the value, however, types which choose to satisify an error or 104 | // Stringer interface with a pointer receiver should not be mutating their 105 | // state inside these interface methods. 106 | if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { 107 | v = unsafeReflectValue(v) 108 | } 109 | if v.CanAddr() { 110 | v = v.Addr() 111 | } 112 | 113 | // Is it an error or Stringer? 114 | switch iface := v.Interface().(type) { 115 | case error: 116 | defer catchPanic(w, v) 117 | if cs.ContinueOnMethod { 118 | w.Write(openParenBytes) 119 | w.Write([]byte(iface.Error())) 120 | w.Write(closeParenBytes) 121 | w.Write(spaceBytes) 122 | return false 123 | } 124 | 125 | w.Write([]byte(iface.Error())) 126 | return true 127 | 128 | case fmt.Stringer: 129 | defer catchPanic(w, v) 130 | if cs.ContinueOnMethod { 131 | w.Write(openParenBytes) 132 | w.Write([]byte(iface.String())) 133 | w.Write(closeParenBytes) 134 | w.Write(spaceBytes) 135 | return false 136 | } 137 | w.Write([]byte(iface.String())) 138 | return true 139 | } 140 | return false 141 | } 142 | 143 | // printBool outputs a boolean value as true or false to Writer w. 144 | func printBool(w io.Writer, val bool) { 145 | if val { 146 | w.Write(trueBytes) 147 | } else { 148 | w.Write(falseBytes) 149 | } 150 | } 151 | 152 | // printInt outputs a signed integer value to Writer w. 153 | func printInt(w io.Writer, val int64, base int) { 154 | w.Write([]byte(strconv.FormatInt(val, base))) 155 | } 156 | 157 | // printUint outputs an unsigned integer value to Writer w. 158 | func printUint(w io.Writer, val uint64, base int) { 159 | w.Write([]byte(strconv.FormatUint(val, base))) 160 | } 161 | 162 | // printFloat outputs a floating point value using the specified precision, 163 | // which is expected to be 32 or 64bit, to Writer w. 164 | func printFloat(w io.Writer, val float64, precision int) { 165 | w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) 166 | } 167 | 168 | // printComplex outputs a complex value using the specified float precision 169 | // for the real and imaginary parts to Writer w. 170 | func printComplex(w io.Writer, c complex128, floatPrecision int) { 171 | r := real(c) 172 | w.Write(openParenBytes) 173 | w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) 174 | i := imag(c) 175 | if i >= 0 { 176 | w.Write(plusBytes) 177 | } 178 | w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) 179 | w.Write(iBytes) 180 | w.Write(closeParenBytes) 181 | } 182 | 183 | // printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' 184 | // prefix to Writer w. 185 | func printHexPtr(w io.Writer, p uintptr) { 186 | // Null pointer. 187 | num := uint64(p) 188 | if num == 0 { 189 | w.Write(nilAngleBytes) 190 | return 191 | } 192 | 193 | // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix 194 | buf := make([]byte, 18) 195 | 196 | // It's simpler to construct the hex string right to left. 197 | base := uint64(16) 198 | i := len(buf) - 1 199 | for num >= base { 200 | buf[i] = hexDigits[num%base] 201 | num /= base 202 | i-- 203 | } 204 | buf[i] = hexDigits[num] 205 | 206 | // Add '0x' prefix. 207 | i-- 208 | buf[i] = 'x' 209 | i-- 210 | buf[i] = '0' 211 | 212 | // Strip unused leading bytes. 213 | buf = buf[i:] 214 | w.Write(buf) 215 | } 216 | 217 | // valuesSorter implements sort.Interface to allow a slice of reflect.Value 218 | // elements to be sorted. 219 | type valuesSorter struct { 220 | values []reflect.Value 221 | strings []string // either nil or same len and values 222 | cs *ConfigState 223 | } 224 | 225 | // newValuesSorter initializes a valuesSorter instance, which holds a set of 226 | // surrogate keys on which the data should be sorted. It uses flags in 227 | // ConfigState to decide if and how to populate those surrogate keys. 228 | func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { 229 | vs := &valuesSorter{values: values, cs: cs} 230 | if canSortSimply(vs.values[0].Kind()) { 231 | return vs 232 | } 233 | if !cs.DisableMethods { 234 | vs.strings = make([]string, len(values)) 235 | for i := range vs.values { 236 | b := bytes.Buffer{} 237 | if !handleMethods(cs, &b, vs.values[i]) { 238 | vs.strings = nil 239 | break 240 | } 241 | vs.strings[i] = b.String() 242 | } 243 | } 244 | if vs.strings == nil && cs.SpewKeys { 245 | vs.strings = make([]string, len(values)) 246 | for i := range vs.values { 247 | vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) 248 | } 249 | } 250 | return vs 251 | } 252 | 253 | // canSortSimply tests whether a reflect.Kind is a primitive that can be sorted 254 | // directly, or whether it should be considered for sorting by surrogate keys 255 | // (if the ConfigState allows it). 256 | func canSortSimply(kind reflect.Kind) bool { 257 | // This switch parallels valueSortLess, except for the default case. 258 | switch kind { 259 | case reflect.Bool: 260 | return true 261 | case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: 262 | return true 263 | case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: 264 | return true 265 | case reflect.Float32, reflect.Float64: 266 | return true 267 | case reflect.String: 268 | return true 269 | case reflect.Uintptr: 270 | return true 271 | case reflect.Array: 272 | return true 273 | } 274 | return false 275 | } 276 | 277 | // Len returns the number of values in the slice. It is part of the 278 | // sort.Interface implementation. 279 | func (s *valuesSorter) Len() int { 280 | return len(s.values) 281 | } 282 | 283 | // Swap swaps the values at the passed indices. It is part of the 284 | // sort.Interface implementation. 285 | func (s *valuesSorter) Swap(i, j int) { 286 | s.values[i], s.values[j] = s.values[j], s.values[i] 287 | if s.strings != nil { 288 | s.strings[i], s.strings[j] = s.strings[j], s.strings[i] 289 | } 290 | } 291 | 292 | // valueSortLess returns whether the first value should sort before the second 293 | // value. It is used by valueSorter.Less as part of the sort.Interface 294 | // implementation. 295 | func valueSortLess(a, b reflect.Value) bool { 296 | switch a.Kind() { 297 | case reflect.Bool: 298 | return !a.Bool() && b.Bool() 299 | case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: 300 | return a.Int() < b.Int() 301 | case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: 302 | return a.Uint() < b.Uint() 303 | case reflect.Float32, reflect.Float64: 304 | return a.Float() < b.Float() 305 | case reflect.String: 306 | return a.String() < b.String() 307 | case reflect.Uintptr: 308 | return a.Uint() < b.Uint() 309 | case reflect.Array: 310 | // Compare the contents of both arrays. 311 | l := a.Len() 312 | for i := 0; i < l; i++ { 313 | av := a.Index(i) 314 | bv := b.Index(i) 315 | if av.Interface() == bv.Interface() { 316 | continue 317 | } 318 | return valueSortLess(av, bv) 319 | } 320 | } 321 | return a.String() < b.String() 322 | } 323 | 324 | // Less returns whether the value at index i should sort before the 325 | // value at index j. It is part of the sort.Interface implementation. 326 | func (s *valuesSorter) Less(i, j int) bool { 327 | if s.strings == nil { 328 | return valueSortLess(s.values[i], s.values[j]) 329 | } 330 | return s.strings[i] < s.strings[j] 331 | } 332 | 333 | // sortValues is a sort function that handles both native types and any type that 334 | // can be converted to error or Stringer. Other inputs are sorted according to 335 | // their Value.String() value to ensure display stability. 336 | func sortValues(values []reflect.Value, cs *ConfigState) { 337 | if len(values) == 0 { 338 | return 339 | } 340 | sort.Sort(newValuesSorter(values, cs)) 341 | } 342 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2016 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package spew 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "io" 23 | "os" 24 | ) 25 | 26 | // ConfigState houses the configuration options used by spew to format and 27 | // display values. There is a global instance, Config, that is used to control 28 | // all top-level Formatter and Dump functionality. Each ConfigState instance 29 | // provides methods equivalent to the top-level functions. 30 | // 31 | // The zero value for ConfigState provides no indentation. You would typically 32 | // want to set it to a space or a tab. 33 | // 34 | // Alternatively, you can use NewDefaultConfig to get a ConfigState instance 35 | // with default settings. See the documentation of NewDefaultConfig for default 36 | // values. 37 | type ConfigState struct { 38 | // Indent specifies the string to use for each indentation level. The 39 | // global config instance that all top-level functions use set this to a 40 | // single space by default. If you would like more indentation, you might 41 | // set this to a tab with "\t" or perhaps two spaces with " ". 42 | Indent string 43 | 44 | // MaxDepth controls the maximum number of levels to descend into nested 45 | // data structures. The default, 0, means there is no limit. 46 | // 47 | // NOTE: Circular data structures are properly detected, so it is not 48 | // necessary to set this value unless you specifically want to limit deeply 49 | // nested data structures. 50 | MaxDepth int 51 | 52 | // DisableMethods specifies whether or not error and Stringer interfaces are 53 | // invoked for types that implement them. 54 | DisableMethods bool 55 | 56 | // DisablePointerMethods specifies whether or not to check for and invoke 57 | // error and Stringer interfaces on types which only accept a pointer 58 | // receiver when the current type is not a pointer. 59 | // 60 | // NOTE: This might be an unsafe action since calling one of these methods 61 | // with a pointer receiver could technically mutate the value, however, 62 | // in practice, types which choose to satisify an error or Stringer 63 | // interface with a pointer receiver should not be mutating their state 64 | // inside these interface methods. As a result, this option relies on 65 | // access to the unsafe package, so it will not have any effect when 66 | // running in environments without access to the unsafe package such as 67 | // Google App Engine or with the "safe" build tag specified. 68 | DisablePointerMethods bool 69 | 70 | // DisablePointerAddresses specifies whether to disable the printing of 71 | // pointer addresses. This is useful when diffing data structures in tests. 72 | DisablePointerAddresses bool 73 | 74 | // DisableCapacities specifies whether to disable the printing of capacities 75 | // for arrays, slices, maps and channels. This is useful when diffing 76 | // data structures in tests. 77 | DisableCapacities bool 78 | 79 | // ContinueOnMethod specifies whether or not recursion should continue once 80 | // a custom error or Stringer interface is invoked. The default, false, 81 | // means it will print the results of invoking the custom error or Stringer 82 | // interface and return immediately instead of continuing to recurse into 83 | // the internals of the data type. 84 | // 85 | // NOTE: This flag does not have any effect if method invocation is disabled 86 | // via the DisableMethods or DisablePointerMethods options. 87 | ContinueOnMethod bool 88 | 89 | // SortKeys specifies map keys should be sorted before being printed. Use 90 | // this to have a more deterministic, diffable output. Note that only 91 | // native types (bool, int, uint, floats, uintptr and string) and types 92 | // that support the error or Stringer interfaces (if methods are 93 | // enabled) are supported, with other types sorted according to the 94 | // reflect.Value.String() output which guarantees display stability. 95 | SortKeys bool 96 | 97 | // SpewKeys specifies that, as a last resort attempt, map keys should 98 | // be spewed to strings and sorted by those strings. This is only 99 | // considered if SortKeys is true. 100 | SpewKeys bool 101 | } 102 | 103 | // Config is the active configuration of the top-level functions. 104 | // The configuration can be changed by modifying the contents of spew.Config. 105 | var Config = ConfigState{Indent: " "} 106 | 107 | // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were 108 | // passed with a Formatter interface returned by c.NewFormatter. It returns 109 | // the formatted string as a value that satisfies error. See NewFormatter 110 | // for formatting details. 111 | // 112 | // This function is shorthand for the following syntax: 113 | // 114 | // fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) 115 | func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { 116 | return fmt.Errorf(format, c.convertArgs(a)...) 117 | } 118 | 119 | // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were 120 | // passed with a Formatter interface returned by c.NewFormatter. It returns 121 | // the number of bytes written and any write error encountered. See 122 | // NewFormatter for formatting details. 123 | // 124 | // This function is shorthand for the following syntax: 125 | // 126 | // fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) 127 | func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { 128 | return fmt.Fprint(w, c.convertArgs(a)...) 129 | } 130 | 131 | // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were 132 | // passed with a Formatter interface returned by c.NewFormatter. It returns 133 | // the number of bytes written and any write error encountered. See 134 | // NewFormatter for formatting details. 135 | // 136 | // This function is shorthand for the following syntax: 137 | // 138 | // fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) 139 | func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { 140 | return fmt.Fprintf(w, format, c.convertArgs(a)...) 141 | } 142 | 143 | // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it 144 | // passed with a Formatter interface returned by c.NewFormatter. See 145 | // NewFormatter for formatting details. 146 | // 147 | // This function is shorthand for the following syntax: 148 | // 149 | // fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) 150 | func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { 151 | return fmt.Fprintln(w, c.convertArgs(a)...) 152 | } 153 | 154 | // Print is a wrapper for fmt.Print that treats each argument as if it were 155 | // passed with a Formatter interface returned by c.NewFormatter. It returns 156 | // the number of bytes written and any write error encountered. See 157 | // NewFormatter for formatting details. 158 | // 159 | // This function is shorthand for the following syntax: 160 | // 161 | // fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) 162 | func (c *ConfigState) Print(a ...interface{}) (n int, err error) { 163 | return fmt.Print(c.convertArgs(a)...) 164 | } 165 | 166 | // Printf is a wrapper for fmt.Printf that treats each argument as if it were 167 | // passed with a Formatter interface returned by c.NewFormatter. It returns 168 | // the number of bytes written and any write error encountered. See 169 | // NewFormatter for formatting details. 170 | // 171 | // This function is shorthand for the following syntax: 172 | // 173 | // fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) 174 | func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { 175 | return fmt.Printf(format, c.convertArgs(a)...) 176 | } 177 | 178 | // Println is a wrapper for fmt.Println that treats each argument as if it were 179 | // passed with a Formatter interface returned by c.NewFormatter. It returns 180 | // the number of bytes written and any write error encountered. See 181 | // NewFormatter for formatting details. 182 | // 183 | // This function is shorthand for the following syntax: 184 | // 185 | // fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) 186 | func (c *ConfigState) Println(a ...interface{}) (n int, err error) { 187 | return fmt.Println(c.convertArgs(a)...) 188 | } 189 | 190 | // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were 191 | // passed with a Formatter interface returned by c.NewFormatter. It returns 192 | // the resulting string. See NewFormatter for formatting details. 193 | // 194 | // This function is shorthand for the following syntax: 195 | // 196 | // fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) 197 | func (c *ConfigState) Sprint(a ...interface{}) string { 198 | return fmt.Sprint(c.convertArgs(a)...) 199 | } 200 | 201 | // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were 202 | // passed with a Formatter interface returned by c.NewFormatter. It returns 203 | // the resulting string. See NewFormatter for formatting details. 204 | // 205 | // This function is shorthand for the following syntax: 206 | // 207 | // fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) 208 | func (c *ConfigState) Sprintf(format string, a ...interface{}) string { 209 | return fmt.Sprintf(format, c.convertArgs(a)...) 210 | } 211 | 212 | // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it 213 | // were passed with a Formatter interface returned by c.NewFormatter. It 214 | // returns the resulting string. See NewFormatter for formatting details. 215 | // 216 | // This function is shorthand for the following syntax: 217 | // 218 | // fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) 219 | func (c *ConfigState) Sprintln(a ...interface{}) string { 220 | return fmt.Sprintln(c.convertArgs(a)...) 221 | } 222 | 223 | /* 224 | NewFormatter returns a custom formatter that satisfies the fmt.Formatter 225 | interface. As a result, it integrates cleanly with standard fmt package 226 | printing functions. The formatter is useful for inline printing of smaller data 227 | types similar to the standard %v format specifier. 228 | 229 | The custom formatter only responds to the %v (most compact), %+v (adds pointer 230 | addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb 231 | combinations. Any other verbs such as %x and %q will be sent to the the 232 | standard fmt package for formatting. In addition, the custom formatter ignores 233 | the width and precision arguments (however they will still work on the format 234 | specifiers not handled by the custom formatter). 235 | 236 | Typically this function shouldn't be called directly. It is much easier to make 237 | use of the custom formatter by calling one of the convenience functions such as 238 | c.Printf, c.Println, or c.Printf. 239 | */ 240 | func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { 241 | return newFormatter(c, v) 242 | } 243 | 244 | // Fdump formats and displays the passed arguments to io.Writer w. It formats 245 | // exactly the same as Dump. 246 | func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { 247 | fdump(c, w, a...) 248 | } 249 | 250 | /* 251 | Dump displays the passed parameters to standard out with newlines, customizable 252 | indentation, and additional debug information such as complete types and all 253 | pointer addresses used to indirect to the final value. It provides the 254 | following features over the built-in printing facilities provided by the fmt 255 | package: 256 | 257 | * Pointers are dereferenced and followed 258 | * Circular data structures are detected and handled properly 259 | * Custom Stringer/error interfaces are optionally invoked, including 260 | on unexported types 261 | * Custom types which only implement the Stringer/error interfaces via 262 | a pointer receiver are optionally invoked when passing non-pointer 263 | variables 264 | * Byte arrays and slices are dumped like the hexdump -C command which 265 | includes offsets, byte values in hex, and ASCII output 266 | 267 | The configuration options are controlled by modifying the public members 268 | of c. See ConfigState for options documentation. 269 | 270 | See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to 271 | get the formatted result as a string. 272 | */ 273 | func (c *ConfigState) Dump(a ...interface{}) { 274 | fdump(c, os.Stdout, a...) 275 | } 276 | 277 | // Sdump returns a string with the passed arguments formatted exactly the same 278 | // as Dump. 279 | func (c *ConfigState) Sdump(a ...interface{}) string { 280 | var buf bytes.Buffer 281 | fdump(c, &buf, a...) 282 | return buf.String() 283 | } 284 | 285 | // convertArgs accepts a slice of arguments and returns a slice of the same 286 | // length with each argument converted to a spew Formatter interface using 287 | // the ConfigState associated with s. 288 | func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { 289 | formatters = make([]interface{}, len(args)) 290 | for index, arg := range args { 291 | formatters[index] = newFormatter(c, arg) 292 | } 293 | return formatters 294 | } 295 | 296 | // NewDefaultConfig returns a ConfigState with the following default settings. 297 | // 298 | // Indent: " " 299 | // MaxDepth: 0 300 | // DisableMethods: false 301 | // DisablePointerMethods: false 302 | // ContinueOnMethod: false 303 | // SortKeys: false 304 | func NewDefaultConfig() *ConfigState { 305 | return &ConfigState{Indent: " "} 306 | } 307 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2016 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /* 18 | Package spew implements a deep pretty printer for Go data structures to aid in 19 | debugging. 20 | 21 | A quick overview of the additional features spew provides over the built-in 22 | printing facilities for Go data types are as follows: 23 | 24 | * Pointers are dereferenced and followed 25 | * Circular data structures are detected and handled properly 26 | * Custom Stringer/error interfaces are optionally invoked, including 27 | on unexported types 28 | * Custom types which only implement the Stringer/error interfaces via 29 | a pointer receiver are optionally invoked when passing non-pointer 30 | variables 31 | * Byte arrays and slices are dumped like the hexdump -C command which 32 | includes offsets, byte values in hex, and ASCII output (only when using 33 | Dump style) 34 | 35 | There are two different approaches spew allows for dumping Go data structures: 36 | 37 | * Dump style which prints with newlines, customizable indentation, 38 | and additional debug information such as types and all pointer addresses 39 | used to indirect to the final value 40 | * A custom Formatter interface that integrates cleanly with the standard fmt 41 | package and replaces %v, %+v, %#v, and %#+v to provide inline printing 42 | similar to the default %v while providing the additional functionality 43 | outlined above and passing unsupported format verbs such as %x and %q 44 | along to fmt 45 | 46 | Quick Start 47 | 48 | This section demonstrates how to quickly get started with spew. See the 49 | sections below for further details on formatting and configuration options. 50 | 51 | To dump a variable with full newlines, indentation, type, and pointer 52 | information use Dump, Fdump, or Sdump: 53 | spew.Dump(myVar1, myVar2, ...) 54 | spew.Fdump(someWriter, myVar1, myVar2, ...) 55 | str := spew.Sdump(myVar1, myVar2, ...) 56 | 57 | Alternatively, if you would prefer to use format strings with a compacted inline 58 | printing style, use the convenience wrappers Printf, Fprintf, etc with 59 | %v (most compact), %+v (adds pointer addresses), %#v (adds types), or 60 | %#+v (adds types and pointer addresses): 61 | spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) 62 | spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 63 | spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) 64 | spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 65 | 66 | Configuration Options 67 | 68 | Configuration of spew is handled by fields in the ConfigState type. For 69 | convenience, all of the top-level functions use a global state available 70 | via the spew.Config global. 71 | 72 | It is also possible to create a ConfigState instance that provides methods 73 | equivalent to the top-level functions. This allows concurrent configuration 74 | options. See the ConfigState documentation for more details. 75 | 76 | The following configuration options are available: 77 | * Indent 78 | String to use for each indentation level for Dump functions. 79 | It is a single space by default. A popular alternative is "\t". 80 | 81 | * MaxDepth 82 | Maximum number of levels to descend into nested data structures. 83 | There is no limit by default. 84 | 85 | * DisableMethods 86 | Disables invocation of error and Stringer interface methods. 87 | Method invocation is enabled by default. 88 | 89 | * DisablePointerMethods 90 | Disables invocation of error and Stringer interface methods on types 91 | which only accept pointer receivers from non-pointer variables. 92 | Pointer method invocation is enabled by default. 93 | 94 | * DisablePointerAddresses 95 | DisablePointerAddresses specifies whether to disable the printing of 96 | pointer addresses. This is useful when diffing data structures in tests. 97 | 98 | * DisableCapacities 99 | DisableCapacities specifies whether to disable the printing of 100 | capacities for arrays, slices, maps and channels. This is useful when 101 | diffing data structures in tests. 102 | 103 | * ContinueOnMethod 104 | Enables recursion into types after invoking error and Stringer interface 105 | methods. Recursion after method invocation is disabled by default. 106 | 107 | * SortKeys 108 | Specifies map keys should be sorted before being printed. Use 109 | this to have a more deterministic, diffable output. Note that 110 | only native types (bool, int, uint, floats, uintptr and string) 111 | and types which implement error or Stringer interfaces are 112 | supported with other types sorted according to the 113 | reflect.Value.String() output which guarantees display 114 | stability. Natural map order is used by default. 115 | 116 | * SpewKeys 117 | Specifies that, as a last resort attempt, map keys should be 118 | spewed to strings and sorted by those strings. This is only 119 | considered if SortKeys is true. 120 | 121 | Dump Usage 122 | 123 | Simply call spew.Dump with a list of variables you want to dump: 124 | 125 | spew.Dump(myVar1, myVar2, ...) 126 | 127 | You may also call spew.Fdump if you would prefer to output to an arbitrary 128 | io.Writer. For example, to dump to standard error: 129 | 130 | spew.Fdump(os.Stderr, myVar1, myVar2, ...) 131 | 132 | A third option is to call spew.Sdump to get the formatted output as a string: 133 | 134 | str := spew.Sdump(myVar1, myVar2, ...) 135 | 136 | Sample Dump Output 137 | 138 | See the Dump example for details on the setup of the types and variables being 139 | shown here. 140 | 141 | (main.Foo) { 142 | unexportedField: (*main.Bar)(0xf84002e210)({ 143 | flag: (main.Flag) flagTwo, 144 | data: (uintptr) 145 | }), 146 | ExportedField: (map[interface {}]interface {}) (len=1) { 147 | (string) (len=3) "one": (bool) true 148 | } 149 | } 150 | 151 | Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C 152 | command as shown. 153 | ([]uint8) (len=32 cap=32) { 154 | 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | 155 | 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| 156 | 00000020 31 32 |12| 157 | } 158 | 159 | Custom Formatter 160 | 161 | Spew provides a custom formatter that implements the fmt.Formatter interface 162 | so that it integrates cleanly with standard fmt package printing functions. The 163 | formatter is useful for inline printing of smaller data types similar to the 164 | standard %v format specifier. 165 | 166 | The custom formatter only responds to the %v (most compact), %+v (adds pointer 167 | addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb 168 | combinations. Any other verbs such as %x and %q will be sent to the the 169 | standard fmt package for formatting. In addition, the custom formatter ignores 170 | the width and precision arguments (however they will still work on the format 171 | specifiers not handled by the custom formatter). 172 | 173 | Custom Formatter Usage 174 | 175 | The simplest way to make use of the spew custom formatter is to call one of the 176 | convenience functions such as spew.Printf, spew.Println, or spew.Printf. The 177 | functions have syntax you are most likely already familiar with: 178 | 179 | spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) 180 | spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 181 | spew.Println(myVar, myVar2) 182 | spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) 183 | spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 184 | 185 | See the Index for the full list convenience functions. 186 | 187 | Sample Formatter Output 188 | 189 | Double pointer to a uint8: 190 | %v: <**>5 191 | %+v: <**>(0xf8400420d0->0xf8400420c8)5 192 | %#v: (**uint8)5 193 | %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 194 | 195 | Pointer to circular struct with a uint8 field and a pointer to itself: 196 | %v: <*>{1 <*>} 197 | %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} 198 | %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} 199 | %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} 200 | 201 | See the Printf example for details on the setup of variables being shown 202 | here. 203 | 204 | Errors 205 | 206 | Since it is possible for custom Stringer/error interfaces to panic, spew 207 | detects them and handles them internally by printing the panic information 208 | inline with the output. Since spew is intended to provide deep pretty printing 209 | capabilities on structures, it intentionally does not return any errors. 210 | */ 211 | package spew 212 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/dump.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2016 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package spew 18 | 19 | import ( 20 | "bytes" 21 | "encoding/hex" 22 | "fmt" 23 | "io" 24 | "os" 25 | "reflect" 26 | "regexp" 27 | "strconv" 28 | "strings" 29 | ) 30 | 31 | var ( 32 | // uint8Type is a reflect.Type representing a uint8. It is used to 33 | // convert cgo types to uint8 slices for hexdumping. 34 | uint8Type = reflect.TypeOf(uint8(0)) 35 | 36 | // cCharRE is a regular expression that matches a cgo char. 37 | // It is used to detect character arrays to hexdump them. 38 | cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) 39 | 40 | // cUnsignedCharRE is a regular expression that matches a cgo unsigned 41 | // char. It is used to detect unsigned character arrays to hexdump 42 | // them. 43 | cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) 44 | 45 | // cUint8tCharRE is a regular expression that matches a cgo uint8_t. 46 | // It is used to detect uint8_t arrays to hexdump them. 47 | cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) 48 | ) 49 | 50 | // dumpState contains information about the state of a dump operation. 51 | type dumpState struct { 52 | w io.Writer 53 | depth int 54 | pointers map[uintptr]int 55 | ignoreNextType bool 56 | ignoreNextIndent bool 57 | cs *ConfigState 58 | } 59 | 60 | // indent performs indentation according to the depth level and cs.Indent 61 | // option. 62 | func (d *dumpState) indent() { 63 | if d.ignoreNextIndent { 64 | d.ignoreNextIndent = false 65 | return 66 | } 67 | d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) 68 | } 69 | 70 | // unpackValue returns values inside of non-nil interfaces when possible. 71 | // This is useful for data types like structs, arrays, slices, and maps which 72 | // can contain varying types packed inside an interface. 73 | func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { 74 | if v.Kind() == reflect.Interface && !v.IsNil() { 75 | v = v.Elem() 76 | } 77 | return v 78 | } 79 | 80 | // dumpPtr handles formatting of pointers by indirecting them as necessary. 81 | func (d *dumpState) dumpPtr(v reflect.Value) { 82 | // Remove pointers at or below the current depth from map used to detect 83 | // circular refs. 84 | for k, depth := range d.pointers { 85 | if depth >= d.depth { 86 | delete(d.pointers, k) 87 | } 88 | } 89 | 90 | // Keep list of all dereferenced pointers to show later. 91 | pointerChain := make([]uintptr, 0) 92 | 93 | // Figure out how many levels of indirection there are by dereferencing 94 | // pointers and unpacking interfaces down the chain while detecting circular 95 | // references. 96 | nilFound := false 97 | cycleFound := false 98 | indirects := 0 99 | ve := v 100 | for ve.Kind() == reflect.Ptr { 101 | if ve.IsNil() { 102 | nilFound = true 103 | break 104 | } 105 | indirects++ 106 | addr := ve.Pointer() 107 | pointerChain = append(pointerChain, addr) 108 | if pd, ok := d.pointers[addr]; ok && pd < d.depth { 109 | cycleFound = true 110 | indirects-- 111 | break 112 | } 113 | d.pointers[addr] = d.depth 114 | 115 | ve = ve.Elem() 116 | if ve.Kind() == reflect.Interface { 117 | if ve.IsNil() { 118 | nilFound = true 119 | break 120 | } 121 | ve = ve.Elem() 122 | } 123 | } 124 | 125 | // Display type information. 126 | d.w.Write(openParenBytes) 127 | d.w.Write(bytes.Repeat(asteriskBytes, indirects)) 128 | d.w.Write([]byte(ve.Type().String())) 129 | d.w.Write(closeParenBytes) 130 | 131 | // Display pointer information. 132 | if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { 133 | d.w.Write(openParenBytes) 134 | for i, addr := range pointerChain { 135 | if i > 0 { 136 | d.w.Write(pointerChainBytes) 137 | } 138 | printHexPtr(d.w, addr) 139 | } 140 | d.w.Write(closeParenBytes) 141 | } 142 | 143 | // Display dereferenced value. 144 | d.w.Write(openParenBytes) 145 | switch { 146 | case nilFound: 147 | d.w.Write(nilAngleBytes) 148 | 149 | case cycleFound: 150 | d.w.Write(circularBytes) 151 | 152 | default: 153 | d.ignoreNextType = true 154 | d.dump(ve) 155 | } 156 | d.w.Write(closeParenBytes) 157 | } 158 | 159 | // dumpSlice handles formatting of arrays and slices. Byte (uint8 under 160 | // reflection) arrays and slices are dumped in hexdump -C fashion. 161 | func (d *dumpState) dumpSlice(v reflect.Value) { 162 | // Determine whether this type should be hex dumped or not. Also, 163 | // for types which should be hexdumped, try to use the underlying data 164 | // first, then fall back to trying to convert them to a uint8 slice. 165 | var buf []uint8 166 | doConvert := false 167 | doHexDump := false 168 | numEntries := v.Len() 169 | if numEntries > 0 { 170 | vt := v.Index(0).Type() 171 | vts := vt.String() 172 | switch { 173 | // C types that need to be converted. 174 | case cCharRE.MatchString(vts): 175 | fallthrough 176 | case cUnsignedCharRE.MatchString(vts): 177 | fallthrough 178 | case cUint8tCharRE.MatchString(vts): 179 | doConvert = true 180 | 181 | // Try to use existing uint8 slices and fall back to converting 182 | // and copying if that fails. 183 | case vt.Kind() == reflect.Uint8: 184 | // We need an addressable interface to convert the type 185 | // to a byte slice. However, the reflect package won't 186 | // give us an interface on certain things like 187 | // unexported struct fields in order to enforce 188 | // visibility rules. We use unsafe, when available, to 189 | // bypass these restrictions since this package does not 190 | // mutate the values. 191 | vs := v 192 | if !vs.CanInterface() || !vs.CanAddr() { 193 | vs = unsafeReflectValue(vs) 194 | } 195 | if !UnsafeDisabled { 196 | vs = vs.Slice(0, numEntries) 197 | 198 | // Use the existing uint8 slice if it can be 199 | // type asserted. 200 | iface := vs.Interface() 201 | if slice, ok := iface.([]uint8); ok { 202 | buf = slice 203 | doHexDump = true 204 | break 205 | } 206 | } 207 | 208 | // The underlying data needs to be converted if it can't 209 | // be type asserted to a uint8 slice. 210 | doConvert = true 211 | } 212 | 213 | // Copy and convert the underlying type if needed. 214 | if doConvert && vt.ConvertibleTo(uint8Type) { 215 | // Convert and copy each element into a uint8 byte 216 | // slice. 217 | buf = make([]uint8, numEntries) 218 | for i := 0; i < numEntries; i++ { 219 | vv := v.Index(i) 220 | buf[i] = uint8(vv.Convert(uint8Type).Uint()) 221 | } 222 | doHexDump = true 223 | } 224 | } 225 | 226 | // Hexdump the entire slice as needed. 227 | if doHexDump { 228 | indent := strings.Repeat(d.cs.Indent, d.depth) 229 | str := indent + hex.Dump(buf) 230 | str = strings.Replace(str, "\n", "\n"+indent, -1) 231 | str = strings.TrimRight(str, d.cs.Indent) 232 | d.w.Write([]byte(str)) 233 | return 234 | } 235 | 236 | // Recursively call dump for each item. 237 | for i := 0; i < numEntries; i++ { 238 | d.dump(d.unpackValue(v.Index(i))) 239 | if i < (numEntries - 1) { 240 | d.w.Write(commaNewlineBytes) 241 | } else { 242 | d.w.Write(newlineBytes) 243 | } 244 | } 245 | } 246 | 247 | // dump is the main workhorse for dumping a value. It uses the passed reflect 248 | // value to figure out what kind of object we are dealing with and formats it 249 | // appropriately. It is a recursive function, however circular data structures 250 | // are detected and handled properly. 251 | func (d *dumpState) dump(v reflect.Value) { 252 | // Handle invalid reflect values immediately. 253 | kind := v.Kind() 254 | if kind == reflect.Invalid { 255 | d.w.Write(invalidAngleBytes) 256 | return 257 | } 258 | 259 | // Handle pointers specially. 260 | if kind == reflect.Ptr { 261 | d.indent() 262 | d.dumpPtr(v) 263 | return 264 | } 265 | 266 | // Print type information unless already handled elsewhere. 267 | if !d.ignoreNextType { 268 | d.indent() 269 | d.w.Write(openParenBytes) 270 | d.w.Write([]byte(v.Type().String())) 271 | d.w.Write(closeParenBytes) 272 | d.w.Write(spaceBytes) 273 | } 274 | d.ignoreNextType = false 275 | 276 | // Display length and capacity if the built-in len and cap functions 277 | // work with the value's kind and the len/cap itself is non-zero. 278 | valueLen, valueCap := 0, 0 279 | switch v.Kind() { 280 | case reflect.Array, reflect.Slice, reflect.Chan: 281 | valueLen, valueCap = v.Len(), v.Cap() 282 | case reflect.Map, reflect.String: 283 | valueLen = v.Len() 284 | } 285 | if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { 286 | d.w.Write(openParenBytes) 287 | if valueLen != 0 { 288 | d.w.Write(lenEqualsBytes) 289 | printInt(d.w, int64(valueLen), 10) 290 | } 291 | if !d.cs.DisableCapacities && valueCap != 0 { 292 | if valueLen != 0 { 293 | d.w.Write(spaceBytes) 294 | } 295 | d.w.Write(capEqualsBytes) 296 | printInt(d.w, int64(valueCap), 10) 297 | } 298 | d.w.Write(closeParenBytes) 299 | d.w.Write(spaceBytes) 300 | } 301 | 302 | // Call Stringer/error interfaces if they exist and the handle methods flag 303 | // is enabled 304 | if !d.cs.DisableMethods { 305 | if (kind != reflect.Invalid) && (kind != reflect.Interface) { 306 | if handled := handleMethods(d.cs, d.w, v); handled { 307 | return 308 | } 309 | } 310 | } 311 | 312 | switch kind { 313 | case reflect.Invalid: 314 | // Do nothing. We should never get here since invalid has already 315 | // been handled above. 316 | 317 | case reflect.Bool: 318 | printBool(d.w, v.Bool()) 319 | 320 | case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: 321 | printInt(d.w, v.Int(), 10) 322 | 323 | case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: 324 | printUint(d.w, v.Uint(), 10) 325 | 326 | case reflect.Float32: 327 | printFloat(d.w, v.Float(), 32) 328 | 329 | case reflect.Float64: 330 | printFloat(d.w, v.Float(), 64) 331 | 332 | case reflect.Complex64: 333 | printComplex(d.w, v.Complex(), 32) 334 | 335 | case reflect.Complex128: 336 | printComplex(d.w, v.Complex(), 64) 337 | 338 | case reflect.Slice: 339 | if v.IsNil() { 340 | d.w.Write(nilAngleBytes) 341 | break 342 | } 343 | fallthrough 344 | 345 | case reflect.Array: 346 | d.w.Write(openBraceNewlineBytes) 347 | d.depth++ 348 | if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { 349 | d.indent() 350 | d.w.Write(maxNewlineBytes) 351 | } else { 352 | d.dumpSlice(v) 353 | } 354 | d.depth-- 355 | d.indent() 356 | d.w.Write(closeBraceBytes) 357 | 358 | case reflect.String: 359 | d.w.Write([]byte(strconv.Quote(v.String()))) 360 | 361 | case reflect.Interface: 362 | // The only time we should get here is for nil interfaces due to 363 | // unpackValue calls. 364 | if v.IsNil() { 365 | d.w.Write(nilAngleBytes) 366 | } 367 | 368 | case reflect.Ptr: 369 | // Do nothing. We should never get here since pointers have already 370 | // been handled above. 371 | 372 | case reflect.Map: 373 | // nil maps should be indicated as different than empty maps 374 | if v.IsNil() { 375 | d.w.Write(nilAngleBytes) 376 | break 377 | } 378 | 379 | d.w.Write(openBraceNewlineBytes) 380 | d.depth++ 381 | if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { 382 | d.indent() 383 | d.w.Write(maxNewlineBytes) 384 | } else { 385 | numEntries := v.Len() 386 | keys := v.MapKeys() 387 | if d.cs.SortKeys { 388 | sortValues(keys, d.cs) 389 | } 390 | for i, key := range keys { 391 | d.dump(d.unpackValue(key)) 392 | d.w.Write(colonSpaceBytes) 393 | d.ignoreNextIndent = true 394 | d.dump(d.unpackValue(v.MapIndex(key))) 395 | if i < (numEntries - 1) { 396 | d.w.Write(commaNewlineBytes) 397 | } else { 398 | d.w.Write(newlineBytes) 399 | } 400 | } 401 | } 402 | d.depth-- 403 | d.indent() 404 | d.w.Write(closeBraceBytes) 405 | 406 | case reflect.Struct: 407 | d.w.Write(openBraceNewlineBytes) 408 | d.depth++ 409 | if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { 410 | d.indent() 411 | d.w.Write(maxNewlineBytes) 412 | } else { 413 | vt := v.Type() 414 | numFields := v.NumField() 415 | for i := 0; i < numFields; i++ { 416 | d.indent() 417 | vtf := vt.Field(i) 418 | d.w.Write([]byte(vtf.Name)) 419 | d.w.Write(colonSpaceBytes) 420 | d.ignoreNextIndent = true 421 | d.dump(d.unpackValue(v.Field(i))) 422 | if i < (numFields - 1) { 423 | d.w.Write(commaNewlineBytes) 424 | } else { 425 | d.w.Write(newlineBytes) 426 | } 427 | } 428 | } 429 | d.depth-- 430 | d.indent() 431 | d.w.Write(closeBraceBytes) 432 | 433 | case reflect.Uintptr: 434 | printHexPtr(d.w, uintptr(v.Uint())) 435 | 436 | case reflect.UnsafePointer, reflect.Chan, reflect.Func: 437 | printHexPtr(d.w, v.Pointer()) 438 | 439 | // There were not any other types at the time this code was written, but 440 | // fall back to letting the default fmt package handle it in case any new 441 | // types are added. 442 | default: 443 | if v.CanInterface() { 444 | fmt.Fprintf(d.w, "%v", v.Interface()) 445 | } else { 446 | fmt.Fprintf(d.w, "%v", v.String()) 447 | } 448 | } 449 | } 450 | 451 | // fdump is a helper function to consolidate the logic from the various public 452 | // methods which take varying writers and config states. 453 | func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { 454 | for _, arg := range a { 455 | if arg == nil { 456 | w.Write(interfaceBytes) 457 | w.Write(spaceBytes) 458 | w.Write(nilAngleBytes) 459 | w.Write(newlineBytes) 460 | continue 461 | } 462 | 463 | d := dumpState{w: w, cs: cs} 464 | d.pointers = make(map[uintptr]int) 465 | d.dump(reflect.ValueOf(arg)) 466 | d.w.Write(newlineBytes) 467 | } 468 | } 469 | 470 | // Fdump formats and displays the passed arguments to io.Writer w. It formats 471 | // exactly the same as Dump. 472 | func Fdump(w io.Writer, a ...interface{}) { 473 | fdump(&Config, w, a...) 474 | } 475 | 476 | // Sdump returns a string with the passed arguments formatted exactly the same 477 | // as Dump. 478 | func Sdump(a ...interface{}) string { 479 | var buf bytes.Buffer 480 | fdump(&Config, &buf, a...) 481 | return buf.String() 482 | } 483 | 484 | /* 485 | Dump displays the passed parameters to standard out with newlines, customizable 486 | indentation, and additional debug information such as complete types and all 487 | pointer addresses used to indirect to the final value. It provides the 488 | following features over the built-in printing facilities provided by the fmt 489 | package: 490 | 491 | * Pointers are dereferenced and followed 492 | * Circular data structures are detected and handled properly 493 | * Custom Stringer/error interfaces are optionally invoked, including 494 | on unexported types 495 | * Custom types which only implement the Stringer/error interfaces via 496 | a pointer receiver are optionally invoked when passing non-pointer 497 | variables 498 | * Byte arrays and slices are dumped like the hexdump -C command which 499 | includes offsets, byte values in hex, and ASCII output 500 | 501 | The configuration options are controlled by an exported package global, 502 | spew.Config. See ConfigState for options documentation. 503 | 504 | See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to 505 | get the formatted result as a string. 506 | */ 507 | func Dump(a ...interface{}) { 508 | fdump(&Config, os.Stdout, a...) 509 | } 510 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/format.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2016 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package spew 18 | 19 | import ( 20 | "bytes" 21 | "fmt" 22 | "reflect" 23 | "strconv" 24 | "strings" 25 | ) 26 | 27 | // supportedFlags is a list of all the character flags supported by fmt package. 28 | const supportedFlags = "0-+# " 29 | 30 | // formatState implements the fmt.Formatter interface and contains information 31 | // about the state of a formatting operation. The NewFormatter function can 32 | // be used to get a new Formatter which can be used directly as arguments 33 | // in standard fmt package printing calls. 34 | type formatState struct { 35 | value interface{} 36 | fs fmt.State 37 | depth int 38 | pointers map[uintptr]int 39 | ignoreNextType bool 40 | cs *ConfigState 41 | } 42 | 43 | // buildDefaultFormat recreates the original format string without precision 44 | // and width information to pass in to fmt.Sprintf in the case of an 45 | // unrecognized type. Unless new types are added to the language, this 46 | // function won't ever be called. 47 | func (f *formatState) buildDefaultFormat() (format string) { 48 | buf := bytes.NewBuffer(percentBytes) 49 | 50 | for _, flag := range supportedFlags { 51 | if f.fs.Flag(int(flag)) { 52 | buf.WriteRune(flag) 53 | } 54 | } 55 | 56 | buf.WriteRune('v') 57 | 58 | format = buf.String() 59 | return format 60 | } 61 | 62 | // constructOrigFormat recreates the original format string including precision 63 | // and width information to pass along to the standard fmt package. This allows 64 | // automatic deferral of all format strings this package doesn't support. 65 | func (f *formatState) constructOrigFormat(verb rune) (format string) { 66 | buf := bytes.NewBuffer(percentBytes) 67 | 68 | for _, flag := range supportedFlags { 69 | if f.fs.Flag(int(flag)) { 70 | buf.WriteRune(flag) 71 | } 72 | } 73 | 74 | if width, ok := f.fs.Width(); ok { 75 | buf.WriteString(strconv.Itoa(width)) 76 | } 77 | 78 | if precision, ok := f.fs.Precision(); ok { 79 | buf.Write(precisionBytes) 80 | buf.WriteString(strconv.Itoa(precision)) 81 | } 82 | 83 | buf.WriteRune(verb) 84 | 85 | format = buf.String() 86 | return format 87 | } 88 | 89 | // unpackValue returns values inside of non-nil interfaces when possible and 90 | // ensures that types for values which have been unpacked from an interface 91 | // are displayed when the show types flag is also set. 92 | // This is useful for data types like structs, arrays, slices, and maps which 93 | // can contain varying types packed inside an interface. 94 | func (f *formatState) unpackValue(v reflect.Value) reflect.Value { 95 | if v.Kind() == reflect.Interface { 96 | f.ignoreNextType = false 97 | if !v.IsNil() { 98 | v = v.Elem() 99 | } 100 | } 101 | return v 102 | } 103 | 104 | // formatPtr handles formatting of pointers by indirecting them as necessary. 105 | func (f *formatState) formatPtr(v reflect.Value) { 106 | // Display nil if top level pointer is nil. 107 | showTypes := f.fs.Flag('#') 108 | if v.IsNil() && (!showTypes || f.ignoreNextType) { 109 | f.fs.Write(nilAngleBytes) 110 | return 111 | } 112 | 113 | // Remove pointers at or below the current depth from map used to detect 114 | // circular refs. 115 | for k, depth := range f.pointers { 116 | if depth >= f.depth { 117 | delete(f.pointers, k) 118 | } 119 | } 120 | 121 | // Keep list of all dereferenced pointers to possibly show later. 122 | pointerChain := make([]uintptr, 0) 123 | 124 | // Figure out how many levels of indirection there are by derferencing 125 | // pointers and unpacking interfaces down the chain while detecting circular 126 | // references. 127 | nilFound := false 128 | cycleFound := false 129 | indirects := 0 130 | ve := v 131 | for ve.Kind() == reflect.Ptr { 132 | if ve.IsNil() { 133 | nilFound = true 134 | break 135 | } 136 | indirects++ 137 | addr := ve.Pointer() 138 | pointerChain = append(pointerChain, addr) 139 | if pd, ok := f.pointers[addr]; ok && pd < f.depth { 140 | cycleFound = true 141 | indirects-- 142 | break 143 | } 144 | f.pointers[addr] = f.depth 145 | 146 | ve = ve.Elem() 147 | if ve.Kind() == reflect.Interface { 148 | if ve.IsNil() { 149 | nilFound = true 150 | break 151 | } 152 | ve = ve.Elem() 153 | } 154 | } 155 | 156 | // Display type or indirection level depending on flags. 157 | if showTypes && !f.ignoreNextType { 158 | f.fs.Write(openParenBytes) 159 | f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) 160 | f.fs.Write([]byte(ve.Type().String())) 161 | f.fs.Write(closeParenBytes) 162 | } else { 163 | if nilFound || cycleFound { 164 | indirects += strings.Count(ve.Type().String(), "*") 165 | } 166 | f.fs.Write(openAngleBytes) 167 | f.fs.Write([]byte(strings.Repeat("*", indirects))) 168 | f.fs.Write(closeAngleBytes) 169 | } 170 | 171 | // Display pointer information depending on flags. 172 | if f.fs.Flag('+') && (len(pointerChain) > 0) { 173 | f.fs.Write(openParenBytes) 174 | for i, addr := range pointerChain { 175 | if i > 0 { 176 | f.fs.Write(pointerChainBytes) 177 | } 178 | printHexPtr(f.fs, addr) 179 | } 180 | f.fs.Write(closeParenBytes) 181 | } 182 | 183 | // Display dereferenced value. 184 | switch { 185 | case nilFound: 186 | f.fs.Write(nilAngleBytes) 187 | 188 | case cycleFound: 189 | f.fs.Write(circularShortBytes) 190 | 191 | default: 192 | f.ignoreNextType = true 193 | f.format(ve) 194 | } 195 | } 196 | 197 | // format is the main workhorse for providing the Formatter interface. It 198 | // uses the passed reflect value to figure out what kind of object we are 199 | // dealing with and formats it appropriately. It is a recursive function, 200 | // however circular data structures are detected and handled properly. 201 | func (f *formatState) format(v reflect.Value) { 202 | // Handle invalid reflect values immediately. 203 | kind := v.Kind() 204 | if kind == reflect.Invalid { 205 | f.fs.Write(invalidAngleBytes) 206 | return 207 | } 208 | 209 | // Handle pointers specially. 210 | if kind == reflect.Ptr { 211 | f.formatPtr(v) 212 | return 213 | } 214 | 215 | // Print type information unless already handled elsewhere. 216 | if !f.ignoreNextType && f.fs.Flag('#') { 217 | f.fs.Write(openParenBytes) 218 | f.fs.Write([]byte(v.Type().String())) 219 | f.fs.Write(closeParenBytes) 220 | } 221 | f.ignoreNextType = false 222 | 223 | // Call Stringer/error interfaces if they exist and the handle methods 224 | // flag is enabled. 225 | if !f.cs.DisableMethods { 226 | if (kind != reflect.Invalid) && (kind != reflect.Interface) { 227 | if handled := handleMethods(f.cs, f.fs, v); handled { 228 | return 229 | } 230 | } 231 | } 232 | 233 | switch kind { 234 | case reflect.Invalid: 235 | // Do nothing. We should never get here since invalid has already 236 | // been handled above. 237 | 238 | case reflect.Bool: 239 | printBool(f.fs, v.Bool()) 240 | 241 | case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: 242 | printInt(f.fs, v.Int(), 10) 243 | 244 | case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: 245 | printUint(f.fs, v.Uint(), 10) 246 | 247 | case reflect.Float32: 248 | printFloat(f.fs, v.Float(), 32) 249 | 250 | case reflect.Float64: 251 | printFloat(f.fs, v.Float(), 64) 252 | 253 | case reflect.Complex64: 254 | printComplex(f.fs, v.Complex(), 32) 255 | 256 | case reflect.Complex128: 257 | printComplex(f.fs, v.Complex(), 64) 258 | 259 | case reflect.Slice: 260 | if v.IsNil() { 261 | f.fs.Write(nilAngleBytes) 262 | break 263 | } 264 | fallthrough 265 | 266 | case reflect.Array: 267 | f.fs.Write(openBracketBytes) 268 | f.depth++ 269 | if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { 270 | f.fs.Write(maxShortBytes) 271 | } else { 272 | numEntries := v.Len() 273 | for i := 0; i < numEntries; i++ { 274 | if i > 0 { 275 | f.fs.Write(spaceBytes) 276 | } 277 | f.ignoreNextType = true 278 | f.format(f.unpackValue(v.Index(i))) 279 | } 280 | } 281 | f.depth-- 282 | f.fs.Write(closeBracketBytes) 283 | 284 | case reflect.String: 285 | f.fs.Write([]byte(v.String())) 286 | 287 | case reflect.Interface: 288 | // The only time we should get here is for nil interfaces due to 289 | // unpackValue calls. 290 | if v.IsNil() { 291 | f.fs.Write(nilAngleBytes) 292 | } 293 | 294 | case reflect.Ptr: 295 | // Do nothing. We should never get here since pointers have already 296 | // been handled above. 297 | 298 | case reflect.Map: 299 | // nil maps should be indicated as different than empty maps 300 | if v.IsNil() { 301 | f.fs.Write(nilAngleBytes) 302 | break 303 | } 304 | 305 | f.fs.Write(openMapBytes) 306 | f.depth++ 307 | if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { 308 | f.fs.Write(maxShortBytes) 309 | } else { 310 | keys := v.MapKeys() 311 | if f.cs.SortKeys { 312 | sortValues(keys, f.cs) 313 | } 314 | for i, key := range keys { 315 | if i > 0 { 316 | f.fs.Write(spaceBytes) 317 | } 318 | f.ignoreNextType = true 319 | f.format(f.unpackValue(key)) 320 | f.fs.Write(colonBytes) 321 | f.ignoreNextType = true 322 | f.format(f.unpackValue(v.MapIndex(key))) 323 | } 324 | } 325 | f.depth-- 326 | f.fs.Write(closeMapBytes) 327 | 328 | case reflect.Struct: 329 | numFields := v.NumField() 330 | f.fs.Write(openBraceBytes) 331 | f.depth++ 332 | if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { 333 | f.fs.Write(maxShortBytes) 334 | } else { 335 | vt := v.Type() 336 | for i := 0; i < numFields; i++ { 337 | if i > 0 { 338 | f.fs.Write(spaceBytes) 339 | } 340 | vtf := vt.Field(i) 341 | if f.fs.Flag('+') || f.fs.Flag('#') { 342 | f.fs.Write([]byte(vtf.Name)) 343 | f.fs.Write(colonBytes) 344 | } 345 | f.format(f.unpackValue(v.Field(i))) 346 | } 347 | } 348 | f.depth-- 349 | f.fs.Write(closeBraceBytes) 350 | 351 | case reflect.Uintptr: 352 | printHexPtr(f.fs, uintptr(v.Uint())) 353 | 354 | case reflect.UnsafePointer, reflect.Chan, reflect.Func: 355 | printHexPtr(f.fs, v.Pointer()) 356 | 357 | // There were not any other types at the time this code was written, but 358 | // fall back to letting the default fmt package handle it if any get added. 359 | default: 360 | format := f.buildDefaultFormat() 361 | if v.CanInterface() { 362 | fmt.Fprintf(f.fs, format, v.Interface()) 363 | } else { 364 | fmt.Fprintf(f.fs, format, v.String()) 365 | } 366 | } 367 | } 368 | 369 | // Format satisfies the fmt.Formatter interface. See NewFormatter for usage 370 | // details. 371 | func (f *formatState) Format(fs fmt.State, verb rune) { 372 | f.fs = fs 373 | 374 | // Use standard formatting for verbs that are not v. 375 | if verb != 'v' { 376 | format := f.constructOrigFormat(verb) 377 | fmt.Fprintf(fs, format, f.value) 378 | return 379 | } 380 | 381 | if f.value == nil { 382 | if fs.Flag('#') { 383 | fs.Write(interfaceBytes) 384 | } 385 | fs.Write(nilAngleBytes) 386 | return 387 | } 388 | 389 | f.format(reflect.ValueOf(f.value)) 390 | } 391 | 392 | // newFormatter is a helper function to consolidate the logic from the various 393 | // public methods which take varying config states. 394 | func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { 395 | fs := &formatState{value: v, cs: cs} 396 | fs.pointers = make(map[uintptr]int) 397 | return fs 398 | } 399 | 400 | /* 401 | NewFormatter returns a custom formatter that satisfies the fmt.Formatter 402 | interface. As a result, it integrates cleanly with standard fmt package 403 | printing functions. The formatter is useful for inline printing of smaller data 404 | types similar to the standard %v format specifier. 405 | 406 | The custom formatter only responds to the %v (most compact), %+v (adds pointer 407 | addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb 408 | combinations. Any other verbs such as %x and %q will be sent to the the 409 | standard fmt package for formatting. In addition, the custom formatter ignores 410 | the width and precision arguments (however they will still work on the format 411 | specifiers not handled by the custom formatter). 412 | 413 | Typically this function shouldn't be called directly. It is much easier to make 414 | use of the custom formatter by calling one of the convenience functions such as 415 | Printf, Println, or Fprintf. 416 | */ 417 | func NewFormatter(v interface{}) fmt.Formatter { 418 | return newFormatter(&Config, v) 419 | } 420 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/spew.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2016 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package spew 18 | 19 | import ( 20 | "fmt" 21 | "io" 22 | ) 23 | 24 | // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were 25 | // passed with a default Formatter interface returned by NewFormatter. It 26 | // returns the formatted string as a value that satisfies error. See 27 | // NewFormatter for formatting details. 28 | // 29 | // This function is shorthand for the following syntax: 30 | // 31 | // fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) 32 | func Errorf(format string, a ...interface{}) (err error) { 33 | return fmt.Errorf(format, convertArgs(a)...) 34 | } 35 | 36 | // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were 37 | // passed with a default Formatter interface returned by NewFormatter. It 38 | // returns the number of bytes written and any write error encountered. See 39 | // NewFormatter for formatting details. 40 | // 41 | // This function is shorthand for the following syntax: 42 | // 43 | // fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) 44 | func Fprint(w io.Writer, a ...interface{}) (n int, err error) { 45 | return fmt.Fprint(w, convertArgs(a)...) 46 | } 47 | 48 | // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were 49 | // passed with a default Formatter interface returned by NewFormatter. It 50 | // returns the number of bytes written and any write error encountered. See 51 | // NewFormatter for formatting details. 52 | // 53 | // This function is shorthand for the following syntax: 54 | // 55 | // fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) 56 | func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { 57 | return fmt.Fprintf(w, format, convertArgs(a)...) 58 | } 59 | 60 | // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it 61 | // passed with a default Formatter interface returned by NewFormatter. See 62 | // NewFormatter for formatting details. 63 | // 64 | // This function is shorthand for the following syntax: 65 | // 66 | // fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) 67 | func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { 68 | return fmt.Fprintln(w, convertArgs(a)...) 69 | } 70 | 71 | // Print is a wrapper for fmt.Print that treats each argument as if it were 72 | // passed with a default Formatter interface returned by NewFormatter. It 73 | // returns the number of bytes written and any write error encountered. See 74 | // NewFormatter for formatting details. 75 | // 76 | // This function is shorthand for the following syntax: 77 | // 78 | // fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) 79 | func Print(a ...interface{}) (n int, err error) { 80 | return fmt.Print(convertArgs(a)...) 81 | } 82 | 83 | // Printf is a wrapper for fmt.Printf that treats each argument as if it were 84 | // passed with a default Formatter interface returned by NewFormatter. It 85 | // returns the number of bytes written and any write error encountered. See 86 | // NewFormatter for formatting details. 87 | // 88 | // This function is shorthand for the following syntax: 89 | // 90 | // fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) 91 | func Printf(format string, a ...interface{}) (n int, err error) { 92 | return fmt.Printf(format, convertArgs(a)...) 93 | } 94 | 95 | // Println is a wrapper for fmt.Println that treats each argument as if it were 96 | // passed with a default Formatter interface returned by NewFormatter. It 97 | // returns the number of bytes written and any write error encountered. See 98 | // NewFormatter for formatting details. 99 | // 100 | // This function is shorthand for the following syntax: 101 | // 102 | // fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) 103 | func Println(a ...interface{}) (n int, err error) { 104 | return fmt.Println(convertArgs(a)...) 105 | } 106 | 107 | // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were 108 | // passed with a default Formatter interface returned by NewFormatter. It 109 | // returns the resulting string. See NewFormatter for formatting details. 110 | // 111 | // This function is shorthand for the following syntax: 112 | // 113 | // fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) 114 | func Sprint(a ...interface{}) string { 115 | return fmt.Sprint(convertArgs(a)...) 116 | } 117 | 118 | // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were 119 | // passed with a default Formatter interface returned by NewFormatter. It 120 | // returns the resulting string. See NewFormatter for formatting details. 121 | // 122 | // This function is shorthand for the following syntax: 123 | // 124 | // fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) 125 | func Sprintf(format string, a ...interface{}) string { 126 | return fmt.Sprintf(format, convertArgs(a)...) 127 | } 128 | 129 | // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it 130 | // were passed with a default Formatter interface returned by NewFormatter. It 131 | // returns the resulting string. See NewFormatter for formatting details. 132 | // 133 | // This function is shorthand for the following syntax: 134 | // 135 | // fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) 136 | func Sprintln(a ...interface{}) string { 137 | return fmt.Sprintln(convertArgs(a)...) 138 | } 139 | 140 | // convertArgs accepts a slice of arguments and returns a slice of the same 141 | // length with each argument converted to a default spew Formatter interface. 142 | func convertArgs(args []interface{}) (formatters []interface{}) { 143 | formatters = make([]interface{}, len(args)) 144 | for index, arg := range args { 145 | formatters[index] = NewFormatter(arg) 146 | } 147 | return formatters 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/pmezard/go-difflib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Patrick Mezard 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | The names of its contributors may not be used to endorse or promote 14 | products derived from this software without specific prior written 15 | permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 18 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_compare.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "reflect" 7 | "time" 8 | ) 9 | 10 | type CompareType int 11 | 12 | const ( 13 | compareLess CompareType = iota - 1 14 | compareEqual 15 | compareGreater 16 | ) 17 | 18 | var ( 19 | intType = reflect.TypeOf(int(1)) 20 | int8Type = reflect.TypeOf(int8(1)) 21 | int16Type = reflect.TypeOf(int16(1)) 22 | int32Type = reflect.TypeOf(int32(1)) 23 | int64Type = reflect.TypeOf(int64(1)) 24 | 25 | uintType = reflect.TypeOf(uint(1)) 26 | uint8Type = reflect.TypeOf(uint8(1)) 27 | uint16Type = reflect.TypeOf(uint16(1)) 28 | uint32Type = reflect.TypeOf(uint32(1)) 29 | uint64Type = reflect.TypeOf(uint64(1)) 30 | 31 | float32Type = reflect.TypeOf(float32(1)) 32 | float64Type = reflect.TypeOf(float64(1)) 33 | 34 | stringType = reflect.TypeOf("") 35 | 36 | timeType = reflect.TypeOf(time.Time{}) 37 | bytesType = reflect.TypeOf([]byte{}) 38 | ) 39 | 40 | func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { 41 | obj1Value := reflect.ValueOf(obj1) 42 | obj2Value := reflect.ValueOf(obj2) 43 | 44 | // throughout this switch we try and avoid calling .Convert() if possible, 45 | // as this has a pretty big performance impact 46 | switch kind { 47 | case reflect.Int: 48 | { 49 | intobj1, ok := obj1.(int) 50 | if !ok { 51 | intobj1 = obj1Value.Convert(intType).Interface().(int) 52 | } 53 | intobj2, ok := obj2.(int) 54 | if !ok { 55 | intobj2 = obj2Value.Convert(intType).Interface().(int) 56 | } 57 | if intobj1 > intobj2 { 58 | return compareGreater, true 59 | } 60 | if intobj1 == intobj2 { 61 | return compareEqual, true 62 | } 63 | if intobj1 < intobj2 { 64 | return compareLess, true 65 | } 66 | } 67 | case reflect.Int8: 68 | { 69 | int8obj1, ok := obj1.(int8) 70 | if !ok { 71 | int8obj1 = obj1Value.Convert(int8Type).Interface().(int8) 72 | } 73 | int8obj2, ok := obj2.(int8) 74 | if !ok { 75 | int8obj2 = obj2Value.Convert(int8Type).Interface().(int8) 76 | } 77 | if int8obj1 > int8obj2 { 78 | return compareGreater, true 79 | } 80 | if int8obj1 == int8obj2 { 81 | return compareEqual, true 82 | } 83 | if int8obj1 < int8obj2 { 84 | return compareLess, true 85 | } 86 | } 87 | case reflect.Int16: 88 | { 89 | int16obj1, ok := obj1.(int16) 90 | if !ok { 91 | int16obj1 = obj1Value.Convert(int16Type).Interface().(int16) 92 | } 93 | int16obj2, ok := obj2.(int16) 94 | if !ok { 95 | int16obj2 = obj2Value.Convert(int16Type).Interface().(int16) 96 | } 97 | if int16obj1 > int16obj2 { 98 | return compareGreater, true 99 | } 100 | if int16obj1 == int16obj2 { 101 | return compareEqual, true 102 | } 103 | if int16obj1 < int16obj2 { 104 | return compareLess, true 105 | } 106 | } 107 | case reflect.Int32: 108 | { 109 | int32obj1, ok := obj1.(int32) 110 | if !ok { 111 | int32obj1 = obj1Value.Convert(int32Type).Interface().(int32) 112 | } 113 | int32obj2, ok := obj2.(int32) 114 | if !ok { 115 | int32obj2 = obj2Value.Convert(int32Type).Interface().(int32) 116 | } 117 | if int32obj1 > int32obj2 { 118 | return compareGreater, true 119 | } 120 | if int32obj1 == int32obj2 { 121 | return compareEqual, true 122 | } 123 | if int32obj1 < int32obj2 { 124 | return compareLess, true 125 | } 126 | } 127 | case reflect.Int64: 128 | { 129 | int64obj1, ok := obj1.(int64) 130 | if !ok { 131 | int64obj1 = obj1Value.Convert(int64Type).Interface().(int64) 132 | } 133 | int64obj2, ok := obj2.(int64) 134 | if !ok { 135 | int64obj2 = obj2Value.Convert(int64Type).Interface().(int64) 136 | } 137 | if int64obj1 > int64obj2 { 138 | return compareGreater, true 139 | } 140 | if int64obj1 == int64obj2 { 141 | return compareEqual, true 142 | } 143 | if int64obj1 < int64obj2 { 144 | return compareLess, true 145 | } 146 | } 147 | case reflect.Uint: 148 | { 149 | uintobj1, ok := obj1.(uint) 150 | if !ok { 151 | uintobj1 = obj1Value.Convert(uintType).Interface().(uint) 152 | } 153 | uintobj2, ok := obj2.(uint) 154 | if !ok { 155 | uintobj2 = obj2Value.Convert(uintType).Interface().(uint) 156 | } 157 | if uintobj1 > uintobj2 { 158 | return compareGreater, true 159 | } 160 | if uintobj1 == uintobj2 { 161 | return compareEqual, true 162 | } 163 | if uintobj1 < uintobj2 { 164 | return compareLess, true 165 | } 166 | } 167 | case reflect.Uint8: 168 | { 169 | uint8obj1, ok := obj1.(uint8) 170 | if !ok { 171 | uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8) 172 | } 173 | uint8obj2, ok := obj2.(uint8) 174 | if !ok { 175 | uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8) 176 | } 177 | if uint8obj1 > uint8obj2 { 178 | return compareGreater, true 179 | } 180 | if uint8obj1 == uint8obj2 { 181 | return compareEqual, true 182 | } 183 | if uint8obj1 < uint8obj2 { 184 | return compareLess, true 185 | } 186 | } 187 | case reflect.Uint16: 188 | { 189 | uint16obj1, ok := obj1.(uint16) 190 | if !ok { 191 | uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16) 192 | } 193 | uint16obj2, ok := obj2.(uint16) 194 | if !ok { 195 | uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16) 196 | } 197 | if uint16obj1 > uint16obj2 { 198 | return compareGreater, true 199 | } 200 | if uint16obj1 == uint16obj2 { 201 | return compareEqual, true 202 | } 203 | if uint16obj1 < uint16obj2 { 204 | return compareLess, true 205 | } 206 | } 207 | case reflect.Uint32: 208 | { 209 | uint32obj1, ok := obj1.(uint32) 210 | if !ok { 211 | uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32) 212 | } 213 | uint32obj2, ok := obj2.(uint32) 214 | if !ok { 215 | uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32) 216 | } 217 | if uint32obj1 > uint32obj2 { 218 | return compareGreater, true 219 | } 220 | if uint32obj1 == uint32obj2 { 221 | return compareEqual, true 222 | } 223 | if uint32obj1 < uint32obj2 { 224 | return compareLess, true 225 | } 226 | } 227 | case reflect.Uint64: 228 | { 229 | uint64obj1, ok := obj1.(uint64) 230 | if !ok { 231 | uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64) 232 | } 233 | uint64obj2, ok := obj2.(uint64) 234 | if !ok { 235 | uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64) 236 | } 237 | if uint64obj1 > uint64obj2 { 238 | return compareGreater, true 239 | } 240 | if uint64obj1 == uint64obj2 { 241 | return compareEqual, true 242 | } 243 | if uint64obj1 < uint64obj2 { 244 | return compareLess, true 245 | } 246 | } 247 | case reflect.Float32: 248 | { 249 | float32obj1, ok := obj1.(float32) 250 | if !ok { 251 | float32obj1 = obj1Value.Convert(float32Type).Interface().(float32) 252 | } 253 | float32obj2, ok := obj2.(float32) 254 | if !ok { 255 | float32obj2 = obj2Value.Convert(float32Type).Interface().(float32) 256 | } 257 | if float32obj1 > float32obj2 { 258 | return compareGreater, true 259 | } 260 | if float32obj1 == float32obj2 { 261 | return compareEqual, true 262 | } 263 | if float32obj1 < float32obj2 { 264 | return compareLess, true 265 | } 266 | } 267 | case reflect.Float64: 268 | { 269 | float64obj1, ok := obj1.(float64) 270 | if !ok { 271 | float64obj1 = obj1Value.Convert(float64Type).Interface().(float64) 272 | } 273 | float64obj2, ok := obj2.(float64) 274 | if !ok { 275 | float64obj2 = obj2Value.Convert(float64Type).Interface().(float64) 276 | } 277 | if float64obj1 > float64obj2 { 278 | return compareGreater, true 279 | } 280 | if float64obj1 == float64obj2 { 281 | return compareEqual, true 282 | } 283 | if float64obj1 < float64obj2 { 284 | return compareLess, true 285 | } 286 | } 287 | case reflect.String: 288 | { 289 | stringobj1, ok := obj1.(string) 290 | if !ok { 291 | stringobj1 = obj1Value.Convert(stringType).Interface().(string) 292 | } 293 | stringobj2, ok := obj2.(string) 294 | if !ok { 295 | stringobj2 = obj2Value.Convert(stringType).Interface().(string) 296 | } 297 | if stringobj1 > stringobj2 { 298 | return compareGreater, true 299 | } 300 | if stringobj1 == stringobj2 { 301 | return compareEqual, true 302 | } 303 | if stringobj1 < stringobj2 { 304 | return compareLess, true 305 | } 306 | } 307 | // Check for known struct types we can check for compare results. 308 | case reflect.Struct: 309 | { 310 | // All structs enter here. We're not interested in most types. 311 | if !canConvert(obj1Value, timeType) { 312 | break 313 | } 314 | 315 | // time.Time can compared! 316 | timeObj1, ok := obj1.(time.Time) 317 | if !ok { 318 | timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) 319 | } 320 | 321 | timeObj2, ok := obj2.(time.Time) 322 | if !ok { 323 | timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time) 324 | } 325 | 326 | return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64) 327 | } 328 | case reflect.Slice: 329 | { 330 | // We only care about the []byte type. 331 | if !canConvert(obj1Value, bytesType) { 332 | break 333 | } 334 | 335 | // []byte can be compared! 336 | bytesObj1, ok := obj1.([]byte) 337 | if !ok { 338 | bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte) 339 | 340 | } 341 | bytesObj2, ok := obj2.([]byte) 342 | if !ok { 343 | bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte) 344 | } 345 | 346 | return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true 347 | } 348 | } 349 | 350 | return compareEqual, false 351 | } 352 | 353 | // Greater asserts that the first element is greater than the second 354 | // 355 | // assert.Greater(t, 2, 1) 356 | // assert.Greater(t, float64(2), float64(1)) 357 | // assert.Greater(t, "b", "a") 358 | func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { 359 | if h, ok := t.(tHelper); ok { 360 | h.Helper() 361 | } 362 | return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) 363 | } 364 | 365 | // GreaterOrEqual asserts that the first element is greater than or equal to the second 366 | // 367 | // assert.GreaterOrEqual(t, 2, 1) 368 | // assert.GreaterOrEqual(t, 2, 2) 369 | // assert.GreaterOrEqual(t, "b", "a") 370 | // assert.GreaterOrEqual(t, "b", "b") 371 | func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { 372 | if h, ok := t.(tHelper); ok { 373 | h.Helper() 374 | } 375 | return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) 376 | } 377 | 378 | // Less asserts that the first element is less than the second 379 | // 380 | // assert.Less(t, 1, 2) 381 | // assert.Less(t, float64(1), float64(2)) 382 | // assert.Less(t, "a", "b") 383 | func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { 384 | if h, ok := t.(tHelper); ok { 385 | h.Helper() 386 | } 387 | return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) 388 | } 389 | 390 | // LessOrEqual asserts that the first element is less than or equal to the second 391 | // 392 | // assert.LessOrEqual(t, 1, 2) 393 | // assert.LessOrEqual(t, 2, 2) 394 | // assert.LessOrEqual(t, "a", "b") 395 | // assert.LessOrEqual(t, "b", "b") 396 | func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { 397 | if h, ok := t.(tHelper); ok { 398 | h.Helper() 399 | } 400 | return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) 401 | } 402 | 403 | // Positive asserts that the specified element is positive 404 | // 405 | // assert.Positive(t, 1) 406 | // assert.Positive(t, 1.23) 407 | func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { 408 | if h, ok := t.(tHelper); ok { 409 | h.Helper() 410 | } 411 | zero := reflect.Zero(reflect.TypeOf(e)) 412 | return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...) 413 | } 414 | 415 | // Negative asserts that the specified element is negative 416 | // 417 | // assert.Negative(t, -1) 418 | // assert.Negative(t, -1.23) 419 | func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { 420 | if h, ok := t.(tHelper); ok { 421 | h.Helper() 422 | } 423 | zero := reflect.Zero(reflect.TypeOf(e)) 424 | return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...) 425 | } 426 | 427 | func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { 428 | if h, ok := t.(tHelper); ok { 429 | h.Helper() 430 | } 431 | 432 | e1Kind := reflect.ValueOf(e1).Kind() 433 | e2Kind := reflect.ValueOf(e2).Kind() 434 | if e1Kind != e2Kind { 435 | return Fail(t, "Elements should be the same type", msgAndArgs...) 436 | } 437 | 438 | compareResult, isComparable := compare(e1, e2, e1Kind) 439 | if !isComparable { 440 | return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) 441 | } 442 | 443 | if !containsValue(allowedComparesResults, compareResult) { 444 | return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...) 445 | } 446 | 447 | return true 448 | } 449 | 450 | func containsValue(values []CompareType, value CompareType) bool { 451 | for _, v := range values { 452 | if v == value { 453 | return true 454 | } 455 | } 456 | 457 | return false 458 | } 459 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go: -------------------------------------------------------------------------------- 1 | //go:build go1.17 2 | // +build go1.17 3 | 4 | // TODO: once support for Go 1.16 is dropped, this file can be 5 | // merged/removed with assertion_compare_go1.17_test.go and 6 | // assertion_compare_legacy.go 7 | 8 | package assert 9 | 10 | import "reflect" 11 | 12 | // Wrapper around reflect.Value.CanConvert, for compatibility 13 | // reasons. 14 | func canConvert(value reflect.Value, to reflect.Type) bool { 15 | return value.CanConvert(to) 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go: -------------------------------------------------------------------------------- 1 | //go:build !go1.17 2 | // +build !go1.17 3 | 4 | // TODO: once support for Go 1.16 is dropped, this file can be 5 | // merged/removed with assertion_compare_go1.17_test.go and 6 | // assertion_compare_can_convert.go 7 | 8 | package assert 9 | 10 | import "reflect" 11 | 12 | // Older versions of Go does not have the reflect.Value.CanConvert 13 | // method. 14 | func canConvert(value reflect.Value, to reflect.Type) bool { 15 | return false 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentFormat}} 2 | func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { 3 | if h, ok := t.(tHelper); ok { h.Helper() } 4 | return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) 5 | } 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { 3 | if h, ok := a.t.(tHelper); ok { h.Helper() } 4 | return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 5 | } 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_order.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | // isOrdered checks that collection contains orderable elements. 9 | func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { 10 | objKind := reflect.TypeOf(object).Kind() 11 | if objKind != reflect.Slice && objKind != reflect.Array { 12 | return false 13 | } 14 | 15 | objValue := reflect.ValueOf(object) 16 | objLen := objValue.Len() 17 | 18 | if objLen <= 1 { 19 | return true 20 | } 21 | 22 | value := objValue.Index(0) 23 | valueInterface := value.Interface() 24 | firstValueKind := value.Kind() 25 | 26 | for i := 1; i < objLen; i++ { 27 | prevValue := value 28 | prevValueInterface := valueInterface 29 | 30 | value = objValue.Index(i) 31 | valueInterface = value.Interface() 32 | 33 | compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) 34 | 35 | if !isComparable { 36 | return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) 37 | } 38 | 39 | if !containsValue(allowedComparesResults, compareResult) { 40 | return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) 41 | } 42 | } 43 | 44 | return true 45 | } 46 | 47 | // IsIncreasing asserts that the collection is increasing 48 | // 49 | // assert.IsIncreasing(t, []int{1, 2, 3}) 50 | // assert.IsIncreasing(t, []float{1, 2}) 51 | // assert.IsIncreasing(t, []string{"a", "b"}) 52 | func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 53 | return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) 54 | } 55 | 56 | // IsNonIncreasing asserts that the collection is not increasing 57 | // 58 | // assert.IsNonIncreasing(t, []int{2, 1, 1}) 59 | // assert.IsNonIncreasing(t, []float{2, 1}) 60 | // assert.IsNonIncreasing(t, []string{"b", "a"}) 61 | func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 62 | return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) 63 | } 64 | 65 | // IsDecreasing asserts that the collection is decreasing 66 | // 67 | // assert.IsDecreasing(t, []int{2, 1, 0}) 68 | // assert.IsDecreasing(t, []float{2, 1}) 69 | // assert.IsDecreasing(t, []string{"b", "a"}) 70 | func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 71 | return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) 72 | } 73 | 74 | // IsNonDecreasing asserts that the collection is not decreasing 75 | // 76 | // assert.IsNonDecreasing(t, []int{1, 1, 2}) 77 | // assert.IsNonDecreasing(t, []float{1, 2}) 78 | // assert.IsNonDecreasing(t, []string{"a", "b"}) 79 | func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 80 | return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/doc.go: -------------------------------------------------------------------------------- 1 | // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. 2 | // 3 | // # Example Usage 4 | // 5 | // The following is a complete example using assert in a standard test function: 6 | // 7 | // import ( 8 | // "testing" 9 | // "github.com/stretchr/testify/assert" 10 | // ) 11 | // 12 | // func TestSomething(t *testing.T) { 13 | // 14 | // var a string = "Hello" 15 | // var b string = "Hello" 16 | // 17 | // assert.Equal(t, a, b, "The two words should be the same.") 18 | // 19 | // } 20 | // 21 | // if you assert many times, use the format below: 22 | // 23 | // import ( 24 | // "testing" 25 | // "github.com/stretchr/testify/assert" 26 | // ) 27 | // 28 | // func TestSomething(t *testing.T) { 29 | // assert := assert.New(t) 30 | // 31 | // var a string = "Hello" 32 | // var b string = "Hello" 33 | // 34 | // assert.Equal(a, b, "The two words should be the same.") 35 | // } 36 | // 37 | // # Assertions 38 | // 39 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package. 40 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the 41 | // testing framework. This allows the assertion funcs to write the failings and other details to 42 | // the correct place. 43 | // 44 | // Every assertion function also takes an optional string message as the final argument, 45 | // allowing custom error messages to be appended to the message the assertion method outputs. 46 | package assert 47 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/errors.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // AnError is an error instance useful for testing. If the code does not care 8 | // about error specifics, and only needs to return the error for example, this 9 | // error should be used to make the test code more readable. 10 | var AnError = errors.New("assert.AnError general error for testing") 11 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/forward_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/http_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "net/url" 8 | "strings" 9 | ) 10 | 11 | // httpCode is a helper that returns HTTP code of the response. It returns -1 and 12 | // an error if building a new request fails. 13 | func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { 14 | w := httptest.NewRecorder() 15 | req, err := http.NewRequest(method, url, nil) 16 | if err != nil { 17 | return -1, err 18 | } 19 | req.URL.RawQuery = values.Encode() 20 | handler(w, req) 21 | return w.Code, nil 22 | } 23 | 24 | // HTTPSuccess asserts that a specified handler returns a success status code. 25 | // 26 | // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) 27 | // 28 | // Returns whether the assertion was successful (true) or not (false). 29 | func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { 30 | if h, ok := t.(tHelper); ok { 31 | h.Helper() 32 | } 33 | code, err := httpCode(handler, method, url, values) 34 | if err != nil { 35 | Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) 36 | } 37 | 38 | isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent 39 | if !isSuccessCode { 40 | Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) 41 | } 42 | 43 | return isSuccessCode 44 | } 45 | 46 | // HTTPRedirect asserts that a specified handler returns a redirect status code. 47 | // 48 | // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} 49 | // 50 | // Returns whether the assertion was successful (true) or not (false). 51 | func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { 52 | if h, ok := t.(tHelper); ok { 53 | h.Helper() 54 | } 55 | code, err := httpCode(handler, method, url, values) 56 | if err != nil { 57 | Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) 58 | } 59 | 60 | isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect 61 | if !isRedirectCode { 62 | Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) 63 | } 64 | 65 | return isRedirectCode 66 | } 67 | 68 | // HTTPError asserts that a specified handler returns an error status code. 69 | // 70 | // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} 71 | // 72 | // Returns whether the assertion was successful (true) or not (false). 73 | func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { 74 | if h, ok := t.(tHelper); ok { 75 | h.Helper() 76 | } 77 | code, err := httpCode(handler, method, url, values) 78 | if err != nil { 79 | Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) 80 | } 81 | 82 | isErrorCode := code >= http.StatusBadRequest 83 | if !isErrorCode { 84 | Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) 85 | } 86 | 87 | return isErrorCode 88 | } 89 | 90 | // HTTPStatusCode asserts that a specified handler returns a specified status code. 91 | // 92 | // assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) 93 | // 94 | // Returns whether the assertion was successful (true) or not (false). 95 | func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { 96 | if h, ok := t.(tHelper); ok { 97 | h.Helper() 98 | } 99 | code, err := httpCode(handler, method, url, values) 100 | if err != nil { 101 | Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) 102 | } 103 | 104 | successful := code == statuscode 105 | if !successful { 106 | Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) 107 | } 108 | 109 | return successful 110 | } 111 | 112 | // HTTPBody is a helper that returns HTTP body of the response. It returns 113 | // empty string if building a new request fails. 114 | func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { 115 | w := httptest.NewRecorder() 116 | req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) 117 | if err != nil { 118 | return "" 119 | } 120 | handler(w, req) 121 | return w.Body.String() 122 | } 123 | 124 | // HTTPBodyContains asserts that a specified handler returns a 125 | // body that contains a string. 126 | // 127 | // assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") 128 | // 129 | // Returns whether the assertion was successful (true) or not (false). 130 | func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { 131 | if h, ok := t.(tHelper); ok { 132 | h.Helper() 133 | } 134 | body := HTTPBody(handler, method, url, values) 135 | 136 | contains := strings.Contains(body, fmt.Sprint(str)) 137 | if !contains { 138 | Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) 139 | } 140 | 141 | return contains 142 | } 143 | 144 | // HTTPBodyNotContains asserts that a specified handler returns a 145 | // body that does not contain a string. 146 | // 147 | // assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") 148 | // 149 | // Returns whether the assertion was successful (true) or not (false). 150 | func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { 151 | if h, ok := t.(tHelper); ok { 152 | h.Helper() 153 | } 154 | body := HTTPBody(handler, method, url, values) 155 | 156 | contains := strings.Contains(body, fmt.Sprint(str)) 157 | if contains { 158 | Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) 159 | } 160 | 161 | return !contains 162 | } 163 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/doc.go: -------------------------------------------------------------------------------- 1 | // Package require implements the same assertions as the `assert` package but 2 | // stops test execution when a test fails. 3 | // 4 | // # Example Usage 5 | // 6 | // The following is a complete example using require in a standard test function: 7 | // 8 | // import ( 9 | // "testing" 10 | // "github.com/stretchr/testify/require" 11 | // ) 12 | // 13 | // func TestSomething(t *testing.T) { 14 | // 15 | // var a string = "Hello" 16 | // var b string = "Hello" 17 | // 18 | // require.Equal(t, a, b, "The two words should be the same.") 19 | // 20 | // } 21 | // 22 | // # Assertions 23 | // 24 | // The `require` package have same global functions as in the `assert` package, 25 | // but instead of returning a boolean result they call `t.FailNow()`. 26 | // 27 | // Every assertion function also takes an optional string message as the final argument, 28 | // allowing custom error messages to be appended to the message the assertion method outputs. 29 | package require 30 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/forward_requirements.go: -------------------------------------------------------------------------------- 1 | package require 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs" 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/require.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.Comment}} 2 | func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { 3 | if h, ok := t.(tHelper); ok { h.Helper() } 4 | if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return } 5 | t.FailNow() 6 | } 7 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/require_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { 3 | if h, ok := a.t.(tHelper); ok { h.Helper() } 4 | {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 5 | } 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/requirements.go: -------------------------------------------------------------------------------- 1 | package require 2 | 3 | // TestingT is an interface wrapper around *testing.T 4 | type TestingT interface { 5 | Errorf(format string, args ...interface{}) 6 | FailNow() 7 | } 8 | 9 | type tHelper interface { 10 | Helper() 11 | } 12 | 13 | // ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful 14 | // for table driven tests. 15 | type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) 16 | 17 | // ValueAssertionFunc is a common function prototype when validating a single value. Can be useful 18 | // for table driven tests. 19 | type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) 20 | 21 | // BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful 22 | // for table driven tests. 23 | type BoolAssertionFunc func(TestingT, bool, ...interface{}) 24 | 25 | // ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful 26 | // for table driven tests. 27 | type ErrorAssertionFunc func(TestingT, error, ...interface{}) 28 | 29 | //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs" 30 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | This project is covered by two different licenses: MIT and Apache. 3 | 4 | #### MIT License #### 5 | 6 | The following files were ported to Go from C files of libyaml, and thus 7 | are still covered by their original MIT license, with the additional 8 | copyright staring in 2011 when the project was ported over: 9 | 10 | apic.go emitterc.go parserc.go readerc.go scannerc.go 11 | writerc.go yamlh.go yamlprivateh.go 12 | 13 | Copyright (c) 2006-2010 Kirill Simonov 14 | Copyright (c) 2006-2011 Kirill Simonov 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy of 17 | this software and associated documentation files (the "Software"), to deal in 18 | the Software without restriction, including without limitation the rights to 19 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 20 | of the Software, and to permit persons to whom the Software is furnished to do 21 | so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | ### Apache License ### 35 | 36 | All the remaining project files are covered by the Apache license: 37 | 38 | Copyright (c) 2011-2019 Canonical Ltd 39 | 40 | Licensed under the Apache License, Version 2.0 (the "License"); 41 | you may not use this file except in compliance with the License. 42 | You may obtain a copy of the License at 43 | 44 | http://www.apache.org/licenses/LICENSE-2.0 45 | 46 | Unless required by applicable law or agreed to in writing, software 47 | distributed under the License is distributed on an "AS IS" BASIS, 48 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 49 | See the License for the specific language governing permissions and 50 | limitations under the License. 51 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/README.md: -------------------------------------------------------------------------------- 1 | # YAML support for the Go language 2 | 3 | Introduction 4 | ------------ 5 | 6 | The yaml package enables Go programs to comfortably encode and decode YAML 7 | values. It was developed within [Canonical](https://www.canonical.com) as 8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a 9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) 10 | C library to parse and generate YAML data quickly and reliably. 11 | 12 | Compatibility 13 | ------------- 14 | 15 | The yaml package supports most of YAML 1.2, but preserves some behavior 16 | from 1.1 for backwards compatibility. 17 | 18 | Specifically, as of v3 of the yaml package: 19 | 20 | - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being 21 | decoded into a typed bool value. Otherwise they behave as a string. Booleans 22 | in YAML 1.2 are _true/false_ only. 23 | - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_ 24 | as specified in YAML 1.2, because most parsers still use the old format. 25 | Octals in the _0o777_ format are supported though, so new files work. 26 | - Does not support base-60 floats. These are gone from YAML 1.2, and were 27 | actually never supported by this package as it's clearly a poor choice. 28 | 29 | and offers backwards 30 | compatibility with YAML 1.1 in some cases. 31 | 1.2, including support for 32 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 33 | implemented, and base-60 floats from YAML 1.1 are purposefully not 34 | supported since they're a poor design and are gone in YAML 1.2. 35 | 36 | Installation and usage 37 | ---------------------- 38 | 39 | The import path for the package is *gopkg.in/yaml.v3*. 40 | 41 | To install it, run: 42 | 43 | go get gopkg.in/yaml.v3 44 | 45 | API documentation 46 | ----------------- 47 | 48 | If opened in a browser, the import path itself leads to the API documentation: 49 | 50 | - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) 51 | 52 | API stability 53 | ------------- 54 | 55 | The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). 56 | 57 | 58 | License 59 | ------- 60 | 61 | The yaml package is licensed under the MIT and Apache License 2.0 licenses. 62 | Please see the LICENSE file for details. 63 | 64 | 65 | Example 66 | ------- 67 | 68 | ```Go 69 | package main 70 | 71 | import ( 72 | "fmt" 73 | "log" 74 | 75 | "gopkg.in/yaml.v3" 76 | ) 77 | 78 | var data = ` 79 | a: Easy! 80 | b: 81 | c: 2 82 | d: [3, 4] 83 | ` 84 | 85 | // Note: struct fields must be public in order for unmarshal to 86 | // correctly populate the data. 87 | type T struct { 88 | A string 89 | B struct { 90 | RenamedC int `yaml:"c"` 91 | D []int `yaml:",flow"` 92 | } 93 | } 94 | 95 | func main() { 96 | t := T{} 97 | 98 | err := yaml.Unmarshal([]byte(data), &t) 99 | if err != nil { 100 | log.Fatalf("error: %v", err) 101 | } 102 | fmt.Printf("--- t:\n%v\n\n", t) 103 | 104 | d, err := yaml.Marshal(&t) 105 | if err != nil { 106 | log.Fatalf("error: %v", err) 107 | } 108 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 109 | 110 | m := make(map[interface{}]interface{}) 111 | 112 | err = yaml.Unmarshal([]byte(data), &m) 113 | if err != nil { 114 | log.Fatalf("error: %v", err) 115 | } 116 | fmt.Printf("--- m:\n%v\n\n", m) 117 | 118 | d, err = yaml.Marshal(&m) 119 | if err != nil { 120 | log.Fatalf("error: %v", err) 121 | } 122 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 123 | } 124 | ``` 125 | 126 | This example will generate the following output: 127 | 128 | ``` 129 | --- t: 130 | {Easy! {2 [3 4]}} 131 | 132 | --- t dump: 133 | a: Easy! 134 | b: 135 | c: 2 136 | d: [3, 4] 137 | 138 | 139 | --- m: 140 | map[a:Easy! b:map[c:2 d:[3 4]]] 141 | 142 | --- m dump: 143 | a: Easy! 144 | b: 145 | c: 2 146 | d: 147 | - 3 148 | - 4 149 | ``` 150 | 151 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/encode.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011-2019 Canonical Ltd 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | package yaml 17 | 18 | import ( 19 | "encoding" 20 | "fmt" 21 | "io" 22 | "reflect" 23 | "regexp" 24 | "sort" 25 | "strconv" 26 | "strings" 27 | "time" 28 | "unicode/utf8" 29 | ) 30 | 31 | type encoder struct { 32 | emitter yaml_emitter_t 33 | event yaml_event_t 34 | out []byte 35 | flow bool 36 | indent int 37 | doneInit bool 38 | } 39 | 40 | func newEncoder() *encoder { 41 | e := &encoder{} 42 | yaml_emitter_initialize(&e.emitter) 43 | yaml_emitter_set_output_string(&e.emitter, &e.out) 44 | yaml_emitter_set_unicode(&e.emitter, true) 45 | return e 46 | } 47 | 48 | func newEncoderWithWriter(w io.Writer) *encoder { 49 | e := &encoder{} 50 | yaml_emitter_initialize(&e.emitter) 51 | yaml_emitter_set_output_writer(&e.emitter, w) 52 | yaml_emitter_set_unicode(&e.emitter, true) 53 | return e 54 | } 55 | 56 | func (e *encoder) init() { 57 | if e.doneInit { 58 | return 59 | } 60 | if e.indent == 0 { 61 | e.indent = 4 62 | } 63 | e.emitter.best_indent = e.indent 64 | yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) 65 | e.emit() 66 | e.doneInit = true 67 | } 68 | 69 | func (e *encoder) finish() { 70 | e.emitter.open_ended = false 71 | yaml_stream_end_event_initialize(&e.event) 72 | e.emit() 73 | } 74 | 75 | func (e *encoder) destroy() { 76 | yaml_emitter_delete(&e.emitter) 77 | } 78 | 79 | func (e *encoder) emit() { 80 | // This will internally delete the e.event value. 81 | e.must(yaml_emitter_emit(&e.emitter, &e.event)) 82 | } 83 | 84 | func (e *encoder) must(ok bool) { 85 | if !ok { 86 | msg := e.emitter.problem 87 | if msg == "" { 88 | msg = "unknown problem generating YAML content" 89 | } 90 | failf("%s", msg) 91 | } 92 | } 93 | 94 | func (e *encoder) marshalDoc(tag string, in reflect.Value) { 95 | e.init() 96 | var node *Node 97 | if in.IsValid() { 98 | node, _ = in.Interface().(*Node) 99 | } 100 | if node != nil && node.Kind == DocumentNode { 101 | e.nodev(in) 102 | } else { 103 | yaml_document_start_event_initialize(&e.event, nil, nil, true) 104 | e.emit() 105 | e.marshal(tag, in) 106 | yaml_document_end_event_initialize(&e.event, true) 107 | e.emit() 108 | } 109 | } 110 | 111 | func (e *encoder) marshal(tag string, in reflect.Value) { 112 | tag = shortTag(tag) 113 | if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { 114 | e.nilv() 115 | return 116 | } 117 | iface := in.Interface() 118 | switch value := iface.(type) { 119 | case *Node: 120 | e.nodev(in) 121 | return 122 | case Node: 123 | if !in.CanAddr() { 124 | var n = reflect.New(in.Type()).Elem() 125 | n.Set(in) 126 | in = n 127 | } 128 | e.nodev(in.Addr()) 129 | return 130 | case time.Time: 131 | e.timev(tag, in) 132 | return 133 | case *time.Time: 134 | e.timev(tag, in.Elem()) 135 | return 136 | case time.Duration: 137 | e.stringv(tag, reflect.ValueOf(value.String())) 138 | return 139 | case Marshaler: 140 | v, err := value.MarshalYAML() 141 | if err != nil { 142 | fail(err) 143 | } 144 | if v == nil { 145 | e.nilv() 146 | return 147 | } 148 | e.marshal(tag, reflect.ValueOf(v)) 149 | return 150 | case encoding.TextMarshaler: 151 | text, err := value.MarshalText() 152 | if err != nil { 153 | fail(err) 154 | } 155 | in = reflect.ValueOf(string(text)) 156 | case nil: 157 | e.nilv() 158 | return 159 | } 160 | switch in.Kind() { 161 | case reflect.Interface: 162 | e.marshal(tag, in.Elem()) 163 | case reflect.Map: 164 | e.mapv(tag, in) 165 | case reflect.Ptr: 166 | e.marshal(tag, in.Elem()) 167 | case reflect.Struct: 168 | e.structv(tag, in) 169 | case reflect.Slice, reflect.Array: 170 | e.slicev(tag, in) 171 | case reflect.String: 172 | e.stringv(tag, in) 173 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 174 | e.intv(tag, in) 175 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 176 | e.uintv(tag, in) 177 | case reflect.Float32, reflect.Float64: 178 | e.floatv(tag, in) 179 | case reflect.Bool: 180 | e.boolv(tag, in) 181 | default: 182 | panic("cannot marshal type: " + in.Type().String()) 183 | } 184 | } 185 | 186 | func (e *encoder) mapv(tag string, in reflect.Value) { 187 | e.mappingv(tag, func() { 188 | keys := keyList(in.MapKeys()) 189 | sort.Sort(keys) 190 | for _, k := range keys { 191 | e.marshal("", k) 192 | e.marshal("", in.MapIndex(k)) 193 | } 194 | }) 195 | } 196 | 197 | func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { 198 | for _, num := range index { 199 | for { 200 | if v.Kind() == reflect.Ptr { 201 | if v.IsNil() { 202 | return reflect.Value{} 203 | } 204 | v = v.Elem() 205 | continue 206 | } 207 | break 208 | } 209 | v = v.Field(num) 210 | } 211 | return v 212 | } 213 | 214 | func (e *encoder) structv(tag string, in reflect.Value) { 215 | sinfo, err := getStructInfo(in.Type()) 216 | if err != nil { 217 | panic(err) 218 | } 219 | e.mappingv(tag, func() { 220 | for _, info := range sinfo.FieldsList { 221 | var value reflect.Value 222 | if info.Inline == nil { 223 | value = in.Field(info.Num) 224 | } else { 225 | value = e.fieldByIndex(in, info.Inline) 226 | if !value.IsValid() { 227 | continue 228 | } 229 | } 230 | if info.OmitEmpty && isZero(value) { 231 | continue 232 | } 233 | e.marshal("", reflect.ValueOf(info.Key)) 234 | e.flow = info.Flow 235 | e.marshal("", value) 236 | } 237 | if sinfo.InlineMap >= 0 { 238 | m := in.Field(sinfo.InlineMap) 239 | if m.Len() > 0 { 240 | e.flow = false 241 | keys := keyList(m.MapKeys()) 242 | sort.Sort(keys) 243 | for _, k := range keys { 244 | if _, found := sinfo.FieldsMap[k.String()]; found { 245 | panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) 246 | } 247 | e.marshal("", k) 248 | e.flow = false 249 | e.marshal("", m.MapIndex(k)) 250 | } 251 | } 252 | } 253 | }) 254 | } 255 | 256 | func (e *encoder) mappingv(tag string, f func()) { 257 | implicit := tag == "" 258 | style := yaml_BLOCK_MAPPING_STYLE 259 | if e.flow { 260 | e.flow = false 261 | style = yaml_FLOW_MAPPING_STYLE 262 | } 263 | yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) 264 | e.emit() 265 | f() 266 | yaml_mapping_end_event_initialize(&e.event) 267 | e.emit() 268 | } 269 | 270 | func (e *encoder) slicev(tag string, in reflect.Value) { 271 | implicit := tag == "" 272 | style := yaml_BLOCK_SEQUENCE_STYLE 273 | if e.flow { 274 | e.flow = false 275 | style = yaml_FLOW_SEQUENCE_STYLE 276 | } 277 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 278 | e.emit() 279 | n := in.Len() 280 | for i := 0; i < n; i++ { 281 | e.marshal("", in.Index(i)) 282 | } 283 | e.must(yaml_sequence_end_event_initialize(&e.event)) 284 | e.emit() 285 | } 286 | 287 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. 288 | // 289 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported 290 | // in YAML 1.2 and by this package, but these should be marshalled quoted for 291 | // the time being for compatibility with other parsers. 292 | func isBase60Float(s string) (result bool) { 293 | // Fast path. 294 | if s == "" { 295 | return false 296 | } 297 | c := s[0] 298 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { 299 | return false 300 | } 301 | // Do the full match. 302 | return base60float.MatchString(s) 303 | } 304 | 305 | // From http://yaml.org/type/float.html, except the regular expression there 306 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. 307 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) 308 | 309 | // isOldBool returns whether s is bool notation as defined in YAML 1.1. 310 | // 311 | // We continue to force strings that YAML 1.1 would interpret as booleans to be 312 | // rendered as quotes strings so that the marshalled output valid for YAML 1.1 313 | // parsing. 314 | func isOldBool(s string) (result bool) { 315 | switch s { 316 | case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", 317 | "n", "N", "no", "No", "NO", "off", "Off", "OFF": 318 | return true 319 | default: 320 | return false 321 | } 322 | } 323 | 324 | func (e *encoder) stringv(tag string, in reflect.Value) { 325 | var style yaml_scalar_style_t 326 | s := in.String() 327 | canUsePlain := true 328 | switch { 329 | case !utf8.ValidString(s): 330 | if tag == binaryTag { 331 | failf("explicitly tagged !!binary data must be base64-encoded") 332 | } 333 | if tag != "" { 334 | failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) 335 | } 336 | // It can't be encoded directly as YAML so use a binary tag 337 | // and encode it as base64. 338 | tag = binaryTag 339 | s = encodeBase64(s) 340 | case tag == "": 341 | // Check to see if it would resolve to a specific 342 | // tag when encoded unquoted. If it doesn't, 343 | // there's no need to quote it. 344 | rtag, _ := resolve("", s) 345 | canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) 346 | } 347 | // Note: it's possible for user code to emit invalid YAML 348 | // if they explicitly specify a tag and a string containing 349 | // text that's incompatible with that tag. 350 | switch { 351 | case strings.Contains(s, "\n"): 352 | if e.flow { 353 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 354 | } else { 355 | style = yaml_LITERAL_SCALAR_STYLE 356 | } 357 | case canUsePlain: 358 | style = yaml_PLAIN_SCALAR_STYLE 359 | default: 360 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 361 | } 362 | e.emitScalar(s, "", tag, style, nil, nil, nil, nil) 363 | } 364 | 365 | func (e *encoder) boolv(tag string, in reflect.Value) { 366 | var s string 367 | if in.Bool() { 368 | s = "true" 369 | } else { 370 | s = "false" 371 | } 372 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) 373 | } 374 | 375 | func (e *encoder) intv(tag string, in reflect.Value) { 376 | s := strconv.FormatInt(in.Int(), 10) 377 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) 378 | } 379 | 380 | func (e *encoder) uintv(tag string, in reflect.Value) { 381 | s := strconv.FormatUint(in.Uint(), 10) 382 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) 383 | } 384 | 385 | func (e *encoder) timev(tag string, in reflect.Value) { 386 | t := in.Interface().(time.Time) 387 | s := t.Format(time.RFC3339Nano) 388 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) 389 | } 390 | 391 | func (e *encoder) floatv(tag string, in reflect.Value) { 392 | // Issue #352: When formatting, use the precision of the underlying value 393 | precision := 64 394 | if in.Kind() == reflect.Float32 { 395 | precision = 32 396 | } 397 | 398 | s := strconv.FormatFloat(in.Float(), 'g', -1, precision) 399 | switch s { 400 | case "+Inf": 401 | s = ".inf" 402 | case "-Inf": 403 | s = "-.inf" 404 | case "NaN": 405 | s = ".nan" 406 | } 407 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) 408 | } 409 | 410 | func (e *encoder) nilv() { 411 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) 412 | } 413 | 414 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { 415 | // TODO Kill this function. Replace all initialize calls by their underlining Go literals. 416 | implicit := tag == "" 417 | if !implicit { 418 | tag = longTag(tag) 419 | } 420 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) 421 | e.event.head_comment = head 422 | e.event.line_comment = line 423 | e.event.foot_comment = foot 424 | e.event.tail_comment = tail 425 | e.emit() 426 | } 427 | 428 | func (e *encoder) nodev(in reflect.Value) { 429 | e.node(in.Interface().(*Node), "") 430 | } 431 | 432 | func (e *encoder) node(node *Node, tail string) { 433 | // Zero nodes behave as nil. 434 | if node.Kind == 0 && node.IsZero() { 435 | e.nilv() 436 | return 437 | } 438 | 439 | // If the tag was not explicitly requested, and dropping it won't change the 440 | // implicit tag of the value, don't include it in the presentation. 441 | var tag = node.Tag 442 | var stag = shortTag(tag) 443 | var forceQuoting bool 444 | if tag != "" && node.Style&TaggedStyle == 0 { 445 | if node.Kind == ScalarNode { 446 | if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { 447 | tag = "" 448 | } else { 449 | rtag, _ := resolve("", node.Value) 450 | if rtag == stag { 451 | tag = "" 452 | } else if stag == strTag { 453 | tag = "" 454 | forceQuoting = true 455 | } 456 | } 457 | } else { 458 | var rtag string 459 | switch node.Kind { 460 | case MappingNode: 461 | rtag = mapTag 462 | case SequenceNode: 463 | rtag = seqTag 464 | } 465 | if rtag == stag { 466 | tag = "" 467 | } 468 | } 469 | } 470 | 471 | switch node.Kind { 472 | case DocumentNode: 473 | yaml_document_start_event_initialize(&e.event, nil, nil, true) 474 | e.event.head_comment = []byte(node.HeadComment) 475 | e.emit() 476 | for _, node := range node.Content { 477 | e.node(node, "") 478 | } 479 | yaml_document_end_event_initialize(&e.event, true) 480 | e.event.foot_comment = []byte(node.FootComment) 481 | e.emit() 482 | 483 | case SequenceNode: 484 | style := yaml_BLOCK_SEQUENCE_STYLE 485 | if node.Style&FlowStyle != 0 { 486 | style = yaml_FLOW_SEQUENCE_STYLE 487 | } 488 | e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) 489 | e.event.head_comment = []byte(node.HeadComment) 490 | e.emit() 491 | for _, node := range node.Content { 492 | e.node(node, "") 493 | } 494 | e.must(yaml_sequence_end_event_initialize(&e.event)) 495 | e.event.line_comment = []byte(node.LineComment) 496 | e.event.foot_comment = []byte(node.FootComment) 497 | e.emit() 498 | 499 | case MappingNode: 500 | style := yaml_BLOCK_MAPPING_STYLE 501 | if node.Style&FlowStyle != 0 { 502 | style = yaml_FLOW_MAPPING_STYLE 503 | } 504 | yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) 505 | e.event.tail_comment = []byte(tail) 506 | e.event.head_comment = []byte(node.HeadComment) 507 | e.emit() 508 | 509 | // The tail logic below moves the foot comment of prior keys to the following key, 510 | // since the value for each key may be a nested structure and the foot needs to be 511 | // processed only the entirety of the value is streamed. The last tail is processed 512 | // with the mapping end event. 513 | var tail string 514 | for i := 0; i+1 < len(node.Content); i += 2 { 515 | k := node.Content[i] 516 | foot := k.FootComment 517 | if foot != "" { 518 | kopy := *k 519 | kopy.FootComment = "" 520 | k = &kopy 521 | } 522 | e.node(k, tail) 523 | tail = foot 524 | 525 | v := node.Content[i+1] 526 | e.node(v, "") 527 | } 528 | 529 | yaml_mapping_end_event_initialize(&e.event) 530 | e.event.tail_comment = []byte(tail) 531 | e.event.line_comment = []byte(node.LineComment) 532 | e.event.foot_comment = []byte(node.FootComment) 533 | e.emit() 534 | 535 | case AliasNode: 536 | yaml_alias_event_initialize(&e.event, []byte(node.Value)) 537 | e.event.head_comment = []byte(node.HeadComment) 538 | e.event.line_comment = []byte(node.LineComment) 539 | e.event.foot_comment = []byte(node.FootComment) 540 | e.emit() 541 | 542 | case ScalarNode: 543 | value := node.Value 544 | if !utf8.ValidString(value) { 545 | if stag == binaryTag { 546 | failf("explicitly tagged !!binary data must be base64-encoded") 547 | } 548 | if stag != "" { 549 | failf("cannot marshal invalid UTF-8 data as %s", stag) 550 | } 551 | // It can't be encoded directly as YAML so use a binary tag 552 | // and encode it as base64. 553 | tag = binaryTag 554 | value = encodeBase64(value) 555 | } 556 | 557 | style := yaml_PLAIN_SCALAR_STYLE 558 | switch { 559 | case node.Style&DoubleQuotedStyle != 0: 560 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 561 | case node.Style&SingleQuotedStyle != 0: 562 | style = yaml_SINGLE_QUOTED_SCALAR_STYLE 563 | case node.Style&LiteralStyle != 0: 564 | style = yaml_LITERAL_SCALAR_STYLE 565 | case node.Style&FoldedStyle != 0: 566 | style = yaml_FOLDED_SCALAR_STYLE 567 | case strings.Contains(value, "\n"): 568 | style = yaml_LITERAL_SCALAR_STYLE 569 | case forceQuoting: 570 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 571 | } 572 | 573 | e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) 574 | default: 575 | failf("cannot encode node with unknown kind %d", node.Kind) 576 | } 577 | } 578 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/readerc.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011-2019 Canonical Ltd 3 | // Copyright (c) 2006-2010 Kirill Simonov 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is furnished to do 10 | // so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | package yaml 24 | 25 | import ( 26 | "io" 27 | ) 28 | 29 | // Set the reader error and return 0. 30 | func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { 31 | parser.error = yaml_READER_ERROR 32 | parser.problem = problem 33 | parser.problem_offset = offset 34 | parser.problem_value = value 35 | return false 36 | } 37 | 38 | // Byte order marks. 39 | const ( 40 | bom_UTF8 = "\xef\xbb\xbf" 41 | bom_UTF16LE = "\xff\xfe" 42 | bom_UTF16BE = "\xfe\xff" 43 | ) 44 | 45 | // Determine the input stream encoding by checking the BOM symbol. If no BOM is 46 | // found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. 47 | func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { 48 | // Ensure that we had enough bytes in the raw buffer. 49 | for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { 50 | if !yaml_parser_update_raw_buffer(parser) { 51 | return false 52 | } 53 | } 54 | 55 | // Determine the encoding. 56 | buf := parser.raw_buffer 57 | pos := parser.raw_buffer_pos 58 | avail := len(buf) - pos 59 | if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { 60 | parser.encoding = yaml_UTF16LE_ENCODING 61 | parser.raw_buffer_pos += 2 62 | parser.offset += 2 63 | } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { 64 | parser.encoding = yaml_UTF16BE_ENCODING 65 | parser.raw_buffer_pos += 2 66 | parser.offset += 2 67 | } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { 68 | parser.encoding = yaml_UTF8_ENCODING 69 | parser.raw_buffer_pos += 3 70 | parser.offset += 3 71 | } else { 72 | parser.encoding = yaml_UTF8_ENCODING 73 | } 74 | return true 75 | } 76 | 77 | // Update the raw buffer. 78 | func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { 79 | size_read := 0 80 | 81 | // Return if the raw buffer is full. 82 | if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { 83 | return true 84 | } 85 | 86 | // Return on EOF. 87 | if parser.eof { 88 | return true 89 | } 90 | 91 | // Move the remaining bytes in the raw buffer to the beginning. 92 | if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { 93 | copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) 94 | } 95 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] 96 | parser.raw_buffer_pos = 0 97 | 98 | // Call the read handler to fill the buffer. 99 | size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) 100 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] 101 | if err == io.EOF { 102 | parser.eof = true 103 | } else if err != nil { 104 | return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) 105 | } 106 | return true 107 | } 108 | 109 | // Ensure that the buffer contains at least `length` characters. 110 | // Return true on success, false on failure. 111 | // 112 | // The length is supposed to be significantly less that the buffer size. 113 | func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { 114 | if parser.read_handler == nil { 115 | panic("read handler must be set") 116 | } 117 | 118 | // [Go] This function was changed to guarantee the requested length size at EOF. 119 | // The fact we need to do this is pretty awful, but the description above implies 120 | // for that to be the case, and there are tests 121 | 122 | // If the EOF flag is set and the raw buffer is empty, do nothing. 123 | if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { 124 | // [Go] ACTUALLY! Read the documentation of this function above. 125 | // This is just broken. To return true, we need to have the 126 | // given length in the buffer. Not doing that means every single 127 | // check that calls this function to make sure the buffer has a 128 | // given length is Go) panicking; or C) accessing invalid memory. 129 | //return true 130 | } 131 | 132 | // Return if the buffer contains enough characters. 133 | if parser.unread >= length { 134 | return true 135 | } 136 | 137 | // Determine the input encoding if it is not known yet. 138 | if parser.encoding == yaml_ANY_ENCODING { 139 | if !yaml_parser_determine_encoding(parser) { 140 | return false 141 | } 142 | } 143 | 144 | // Move the unread characters to the beginning of the buffer. 145 | buffer_len := len(parser.buffer) 146 | if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { 147 | copy(parser.buffer, parser.buffer[parser.buffer_pos:]) 148 | buffer_len -= parser.buffer_pos 149 | parser.buffer_pos = 0 150 | } else if parser.buffer_pos == buffer_len { 151 | buffer_len = 0 152 | parser.buffer_pos = 0 153 | } 154 | 155 | // Open the whole buffer for writing, and cut it before returning. 156 | parser.buffer = parser.buffer[:cap(parser.buffer)] 157 | 158 | // Fill the buffer until it has enough characters. 159 | first := true 160 | for parser.unread < length { 161 | 162 | // Fill the raw buffer if necessary. 163 | if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { 164 | if !yaml_parser_update_raw_buffer(parser) { 165 | parser.buffer = parser.buffer[:buffer_len] 166 | return false 167 | } 168 | } 169 | first = false 170 | 171 | // Decode the raw buffer. 172 | inner: 173 | for parser.raw_buffer_pos != len(parser.raw_buffer) { 174 | var value rune 175 | var width int 176 | 177 | raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos 178 | 179 | // Decode the next character. 180 | switch parser.encoding { 181 | case yaml_UTF8_ENCODING: 182 | // Decode a UTF-8 character. Check RFC 3629 183 | // (http://www.ietf.org/rfc/rfc3629.txt) for more details. 184 | // 185 | // The following table (taken from the RFC) is used for 186 | // decoding. 187 | // 188 | // Char. number range | UTF-8 octet sequence 189 | // (hexadecimal) | (binary) 190 | // --------------------+------------------------------------ 191 | // 0000 0000-0000 007F | 0xxxxxxx 192 | // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 193 | // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 194 | // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 195 | // 196 | // Additionally, the characters in the range 0xD800-0xDFFF 197 | // are prohibited as they are reserved for use with UTF-16 198 | // surrogate pairs. 199 | 200 | // Determine the length of the UTF-8 sequence. 201 | octet := parser.raw_buffer[parser.raw_buffer_pos] 202 | switch { 203 | case octet&0x80 == 0x00: 204 | width = 1 205 | case octet&0xE0 == 0xC0: 206 | width = 2 207 | case octet&0xF0 == 0xE0: 208 | width = 3 209 | case octet&0xF8 == 0xF0: 210 | width = 4 211 | default: 212 | // The leading octet is invalid. 213 | return yaml_parser_set_reader_error(parser, 214 | "invalid leading UTF-8 octet", 215 | parser.offset, int(octet)) 216 | } 217 | 218 | // Check if the raw buffer contains an incomplete character. 219 | if width > raw_unread { 220 | if parser.eof { 221 | return yaml_parser_set_reader_error(parser, 222 | "incomplete UTF-8 octet sequence", 223 | parser.offset, -1) 224 | } 225 | break inner 226 | } 227 | 228 | // Decode the leading octet. 229 | switch { 230 | case octet&0x80 == 0x00: 231 | value = rune(octet & 0x7F) 232 | case octet&0xE0 == 0xC0: 233 | value = rune(octet & 0x1F) 234 | case octet&0xF0 == 0xE0: 235 | value = rune(octet & 0x0F) 236 | case octet&0xF8 == 0xF0: 237 | value = rune(octet & 0x07) 238 | default: 239 | value = 0 240 | } 241 | 242 | // Check and decode the trailing octets. 243 | for k := 1; k < width; k++ { 244 | octet = parser.raw_buffer[parser.raw_buffer_pos+k] 245 | 246 | // Check if the octet is valid. 247 | if (octet & 0xC0) != 0x80 { 248 | return yaml_parser_set_reader_error(parser, 249 | "invalid trailing UTF-8 octet", 250 | parser.offset+k, int(octet)) 251 | } 252 | 253 | // Decode the octet. 254 | value = (value << 6) + rune(octet&0x3F) 255 | } 256 | 257 | // Check the length of the sequence against the value. 258 | switch { 259 | case width == 1: 260 | case width == 2 && value >= 0x80: 261 | case width == 3 && value >= 0x800: 262 | case width == 4 && value >= 0x10000: 263 | default: 264 | return yaml_parser_set_reader_error(parser, 265 | "invalid length of a UTF-8 sequence", 266 | parser.offset, -1) 267 | } 268 | 269 | // Check the range of the value. 270 | if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { 271 | return yaml_parser_set_reader_error(parser, 272 | "invalid Unicode character", 273 | parser.offset, int(value)) 274 | } 275 | 276 | case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: 277 | var low, high int 278 | if parser.encoding == yaml_UTF16LE_ENCODING { 279 | low, high = 0, 1 280 | } else { 281 | low, high = 1, 0 282 | } 283 | 284 | // The UTF-16 encoding is not as simple as one might 285 | // naively think. Check RFC 2781 286 | // (http://www.ietf.org/rfc/rfc2781.txt). 287 | // 288 | // Normally, two subsequent bytes describe a Unicode 289 | // character. However a special technique (called a 290 | // surrogate pair) is used for specifying character 291 | // values larger than 0xFFFF. 292 | // 293 | // A surrogate pair consists of two pseudo-characters: 294 | // high surrogate area (0xD800-0xDBFF) 295 | // low surrogate area (0xDC00-0xDFFF) 296 | // 297 | // The following formulas are used for decoding 298 | // and encoding characters using surrogate pairs: 299 | // 300 | // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) 301 | // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) 302 | // W1 = 110110yyyyyyyyyy 303 | // W2 = 110111xxxxxxxxxx 304 | // 305 | // where U is the character value, W1 is the high surrogate 306 | // area, W2 is the low surrogate area. 307 | 308 | // Check for incomplete UTF-16 character. 309 | if raw_unread < 2 { 310 | if parser.eof { 311 | return yaml_parser_set_reader_error(parser, 312 | "incomplete UTF-16 character", 313 | parser.offset, -1) 314 | } 315 | break inner 316 | } 317 | 318 | // Get the character. 319 | value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + 320 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) 321 | 322 | // Check for unexpected low surrogate area. 323 | if value&0xFC00 == 0xDC00 { 324 | return yaml_parser_set_reader_error(parser, 325 | "unexpected low surrogate area", 326 | parser.offset, int(value)) 327 | } 328 | 329 | // Check for a high surrogate area. 330 | if value&0xFC00 == 0xD800 { 331 | width = 4 332 | 333 | // Check for incomplete surrogate pair. 334 | if raw_unread < 4 { 335 | if parser.eof { 336 | return yaml_parser_set_reader_error(parser, 337 | "incomplete UTF-16 surrogate pair", 338 | parser.offset, -1) 339 | } 340 | break inner 341 | } 342 | 343 | // Get the next character. 344 | value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + 345 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) 346 | 347 | // Check for a low surrogate area. 348 | if value2&0xFC00 != 0xDC00 { 349 | return yaml_parser_set_reader_error(parser, 350 | "expected low surrogate area", 351 | parser.offset+2, int(value2)) 352 | } 353 | 354 | // Generate the value of the surrogate pair. 355 | value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) 356 | } else { 357 | width = 2 358 | } 359 | 360 | default: 361 | panic("impossible") 362 | } 363 | 364 | // Check if the character is in the allowed range: 365 | // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) 366 | // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) 367 | // | [#x10000-#x10FFFF] (32 bit) 368 | switch { 369 | case value == 0x09: 370 | case value == 0x0A: 371 | case value == 0x0D: 372 | case value >= 0x20 && value <= 0x7E: 373 | case value == 0x85: 374 | case value >= 0xA0 && value <= 0xD7FF: 375 | case value >= 0xE000 && value <= 0xFFFD: 376 | case value >= 0x10000 && value <= 0x10FFFF: 377 | default: 378 | return yaml_parser_set_reader_error(parser, 379 | "control characters are not allowed", 380 | parser.offset, int(value)) 381 | } 382 | 383 | // Move the raw pointers. 384 | parser.raw_buffer_pos += width 385 | parser.offset += width 386 | 387 | // Finally put the character into the buffer. 388 | if value <= 0x7F { 389 | // 0000 0000-0000 007F . 0xxxxxxx 390 | parser.buffer[buffer_len+0] = byte(value) 391 | buffer_len += 1 392 | } else if value <= 0x7FF { 393 | // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx 394 | parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) 395 | parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) 396 | buffer_len += 2 397 | } else if value <= 0xFFFF { 398 | // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx 399 | parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) 400 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) 401 | parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) 402 | buffer_len += 3 403 | } else { 404 | // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 405 | parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) 406 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) 407 | parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) 408 | parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) 409 | buffer_len += 4 410 | } 411 | 412 | parser.unread++ 413 | } 414 | 415 | // On EOF, put NUL into the buffer and return. 416 | if parser.eof { 417 | parser.buffer[buffer_len] = 0 418 | buffer_len++ 419 | parser.unread++ 420 | break 421 | } 422 | } 423 | // [Go] Read the documentation of this function above. To return true, 424 | // we need to have the given length in the buffer. Not doing that means 425 | // every single check that calls this function to make sure the buffer 426 | // has a given length is Go) panicking; or C) accessing invalid memory. 427 | // This happens here due to the EOF above breaking early. 428 | for buffer_len < length { 429 | parser.buffer[buffer_len] = 0 430 | buffer_len++ 431 | } 432 | parser.buffer = parser.buffer[:buffer_len] 433 | return true 434 | } 435 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/resolve.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011-2019 Canonical Ltd 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | package yaml 17 | 18 | import ( 19 | "encoding/base64" 20 | "math" 21 | "regexp" 22 | "strconv" 23 | "strings" 24 | "time" 25 | ) 26 | 27 | type resolveMapItem struct { 28 | value interface{} 29 | tag string 30 | } 31 | 32 | var resolveTable = make([]byte, 256) 33 | var resolveMap = make(map[string]resolveMapItem) 34 | 35 | func init() { 36 | t := resolveTable 37 | t[int('+')] = 'S' // Sign 38 | t[int('-')] = 'S' 39 | for _, c := range "0123456789" { 40 | t[int(c)] = 'D' // Digit 41 | } 42 | for _, c := range "yYnNtTfFoO~" { 43 | t[int(c)] = 'M' // In map 44 | } 45 | t[int('.')] = '.' // Float (potentially in map) 46 | 47 | var resolveMapList = []struct { 48 | v interface{} 49 | tag string 50 | l []string 51 | }{ 52 | {true, boolTag, []string{"true", "True", "TRUE"}}, 53 | {false, boolTag, []string{"false", "False", "FALSE"}}, 54 | {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, 55 | {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, 56 | {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, 57 | {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, 58 | {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, 59 | {"<<", mergeTag, []string{"<<"}}, 60 | } 61 | 62 | m := resolveMap 63 | for _, item := range resolveMapList { 64 | for _, s := range item.l { 65 | m[s] = resolveMapItem{item.v, item.tag} 66 | } 67 | } 68 | } 69 | 70 | const ( 71 | nullTag = "!!null" 72 | boolTag = "!!bool" 73 | strTag = "!!str" 74 | intTag = "!!int" 75 | floatTag = "!!float" 76 | timestampTag = "!!timestamp" 77 | seqTag = "!!seq" 78 | mapTag = "!!map" 79 | binaryTag = "!!binary" 80 | mergeTag = "!!merge" 81 | ) 82 | 83 | var longTags = make(map[string]string) 84 | var shortTags = make(map[string]string) 85 | 86 | func init() { 87 | for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { 88 | ltag := longTag(stag) 89 | longTags[stag] = ltag 90 | shortTags[ltag] = stag 91 | } 92 | } 93 | 94 | const longTagPrefix = "tag:yaml.org,2002:" 95 | 96 | func shortTag(tag string) string { 97 | if strings.HasPrefix(tag, longTagPrefix) { 98 | if stag, ok := shortTags[tag]; ok { 99 | return stag 100 | } 101 | return "!!" + tag[len(longTagPrefix):] 102 | } 103 | return tag 104 | } 105 | 106 | func longTag(tag string) string { 107 | if strings.HasPrefix(tag, "!!") { 108 | if ltag, ok := longTags[tag]; ok { 109 | return ltag 110 | } 111 | return longTagPrefix + tag[2:] 112 | } 113 | return tag 114 | } 115 | 116 | func resolvableTag(tag string) bool { 117 | switch tag { 118 | case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: 119 | return true 120 | } 121 | return false 122 | } 123 | 124 | var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) 125 | 126 | func resolve(tag string, in string) (rtag string, out interface{}) { 127 | tag = shortTag(tag) 128 | if !resolvableTag(tag) { 129 | return tag, in 130 | } 131 | 132 | defer func() { 133 | switch tag { 134 | case "", rtag, strTag, binaryTag: 135 | return 136 | case floatTag: 137 | if rtag == intTag { 138 | switch v := out.(type) { 139 | case int64: 140 | rtag = floatTag 141 | out = float64(v) 142 | return 143 | case int: 144 | rtag = floatTag 145 | out = float64(v) 146 | return 147 | } 148 | } 149 | } 150 | failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) 151 | }() 152 | 153 | // Any data is accepted as a !!str or !!binary. 154 | // Otherwise, the prefix is enough of a hint about what it might be. 155 | hint := byte('N') 156 | if in != "" { 157 | hint = resolveTable[in[0]] 158 | } 159 | if hint != 0 && tag != strTag && tag != binaryTag { 160 | // Handle things we can lookup in a map. 161 | if item, ok := resolveMap[in]; ok { 162 | return item.tag, item.value 163 | } 164 | 165 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 166 | // are purposefully unsupported here. They're still quoted on 167 | // the way out for compatibility with other parser, though. 168 | 169 | switch hint { 170 | case 'M': 171 | // We've already checked the map above. 172 | 173 | case '.': 174 | // Not in the map, so maybe a normal float. 175 | floatv, err := strconv.ParseFloat(in, 64) 176 | if err == nil { 177 | return floatTag, floatv 178 | } 179 | 180 | case 'D', 'S': 181 | // Int, float, or timestamp. 182 | // Only try values as a timestamp if the value is unquoted or there's an explicit 183 | // !!timestamp tag. 184 | if tag == "" || tag == timestampTag { 185 | t, ok := parseTimestamp(in) 186 | if ok { 187 | return timestampTag, t 188 | } 189 | } 190 | 191 | plain := strings.Replace(in, "_", "", -1) 192 | intv, err := strconv.ParseInt(plain, 0, 64) 193 | if err == nil { 194 | if intv == int64(int(intv)) { 195 | return intTag, int(intv) 196 | } else { 197 | return intTag, intv 198 | } 199 | } 200 | uintv, err := strconv.ParseUint(plain, 0, 64) 201 | if err == nil { 202 | return intTag, uintv 203 | } 204 | if yamlStyleFloat.MatchString(plain) { 205 | floatv, err := strconv.ParseFloat(plain, 64) 206 | if err == nil { 207 | return floatTag, floatv 208 | } 209 | } 210 | if strings.HasPrefix(plain, "0b") { 211 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 212 | if err == nil { 213 | if intv == int64(int(intv)) { 214 | return intTag, int(intv) 215 | } else { 216 | return intTag, intv 217 | } 218 | } 219 | uintv, err := strconv.ParseUint(plain[2:], 2, 64) 220 | if err == nil { 221 | return intTag, uintv 222 | } 223 | } else if strings.HasPrefix(plain, "-0b") { 224 | intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) 225 | if err == nil { 226 | if true || intv == int64(int(intv)) { 227 | return intTag, int(intv) 228 | } else { 229 | return intTag, intv 230 | } 231 | } 232 | } 233 | // Octals as introduced in version 1.2 of the spec. 234 | // Octals from the 1.1 spec, spelled as 0777, are still 235 | // decoded by default in v3 as well for compatibility. 236 | // May be dropped in v4 depending on how usage evolves. 237 | if strings.HasPrefix(plain, "0o") { 238 | intv, err := strconv.ParseInt(plain[2:], 8, 64) 239 | if err == nil { 240 | if intv == int64(int(intv)) { 241 | return intTag, int(intv) 242 | } else { 243 | return intTag, intv 244 | } 245 | } 246 | uintv, err := strconv.ParseUint(plain[2:], 8, 64) 247 | if err == nil { 248 | return intTag, uintv 249 | } 250 | } else if strings.HasPrefix(plain, "-0o") { 251 | intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) 252 | if err == nil { 253 | if true || intv == int64(int(intv)) { 254 | return intTag, int(intv) 255 | } else { 256 | return intTag, intv 257 | } 258 | } 259 | } 260 | default: 261 | panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") 262 | } 263 | } 264 | return strTag, in 265 | } 266 | 267 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 268 | // as appropriate for the resulting length. 269 | func encodeBase64(s string) string { 270 | const lineLen = 70 271 | encLen := base64.StdEncoding.EncodedLen(len(s)) 272 | lines := encLen/lineLen + 1 273 | buf := make([]byte, encLen*2+lines) 274 | in := buf[0:encLen] 275 | out := buf[encLen:] 276 | base64.StdEncoding.Encode(in, []byte(s)) 277 | k := 0 278 | for i := 0; i < len(in); i += lineLen { 279 | j := i + lineLen 280 | if j > len(in) { 281 | j = len(in) 282 | } 283 | k += copy(out[k:], in[i:j]) 284 | if lines > 1 { 285 | out[k] = '\n' 286 | k++ 287 | } 288 | } 289 | return string(out[:k]) 290 | } 291 | 292 | // This is a subset of the formats allowed by the regular expression 293 | // defined at http://yaml.org/type/timestamp.html. 294 | var allowedTimestampFormats = []string{ 295 | "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. 296 | "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". 297 | "2006-1-2 15:4:5.999999999", // space separated with no time zone 298 | "2006-1-2", // date only 299 | // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" 300 | // from the set of examples. 301 | } 302 | 303 | // parseTimestamp parses s as a timestamp string and 304 | // returns the timestamp and reports whether it succeeded. 305 | // Timestamp formats are defined at http://yaml.org/type/timestamp.html 306 | func parseTimestamp(s string) (time.Time, bool) { 307 | // TODO write code to check all the formats supported by 308 | // http://yaml.org/type/timestamp.html instead of using time.Parse. 309 | 310 | // Quick check: all date formats start with YYYY-. 311 | i := 0 312 | for ; i < len(s); i++ { 313 | if c := s[i]; c < '0' || c > '9' { 314 | break 315 | } 316 | } 317 | if i != 4 || i == len(s) || s[i] != '-' { 318 | return time.Time{}, false 319 | } 320 | for _, format := range allowedTimestampFormats { 321 | if t, err := time.Parse(format, s); err == nil { 322 | return t, true 323 | } 324 | } 325 | return time.Time{}, false 326 | } 327 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/sorter.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011-2019 Canonical Ltd 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | package yaml 17 | 18 | import ( 19 | "reflect" 20 | "unicode" 21 | ) 22 | 23 | type keyList []reflect.Value 24 | 25 | func (l keyList) Len() int { return len(l) } 26 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 27 | func (l keyList) Less(i, j int) bool { 28 | a := l[i] 29 | b := l[j] 30 | ak := a.Kind() 31 | bk := b.Kind() 32 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 33 | a = a.Elem() 34 | ak = a.Kind() 35 | } 36 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 37 | b = b.Elem() 38 | bk = b.Kind() 39 | } 40 | af, aok := keyFloat(a) 41 | bf, bok := keyFloat(b) 42 | if aok && bok { 43 | if af != bf { 44 | return af < bf 45 | } 46 | if ak != bk { 47 | return ak < bk 48 | } 49 | return numLess(a, b) 50 | } 51 | if ak != reflect.String || bk != reflect.String { 52 | return ak < bk 53 | } 54 | ar, br := []rune(a.String()), []rune(b.String()) 55 | digits := false 56 | for i := 0; i < len(ar) && i < len(br); i++ { 57 | if ar[i] == br[i] { 58 | digits = unicode.IsDigit(ar[i]) 59 | continue 60 | } 61 | al := unicode.IsLetter(ar[i]) 62 | bl := unicode.IsLetter(br[i]) 63 | if al && bl { 64 | return ar[i] < br[i] 65 | } 66 | if al || bl { 67 | if digits { 68 | return al 69 | } else { 70 | return bl 71 | } 72 | } 73 | var ai, bi int 74 | var an, bn int64 75 | if ar[i] == '0' || br[i] == '0' { 76 | for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { 77 | if ar[j] != '0' { 78 | an = 1 79 | bn = 1 80 | break 81 | } 82 | } 83 | } 84 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 85 | an = an*10 + int64(ar[ai]-'0') 86 | } 87 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 88 | bn = bn*10 + int64(br[bi]-'0') 89 | } 90 | if an != bn { 91 | return an < bn 92 | } 93 | if ai != bi { 94 | return ai < bi 95 | } 96 | return ar[i] < br[i] 97 | } 98 | return len(ar) < len(br) 99 | } 100 | 101 | // keyFloat returns a float value for v if it is a number/bool 102 | // and whether it is a number/bool or not. 103 | func keyFloat(v reflect.Value) (f float64, ok bool) { 104 | switch v.Kind() { 105 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 106 | return float64(v.Int()), true 107 | case reflect.Float32, reflect.Float64: 108 | return v.Float(), true 109 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 110 | return float64(v.Uint()), true 111 | case reflect.Bool: 112 | if v.Bool() { 113 | return 1, true 114 | } 115 | return 0, true 116 | } 117 | return 0, false 118 | } 119 | 120 | // numLess returns whether a < b. 121 | // a and b must necessarily have the same kind. 122 | func numLess(a, b reflect.Value) bool { 123 | switch a.Kind() { 124 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 125 | return a.Int() < b.Int() 126 | case reflect.Float32, reflect.Float64: 127 | return a.Float() < b.Float() 128 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 129 | return a.Uint() < b.Uint() 130 | case reflect.Bool: 131 | return !a.Bool() && b.Bool() 132 | } 133 | panic("not a number") 134 | } 135 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/writerc.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011-2019 Canonical Ltd 3 | // Copyright (c) 2006-2010 Kirill Simonov 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is furnished to do 10 | // so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | package yaml 24 | 25 | // Set the writer error and return false. 26 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 27 | emitter.error = yaml_WRITER_ERROR 28 | emitter.problem = problem 29 | return false 30 | } 31 | 32 | // Flush the output buffer. 33 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 34 | if emitter.write_handler == nil { 35 | panic("write handler not set") 36 | } 37 | 38 | // Check if the buffer is empty. 39 | if emitter.buffer_pos == 0 { 40 | return true 41 | } 42 | 43 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 44 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 45 | } 46 | emitter.buffer_pos = 0 47 | return true 48 | } 49 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v3/yamlprivateh.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011-2019 Canonical Ltd 3 | // Copyright (c) 2006-2010 Kirill Simonov 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files (the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | // of the Software, and to permit persons to whom the Software is furnished to do 10 | // so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | package yaml 24 | 25 | const ( 26 | // The size of the input raw buffer. 27 | input_raw_buffer_size = 512 28 | 29 | // The size of the input buffer. 30 | // It should be possible to decode the whole raw buffer. 31 | input_buffer_size = input_raw_buffer_size * 3 32 | 33 | // The size of the output buffer. 34 | output_buffer_size = 128 35 | 36 | // The size of the output raw buffer. 37 | // It should be possible to encode the whole output buffer. 38 | output_raw_buffer_size = (output_buffer_size*2 + 2) 39 | 40 | // The size of other stacks and queues. 41 | initial_stack_size = 16 42 | initial_queue_size = 16 43 | initial_string_size = 16 44 | ) 45 | 46 | // Check if the character at the specified position is an alphabetical 47 | // character, a digit, '_', or '-'. 48 | func is_alpha(b []byte, i int) bool { 49 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' 50 | } 51 | 52 | // Check if the character at the specified position is a digit. 53 | func is_digit(b []byte, i int) bool { 54 | return b[i] >= '0' && b[i] <= '9' 55 | } 56 | 57 | // Get the value of a digit. 58 | func as_digit(b []byte, i int) int { 59 | return int(b[i]) - '0' 60 | } 61 | 62 | // Check if the character at the specified position is a hex-digit. 63 | func is_hex(b []byte, i int) bool { 64 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' 65 | } 66 | 67 | // Get the value of a hex-digit. 68 | func as_hex(b []byte, i int) int { 69 | bi := b[i] 70 | if bi >= 'A' && bi <= 'F' { 71 | return int(bi) - 'A' + 10 72 | } 73 | if bi >= 'a' && bi <= 'f' { 74 | return int(bi) - 'a' + 10 75 | } 76 | return int(bi) - '0' 77 | } 78 | 79 | // Check if the character is ASCII. 80 | func is_ascii(b []byte, i int) bool { 81 | return b[i] <= 0x7F 82 | } 83 | 84 | // Check if the character at the start of the buffer can be printed unescaped. 85 | func is_printable(b []byte, i int) bool { 86 | return ((b[i] == 0x0A) || // . == #x0A 87 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E 88 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF 89 | (b[i] > 0xC2 && b[i] < 0xED) || 90 | (b[i] == 0xED && b[i+1] < 0xA0) || 91 | (b[i] == 0xEE) || 92 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD 93 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF 94 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) 95 | } 96 | 97 | // Check if the character at the specified position is NUL. 98 | func is_z(b []byte, i int) bool { 99 | return b[i] == 0x00 100 | } 101 | 102 | // Check if the beginning of the buffer is a BOM. 103 | func is_bom(b []byte, i int) bool { 104 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF 105 | } 106 | 107 | // Check if the character at the specified position is space. 108 | func is_space(b []byte, i int) bool { 109 | return b[i] == ' ' 110 | } 111 | 112 | // Check if the character at the specified position is tab. 113 | func is_tab(b []byte, i int) bool { 114 | return b[i] == '\t' 115 | } 116 | 117 | // Check if the character at the specified position is blank (space or tab). 118 | func is_blank(b []byte, i int) bool { 119 | //return is_space(b, i) || is_tab(b, i) 120 | return b[i] == ' ' || b[i] == '\t' 121 | } 122 | 123 | // Check if the character at the specified position is a line break. 124 | func is_break(b []byte, i int) bool { 125 | return (b[i] == '\r' || // CR (#xD) 126 | b[i] == '\n' || // LF (#xA) 127 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 128 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 129 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) 130 | } 131 | 132 | func is_crlf(b []byte, i int) bool { 133 | return b[i] == '\r' && b[i+1] == '\n' 134 | } 135 | 136 | // Check if the character is a line break or NUL. 137 | func is_breakz(b []byte, i int) bool { 138 | //return is_break(b, i) || is_z(b, i) 139 | return ( 140 | // is_break: 141 | b[i] == '\r' || // CR (#xD) 142 | b[i] == '\n' || // LF (#xA) 143 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 144 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 145 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 146 | // is_z: 147 | b[i] == 0) 148 | } 149 | 150 | // Check if the character is a line break, space, or NUL. 151 | func is_spacez(b []byte, i int) bool { 152 | //return is_space(b, i) || is_breakz(b, i) 153 | return ( 154 | // is_space: 155 | b[i] == ' ' || 156 | // is_breakz: 157 | b[i] == '\r' || // CR (#xD) 158 | b[i] == '\n' || // LF (#xA) 159 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 160 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 161 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 162 | b[i] == 0) 163 | } 164 | 165 | // Check if the character is a line break, space, tab, or NUL. 166 | func is_blankz(b []byte, i int) bool { 167 | //return is_blank(b, i) || is_breakz(b, i) 168 | return ( 169 | // is_blank: 170 | b[i] == ' ' || b[i] == '\t' || 171 | // is_breakz: 172 | b[i] == '\r' || // CR (#xD) 173 | b[i] == '\n' || // LF (#xA) 174 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 175 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 176 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 177 | b[i] == 0) 178 | } 179 | 180 | // Determine the width of the character. 181 | func width(b byte) int { 182 | // Don't replace these by a switch without first 183 | // confirming that it is being inlined. 184 | if b&0x80 == 0x00 { 185 | return 1 186 | } 187 | if b&0xE0 == 0xC0 { 188 | return 2 189 | } 190 | if b&0xF0 == 0xE0 { 191 | return 3 192 | } 193 | if b&0xF8 == 0xF0 { 194 | return 4 195 | } 196 | return 0 197 | 198 | } 199 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/davecgh/go-spew v1.1.1 2 | ## explicit 3 | github.com/davecgh/go-spew/spew 4 | # github.com/pmezard/go-difflib v1.0.0 5 | ## explicit 6 | github.com/pmezard/go-difflib/difflib 7 | # github.com/stretchr/testify v1.8.4 8 | ## explicit; go 1.20 9 | github.com/stretchr/testify/assert 10 | github.com/stretchr/testify/require 11 | # gopkg.in/yaml.v3 v3.0.1 12 | ## explicit 13 | gopkg.in/yaml.v3 14 | --------------------------------------------------------------------------------