├── .gitignore ├── Gopkg.lock ├── Gopkg.toml ├── Makefile ├── README.md ├── cmd └── main.go ├── examples ├── basic.yml ├── client-opts.yml ├── dynamic.yml ├── env.yml ├── get.yml ├── post.yml └── query.yml ├── pkg ├── dispatcher │ └── dispatcher.go ├── parser │ ├── parser.go │ ├── parser_test.go │ ├── request.go │ └── request_test.go └── template │ └── funcs.go ├── scripts ├── install.sh └── release.sh ├── vendor └── gopkg.in │ └── yaml.v2 │ ├── .travis.yml │ ├── LICENSE │ ├── LICENSE.libyaml │ ├── NOTICE │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── decode_test.go │ ├── emitterc.go │ ├── encode.go │ ├── encode_test.go │ ├── example_embedded_test.go │ ├── go.mod │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── suite_test.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── wercker.yml /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | name = "gopkg.in/yaml.v2" 6 | packages = ["."] 7 | revision = "7f97868eec74b32b0982dd158a51a446d1da7eb5" 8 | version = "v2.1.1" 9 | 10 | [solve-meta] 11 | analyzer-name = "dep" 12 | analyzer-version = 1 13 | inputs-digest = "bbb168ed7f43b40cf4f75a1bccce6a8f8f9755d21b499eafd1bbe8f92fe1420b" 14 | solver-name = "gps-cdcl" 15 | solver-version = 1 16 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | 2 | # Gopkg.toml example 3 | # 4 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 5 | # for detailed Gopkg.toml documentation. 6 | # 7 | # required = ["github.com/user/thing/cmd/thing"] 8 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 9 | # 10 | # [[constraint]] 11 | # name = "github.com/user/project" 12 | # version = "1.0.0" 13 | # 14 | # [[constraint]] 15 | # name = "github.com/user/project2" 16 | # branch = "dev" 17 | # source = "github.com/myfork/project2" 18 | # 19 | # [[override]] 20 | # name = "github.com/x/y" 21 | # version = "2.4.0" 22 | 23 | 24 | [[constraint]] 25 | name = "gopkg.in/yaml.v2" 26 | version = "2.1.1" 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: clean build 2 | 3 | .PHONY: run 4 | run: 5 | @go run cmd/main.go examples/get.yml 6 | 7 | .PHONY: clean 8 | clean: 9 | rm -rf dist 10 | 11 | .PHONY: test 12 | test: 13 | go test ./... 14 | 15 | .PHONY: build 16 | build: 17 | go build -i -v -ldflags="-X main.version=$(git describe --always --dirty)" -o dist/relay cmd/main.go 18 | 19 | release: 20 | @./scripts/release.sh 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Relay 2 | 3 | [![wercker status](https://app.wercker.com/status/c209eca6ce0c52f92ca6ad091fa89117/s/master "wercker status")](https://app.wercker.com/project/byKey/c209eca6ce0c52f92ca6ad091fa89117) 4 | 5 | Relay lets you write HTTP requests as easy to read, structured YAML and dispatch them easily using a CLI. 6 | 7 | The motivation for this library is to have a Postman like tool for sharing HTTP reqests in a team. Relay lets you treat HTTP requests as human readable data files and store them in version control with your project. 8 | 9 | Relay provides a CLI for executing the request only and no GUI. 10 | 11 | ## Quickstart 12 | 13 | Download the relevant binary from [here](https://github.com/owainlewis/relay/releases). Add to your path i.e /usr/local/bin 14 | 15 | ## Examples 16 | 17 | Relay HTTP requests are defined as YAML with a simple structure. See the examples folder for more ideas. 18 | 19 | A request definition can contain the following 20 | 21 | | Field | Required | Description | 22 | |---------|----------|-------------------------------------------------| 23 | | url | Yes | The full URL including protocol | 24 | | method | Yes | HTTP method as uppercase | 25 | | body | No | Optional HTTP request body | 26 | | query | No | Optional key value query params appended to URL | 27 | | headers | No | Key value HTTP headers | 28 | | | | | 29 | 30 | Here are some simple examples 31 | 32 | #### Get request 33 | 34 | This is the most basic HTTP request with only a method and URL defined. 35 | 36 | ```yaml 37 | description: A simple GET request 38 | request: 39 | method: GET 40 | url: https://requestb.in/1ead0f91 41 | ``` 42 | 43 | Dispatch this request from the CLI as follows 44 | 45 | ``` 46 | relay examples/get.yml 47 | ``` 48 | 49 | #### Post request 50 | 51 | ```yaml 52 | description: A simple POST request with body 53 | request: 54 | method: POST 55 | url: https://requestb.in/1ead0f91 56 | body: 'Hello, World!' 57 | ``` 58 | 59 | #### Get request with query params and HTTP headers 60 | 61 | ```yaml 62 | request: 63 | method: GET 64 | url: https://httpbin.org/get 65 | query: 66 | foo: bar 67 | baz: qux 68 | headers: 69 | Content-Type: application/json 70 | Authorization: Bearer {{env "AUTH_TOKEN"}} 71 | ``` 72 | 73 | #### Custom variables 74 | 75 | Many times you will want to inject values into the templates. For example dynamic URLs like GET /foo/:id etc. 76 | 77 | You can use a `-params 'a=b c=d'` flag format in the CLI. Here is an example of passing in custom variables 78 | 79 | ```yaml 80 | description: Example using injected values via params 81 | request: 82 | method: GET 83 | url: https://api.mysite.com/users/{{.id}} 84 | headers: 85 | Content-Type: application/json 86 | Authorization: Bearer {{.authToken}} 87 | ``` 88 | 89 | Now we can dispatch it using the CLI 90 | 91 | ``` 92 | relay examples/dynamic.yaml -params 'id=1 authToken=XXX' 93 | ``` 94 | 95 | ## Functions 96 | 97 | A selection of functions are provided to make life easier 98 | 99 | ### Environment variables 100 | 101 | The `env` function will extract an environment variable. 102 | 103 | If the environment variable is not defined then an empty string is returned. 104 | 105 | ```yaml 106 | description: A simple request example that makes use of environment vars 107 | request: 108 | method: GET 109 | url: https://httpbin.org/get 110 | headers: 111 | Content-Type: application/json 112 | Authorization: Bearer {{env "AUTH_TOKEN"}} 113 | ``` 114 | 115 | ### Basic Auth 116 | 117 | ```yaml 118 | description: A request with HTTP Basic Auth 119 | request: 120 | method: GET 121 | url: https://requestb.in/1ead0f91 122 | headers: 123 | Authorization: Basic {{basic "USER" "PASS"}} 124 | ``` 125 | 126 | ### Basic 64 Encoding 127 | 128 | Use `b64encode` 129 | 130 | ## Advanced (Timeouts etc) 131 | 132 | You can set an explicit HTTP request timeout as in the following examples: 133 | 134 | ```yaml 135 | description: A request with explicit request timeouts 136 | request: 137 | method: GET 138 | url: https://requestb.in/1ead0f91 139 | options: 140 | timeout: 20 141 | ``` 142 | 143 | ## Roadmap 144 | 145 | + CLI option for casting request to CURL request 146 | + Support for proxies 147 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "strings" 9 | 10 | "github.com/owainlewis/relay/pkg/dispatcher" 11 | "github.com/owainlewis/relay/pkg/parser" 12 | ) 13 | 14 | var version = "" 15 | 16 | func parseParams(input string) (map[string]string, error) { 17 | params := make(map[string]string) 18 | parts := strings.Fields(input) 19 | for _, pair := range parts { 20 | kv := strings.Split(pair, "=") 21 | if len(kv) == 2 { 22 | k := kv[0] 23 | v := kv[1] 24 | params[k] = v 25 | } 26 | } 27 | return params, nil 28 | } 29 | 30 | func extractParamsFromArgs(args []string) (map[string]string, error) { 31 | var parameters string 32 | flagSet := flag.NewFlagSet("Request params", flag.ExitOnError) 33 | flagSet.StringVar(¶meters, "params", "", "Request params") 34 | flagSet.Parse(args[1:]) 35 | 36 | requestParams, err := parseParams(parameters) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | return requestParams, nil 42 | } 43 | 44 | func getRequestFromFile(filename string, params map[string]string) (*parser.RequestItem, error) { 45 | return parser.ParseFile(filename, params) 46 | } 47 | 48 | func run(filename string, params map[string]string) error { 49 | requestItem, err := getRequestFromFile(filename, params) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | response, err := dispatcher.Run(requestItem) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | body, err := ioutil.ReadAll(response.Body) 60 | if err != nil { 61 | return err 62 | } 63 | 64 | fmt.Printf("Response: %#v\n", response) 65 | fmt.Println(string(body)) 66 | 67 | return nil 68 | } 69 | 70 | func handleRun(args []string) { 71 | if len(args) == 0 { 72 | fmt.Println("Missing file for run command") 73 | os.Exit(1) 74 | } 75 | 76 | file := args[0] 77 | 78 | requestParams, err := extractParamsFromArgs(args) 79 | if err != nil { 80 | fmt.Println("Failed to parse request params", err) 81 | os.Exit(1) 82 | } 83 | 84 | ok := run(file, requestParams) == nil 85 | if !ok { 86 | fmt.Println("Failed to execute run command", err) 87 | } 88 | } 89 | 90 | func main() { 91 | handleRun(os.Args[1:]) 92 | } 93 | -------------------------------------------------------------------------------- /examples/basic.yml: -------------------------------------------------------------------------------- 1 | description: A request with HTTP Basic Auth 2 | request: 3 | method: GET 4 | url: https://requestb.in/1ead0f91 5 | headers: 6 | Authorization: Basic {{basic "USER" "PASS"}} 7 | -------------------------------------------------------------------------------- /examples/client-opts.yml: -------------------------------------------------------------------------------- 1 | description: A request with explicit timeouts 2 | request: 3 | method: GET 4 | url: https://requestb.in/1ead0f91 5 | options: 6 | timeout: 20 7 | -------------------------------------------------------------------------------- /examples/dynamic.yml: -------------------------------------------------------------------------------- 1 | description: Example using injected values via params 2 | request: 3 | method: GET 4 | url: https://requestb.in/1ead0f91 5 | headers: 6 | Content-Type: application/json 7 | Authorization: Bearer {{.authToken}} 8 | -------------------------------------------------------------------------------- /examples/env.yml: -------------------------------------------------------------------------------- 1 | description: A simple request example that makes use of environment vars 2 | request: 3 | method: GET 4 | url: https://httpbin.org/get 5 | headers: 6 | Content-Type: application/json 7 | Authorization: Bearer {{env "AUTH_TOKEN"}} 8 | -------------------------------------------------------------------------------- /examples/get.yml: -------------------------------------------------------------------------------- 1 | description: A simple GET request example 2 | request: 3 | method: GET 4 | url: https://httpbin.org/get 5 | -------------------------------------------------------------------------------- /examples/post.yml: -------------------------------------------------------------------------------- 1 | description: A simple POST request with body 2 | request: 3 | method: POST 4 | url: https://requestb.in/1ead0f91 5 | body: 'Hello, World!' 6 | -------------------------------------------------------------------------------- /examples/query.yml: -------------------------------------------------------------------------------- 1 | description: A request with query params 2 | request: 3 | method: GET 4 | url: https://httpbin.org/get 5 | query: 6 | page: 1 7 | limit: 10 8 | headers: 9 | Content-Type: application/json 10 | -------------------------------------------------------------------------------- /pkg/dispatcher/dispatcher.go: -------------------------------------------------------------------------------- 1 | package dispatcher 2 | 3 | import ( 4 | "bytes" 5 | "net/http" 6 | "strings" 7 | "time" 8 | 9 | "github.com/owainlewis/relay/pkg/parser" 10 | ) 11 | 12 | func toHTTPRequest(request parser.Request) (*http.Request, error) { 13 | body := bytes.NewBuffer([]byte(request.Body)) 14 | 15 | r, err := http.NewRequest(strings.ToUpper(request.Method), request.URL, body) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | // Add HTTP headers to the request 21 | for k, v := range request.Headers { 22 | r.Header.Set(k, v) 23 | } 24 | 25 | // Add query params to the request 26 | if len(request.Query) > 0 { 27 | q := r.URL.Query() 28 | for k, v := range request.Query { 29 | q.Add(k, v) 30 | } 31 | r.URL.RawQuery = q.Encode() 32 | } 33 | 34 | return r, nil 35 | } 36 | 37 | // Run will execute a request item 38 | func Run(request *parser.RequestItem) (*http.Response, error) { 39 | var client = &http.Client{ 40 | Timeout: time.Second * 10, 41 | } 42 | 43 | httpRequest, err := toHTTPRequest(request.Request) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | return client.Do(httpRequest) 49 | } 50 | -------------------------------------------------------------------------------- /pkg/parser/parser.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "io/ioutil" 5 | 6 | "github.com/owainlewis/relay/pkg/template" 7 | "gopkg.in/yaml.v2" 8 | ) 9 | 10 | // Parse will turn a raw byte array into a RequestItem 11 | func Parse(data []byte) (*RequestItem, error) { 12 | defaultClientOptions := Options{Timeout: 10} 13 | var req = &RequestItem{Options: defaultClientOptions} 14 | 15 | err := yaml.Unmarshal(data, req) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | return req, nil 21 | } 22 | 23 | // ParseFile will a file returning a RequestItem. We also do template interpolation at this stage 24 | func ParseFile(file string, params map[string]string) (*RequestItem, error) { 25 | contents, err := ioutil.ReadFile(file) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | expanded, err := template.Expand(string(contents), params) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | return Parse(expanded) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/parser/parser_test.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestParserGet(t *testing.T) { 8 | params := map[string]string{"method": "get"} 9 | _, err := ParseFile("../../examples/get.yml", params) 10 | if err != nil { 11 | t.Error("Cannot parse file get.yaml") 12 | } 13 | } 14 | 15 | func TestDefaultOptions(t *testing.T) { 16 | params := map[string]string{"method": "get"} 17 | req, _ := ParseFile("../../examples/client-opts.yml", params) 18 | if req.Options.Timeout != 20 { 19 | t.Error("Expecting timeout value of 20 seconds for HTTP client options") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pkg/parser/request.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | const defaultRequestTimeout = 10 4 | 5 | // NewRequestItem will construct a new Request item with defaults 6 | func NewRequestItem() RequestItem { 7 | defaultClientOptions := Options{Timeout: defaultRequestTimeout} 8 | return RequestItem{Options: defaultClientOptions} 9 | } 10 | 11 | // RequestItem defines the structure of a request yaml item 12 | type RequestItem struct { 13 | Description string `yaml:"description"` 14 | Request Request `yaml:"request"` 15 | // Custom options for the HTTP request client i.e timeouts etc 16 | Options Options `yaml:"options"` 17 | } 18 | 19 | // Options defines the custom options for dispatching a request 20 | type Options struct { 21 | Timeout int `yaml:"timeout"` 22 | } 23 | 24 | // Request describes the structure of a Request as YAML 25 | type Request struct { 26 | // The HTTP method in uppercase 27 | Method string `yaml:"method"` 28 | // The full URL including protocol etc 29 | URL string `yaml:"url"` 30 | // HTTP headers 31 | Headers map[string]string `yaml:"headers"` 32 | // Query string params ?foo=bar 33 | Query map[string]string `yaml:"query"` 34 | // HTTP request body 35 | Body string `yaml:"body"` 36 | } 37 | 38 | // Validate will ensure that a user defined request is valid 39 | func (r Request) Validate() []error { 40 | var errs []error 41 | return errs 42 | } 43 | 44 | func requestMethodValid(method string) bool { 45 | methods := []string{"GET", "POST", "DELETE", "PUT", "PATCH"} 46 | for _, m := range methods { 47 | if method == m { 48 | return true 49 | } 50 | } 51 | return false 52 | } 53 | -------------------------------------------------------------------------------- /pkg/parser/request_test.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import "testing" 4 | 5 | func TestValidateRequestMethod(t *testing.T) { 6 | methods := []string{"GET", "POST", "PUT", "PATCH"} 7 | for _, m := range methods { 8 | if !requestMethodValid(m) { 9 | t.Error(m + " should be a valid request method") 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pkg/template/funcs.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "os" 7 | "text/template" 8 | ) 9 | 10 | func envFn(envVar string) (string, error) { 11 | return os.Getenv(envVar), nil 12 | } 13 | 14 | func basicAuthFn(username string, password string) (string, error) { 15 | auth := username + ":" + password 16 | return base64.StdEncoding.EncodeToString([]byte(auth)), nil 17 | } 18 | 19 | func base64Fn(input string) (string, error) { 20 | return base64.StdEncoding.EncodeToString([]byte(input)), nil 21 | } 22 | 23 | var funcMap = template.FuncMap{ 24 | "env": envFn, 25 | "basic": basicAuthFn, 26 | "base64encode": base64Fn, 27 | } 28 | 29 | // Expand will expand out any user defined functions in a template 30 | func Expand(input string, params map[string]string) ([]byte, error) { 31 | tmpl := template.New("request-template").Funcs(funcMap) 32 | 33 | t, err := tmpl.Parse(input) 34 | if err != nil { 35 | return []byte{}, err 36 | } 37 | 38 | var buffer bytes.Buffer 39 | if err := t.Execute(&buffer, params); err != nil { 40 | return []byte{}, err 41 | } 42 | 43 | return buffer.Bytes(), nil 44 | } 45 | -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | RELEASE=0.1 2 | 3 | wget https://github.com/owainlewis/relay/releases/download/$RELEASE/relay 4 | 5 | mv relay /usr/local/bin/ 6 | -------------------------------------------------------------------------------- /scripts/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Release script 6 | # Install github-release => go get github.com/aktau/github-release 7 | 8 | RELEASE=0.1.0 9 | 10 | USERNAME=owainlewis 11 | REPO=relay 12 | 13 | if git rev-parse "$RELEASE" >/dev/null 2>&1; then 14 | echo "Tag $RELEASE already exists. Doing nothing"; 15 | else 16 | echo "Creating new release $RELEASE" 17 | git tag -a "$RELEASE" -m "Relase version: $RELEASE" 18 | git push --tags 19 | github-release release \ 20 | --user $USERNAME \ 21 | --repo $REPO \ 22 | --tag $RELEASE \ 23 | --name "$RELEASE" \ 24 | --description "Release version $RELEASE" \ 25 | --pre-release 26 | 27 | github-release upload \ 28 | --user $USERNAME \ 29 | --repo $REPO \ 30 | --tag $RELEASE \ 31 | --name "relay" \ 32 | --file dist/relay 33 | fi 34 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | - 1.5 6 | - 1.6 7 | - 1.7 8 | - 1.8 9 | - 1.9 10 | - tip 11 | 12 | go_import_path: gopkg.in/yaml.v2 13 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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.v2/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.1 and 1.2, including support for 16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 17 | implemented, and base-60 floats from YAML 1.1 are purposefully not 18 | supported since they're a poor design and are gone in YAML 1.2. 19 | 20 | Installation and usage 21 | ---------------------- 22 | 23 | The import path for the package is *gopkg.in/yaml.v2*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v2 28 | 29 | API documentation 30 | ----------------- 31 | 32 | If opened in a browser, the import path itself leads to the API documentation: 33 | 34 | * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). 40 | 41 | 42 | License 43 | ------- 44 | 45 | The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. 46 | 47 | 48 | Example 49 | ------- 50 | 51 | Some more examples can be found in the "examples" folder. 52 | 53 | ```Go 54 | package main 55 | 56 | import ( 57 | "fmt" 58 | "log" 59 | 60 | "gopkg.in/yaml.v2" 61 | ) 62 | 63 | var data = ` 64 | a: Easy! 65 | b: 66 | c: 2 67 | d: [3, 4] 68 | ` 69 | 70 | // Note: struct fields must be public in order for unmarshal to 71 | // correctly populate the data. 72 | type T struct { 73 | A string 74 | B struct { 75 | RenamedC int `yaml:"c"` 76 | D []int `yaml:",flow"` 77 | } 78 | } 79 | 80 | func main() { 81 | t := T{} 82 | 83 | err := yaml.Unmarshal([]byte(data), &t) 84 | if err != nil { 85 | log.Fatalf("error: %v", err) 86 | } 87 | fmt.Printf("--- t:\n%v\n\n", t) 88 | 89 | d, err := yaml.Marshal(&t) 90 | if err != nil { 91 | log.Fatalf("error: %v", err) 92 | } 93 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 94 | 95 | m := make(map[interface{}]interface{}) 96 | 97 | err = yaml.Unmarshal([]byte(data), &m) 98 | if err != nil { 99 | log.Fatalf("error: %v", err) 100 | } 101 | fmt.Printf("--- m:\n%v\n\n", m) 102 | 103 | d, err = yaml.Marshal(&m) 104 | if err != nil { 105 | log.Fatalf("error: %v", err) 106 | } 107 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 108 | } 109 | ``` 110 | 111 | This example will generate the following output: 112 | 113 | ``` 114 | --- t: 115 | {Easy! {2 [3 4]}} 116 | 117 | --- t dump: 118 | a: Easy! 119 | b: 120 | c: 2 121 | d: [3, 4] 122 | 123 | 124 | --- m: 125 | map[a:Easy! b:map[c:2 d:[3 4]]] 126 | 127 | --- m dump: 128 | a: Easy! 129 | b: 130 | c: 2 131 | d: 132 | - 3 133 | - 4 134 | ``` 135 | 136 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/apic.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { 8 | //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) 9 | 10 | // Check if we can move the queue at the beginning of the buffer. 11 | if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { 12 | if parser.tokens_head != len(parser.tokens) { 13 | copy(parser.tokens, parser.tokens[parser.tokens_head:]) 14 | } 15 | parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] 16 | parser.tokens_head = 0 17 | } 18 | parser.tokens = append(parser.tokens, *token) 19 | if pos < 0 { 20 | return 21 | } 22 | copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) 23 | parser.tokens[parser.tokens_head+pos] = *token 24 | } 25 | 26 | // Create a new parser object. 27 | func yaml_parser_initialize(parser *yaml_parser_t) bool { 28 | *parser = yaml_parser_t{ 29 | raw_buffer: make([]byte, 0, input_raw_buffer_size), 30 | buffer: make([]byte, 0, input_buffer_size), 31 | } 32 | return true 33 | } 34 | 35 | // Destroy a parser object. 36 | func yaml_parser_delete(parser *yaml_parser_t) { 37 | *parser = yaml_parser_t{} 38 | } 39 | 40 | // String read handler. 41 | func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { 42 | if parser.input_pos == len(parser.input) { 43 | return 0, io.EOF 44 | } 45 | n = copy(buffer, parser.input[parser.input_pos:]) 46 | parser.input_pos += n 47 | return n, nil 48 | } 49 | 50 | // Reader read handler. 51 | func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { 52 | return parser.input_reader.Read(buffer) 53 | } 54 | 55 | // Set a string input. 56 | func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { 57 | if parser.read_handler != nil { 58 | panic("must set the input source only once") 59 | } 60 | parser.read_handler = yaml_string_read_handler 61 | parser.input = input 62 | parser.input_pos = 0 63 | } 64 | 65 | // Set a file input. 66 | func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { 67 | if parser.read_handler != nil { 68 | panic("must set the input source only once") 69 | } 70 | parser.read_handler = yaml_reader_read_handler 71 | parser.input_reader = r 72 | } 73 | 74 | // Set the source encoding. 75 | func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { 76 | if parser.encoding != yaml_ANY_ENCODING { 77 | panic("must set the encoding only once") 78 | } 79 | parser.encoding = encoding 80 | } 81 | 82 | // Create a new emitter object. 83 | func yaml_emitter_initialize(emitter *yaml_emitter_t) { 84 | *emitter = yaml_emitter_t{ 85 | buffer: make([]byte, output_buffer_size), 86 | raw_buffer: make([]byte, 0, output_raw_buffer_size), 87 | states: make([]yaml_emitter_state_t, 0, initial_stack_size), 88 | events: make([]yaml_event_t, 0, initial_queue_size), 89 | } 90 | } 91 | 92 | // Destroy an emitter object. 93 | func yaml_emitter_delete(emitter *yaml_emitter_t) { 94 | *emitter = yaml_emitter_t{} 95 | } 96 | 97 | // String write handler. 98 | func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { 99 | *emitter.output_buffer = append(*emitter.output_buffer, buffer...) 100 | return nil 101 | } 102 | 103 | // yaml_writer_write_handler uses emitter.output_writer to write the 104 | // emitted text. 105 | func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { 106 | _, err := emitter.output_writer.Write(buffer) 107 | return err 108 | } 109 | 110 | // Set a string output. 111 | func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { 112 | if emitter.write_handler != nil { 113 | panic("must set the output target only once") 114 | } 115 | emitter.write_handler = yaml_string_write_handler 116 | emitter.output_buffer = output_buffer 117 | } 118 | 119 | // Set a file output. 120 | func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { 121 | if emitter.write_handler != nil { 122 | panic("must set the output target only once") 123 | } 124 | emitter.write_handler = yaml_writer_write_handler 125 | emitter.output_writer = w 126 | } 127 | 128 | // Set the output encoding. 129 | func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { 130 | if emitter.encoding != yaml_ANY_ENCODING { 131 | panic("must set the output encoding only once") 132 | } 133 | emitter.encoding = encoding 134 | } 135 | 136 | // Set the canonical output style. 137 | func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { 138 | emitter.canonical = canonical 139 | } 140 | 141 | //// Set the indentation increment. 142 | func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { 143 | if indent < 2 || indent > 9 { 144 | indent = 2 145 | } 146 | emitter.best_indent = indent 147 | } 148 | 149 | // Set the preferred line width. 150 | func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { 151 | if width < 0 { 152 | width = -1 153 | } 154 | emitter.best_width = width 155 | } 156 | 157 | // Set if unescaped non-ASCII characters are allowed. 158 | func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { 159 | emitter.unicode = unicode 160 | } 161 | 162 | // Set the preferred line break character. 163 | func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { 164 | emitter.line_break = line_break 165 | } 166 | 167 | ///* 168 | // * Destroy a token object. 169 | // */ 170 | // 171 | //YAML_DECLARE(void) 172 | //yaml_token_delete(yaml_token_t *token) 173 | //{ 174 | // assert(token); // Non-NULL token object expected. 175 | // 176 | // switch (token.type) 177 | // { 178 | // case YAML_TAG_DIRECTIVE_TOKEN: 179 | // yaml_free(token.data.tag_directive.handle); 180 | // yaml_free(token.data.tag_directive.prefix); 181 | // break; 182 | // 183 | // case YAML_ALIAS_TOKEN: 184 | // yaml_free(token.data.alias.value); 185 | // break; 186 | // 187 | // case YAML_ANCHOR_TOKEN: 188 | // yaml_free(token.data.anchor.value); 189 | // break; 190 | // 191 | // case YAML_TAG_TOKEN: 192 | // yaml_free(token.data.tag.handle); 193 | // yaml_free(token.data.tag.suffix); 194 | // break; 195 | // 196 | // case YAML_SCALAR_TOKEN: 197 | // yaml_free(token.data.scalar.value); 198 | // break; 199 | // 200 | // default: 201 | // break; 202 | // } 203 | // 204 | // memset(token, 0, sizeof(yaml_token_t)); 205 | //} 206 | // 207 | ///* 208 | // * Check if a string is a valid UTF-8 sequence. 209 | // * 210 | // * Check 'reader.c' for more details on UTF-8 encoding. 211 | // */ 212 | // 213 | //static int 214 | //yaml_check_utf8(yaml_char_t *start, size_t length) 215 | //{ 216 | // yaml_char_t *end = start+length; 217 | // yaml_char_t *pointer = start; 218 | // 219 | // while (pointer < end) { 220 | // unsigned char octet; 221 | // unsigned int width; 222 | // unsigned int value; 223 | // size_t k; 224 | // 225 | // octet = pointer[0]; 226 | // width = (octet & 0x80) == 0x00 ? 1 : 227 | // (octet & 0xE0) == 0xC0 ? 2 : 228 | // (octet & 0xF0) == 0xE0 ? 3 : 229 | // (octet & 0xF8) == 0xF0 ? 4 : 0; 230 | // value = (octet & 0x80) == 0x00 ? octet & 0x7F : 231 | // (octet & 0xE0) == 0xC0 ? octet & 0x1F : 232 | // (octet & 0xF0) == 0xE0 ? octet & 0x0F : 233 | // (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; 234 | // if (!width) return 0; 235 | // if (pointer+width > end) return 0; 236 | // for (k = 1; k < width; k ++) { 237 | // octet = pointer[k]; 238 | // if ((octet & 0xC0) != 0x80) return 0; 239 | // value = (value << 6) + (octet & 0x3F); 240 | // } 241 | // if (!((width == 1) || 242 | // (width == 2 && value >= 0x80) || 243 | // (width == 3 && value >= 0x800) || 244 | // (width == 4 && value >= 0x10000))) return 0; 245 | // 246 | // pointer += width; 247 | // } 248 | // 249 | // return 1; 250 | //} 251 | // 252 | 253 | // Create STREAM-START. 254 | func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { 255 | *event = yaml_event_t{ 256 | typ: yaml_STREAM_START_EVENT, 257 | encoding: encoding, 258 | } 259 | } 260 | 261 | // Create STREAM-END. 262 | func yaml_stream_end_event_initialize(event *yaml_event_t) { 263 | *event = yaml_event_t{ 264 | typ: yaml_STREAM_END_EVENT, 265 | } 266 | } 267 | 268 | // Create DOCUMENT-START. 269 | func yaml_document_start_event_initialize( 270 | event *yaml_event_t, 271 | version_directive *yaml_version_directive_t, 272 | tag_directives []yaml_tag_directive_t, 273 | implicit bool, 274 | ) { 275 | *event = yaml_event_t{ 276 | typ: yaml_DOCUMENT_START_EVENT, 277 | version_directive: version_directive, 278 | tag_directives: tag_directives, 279 | implicit: implicit, 280 | } 281 | } 282 | 283 | // Create DOCUMENT-END. 284 | func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { 285 | *event = yaml_event_t{ 286 | typ: yaml_DOCUMENT_END_EVENT, 287 | implicit: implicit, 288 | } 289 | } 290 | 291 | ///* 292 | // * Create ALIAS. 293 | // */ 294 | // 295 | //YAML_DECLARE(int) 296 | //yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t) 297 | //{ 298 | // mark yaml_mark_t = { 0, 0, 0 } 299 | // anchor_copy *yaml_char_t = NULL 300 | // 301 | // assert(event) // Non-NULL event object is expected. 302 | // assert(anchor) // Non-NULL anchor is expected. 303 | // 304 | // if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0 305 | // 306 | // anchor_copy = yaml_strdup(anchor) 307 | // if (!anchor_copy) 308 | // return 0 309 | // 310 | // ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark) 311 | // 312 | // return 1 313 | //} 314 | 315 | // Create SCALAR. 316 | func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { 317 | *event = yaml_event_t{ 318 | typ: yaml_SCALAR_EVENT, 319 | anchor: anchor, 320 | tag: tag, 321 | value: value, 322 | implicit: plain_implicit, 323 | quoted_implicit: quoted_implicit, 324 | style: yaml_style_t(style), 325 | } 326 | return true 327 | } 328 | 329 | // Create SEQUENCE-START. 330 | func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { 331 | *event = yaml_event_t{ 332 | typ: yaml_SEQUENCE_START_EVENT, 333 | anchor: anchor, 334 | tag: tag, 335 | implicit: implicit, 336 | style: yaml_style_t(style), 337 | } 338 | return true 339 | } 340 | 341 | // Create SEQUENCE-END. 342 | func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { 343 | *event = yaml_event_t{ 344 | typ: yaml_SEQUENCE_END_EVENT, 345 | } 346 | return true 347 | } 348 | 349 | // Create MAPPING-START. 350 | func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { 351 | *event = yaml_event_t{ 352 | typ: yaml_MAPPING_START_EVENT, 353 | anchor: anchor, 354 | tag: tag, 355 | implicit: implicit, 356 | style: yaml_style_t(style), 357 | } 358 | } 359 | 360 | // Create MAPPING-END. 361 | func yaml_mapping_end_event_initialize(event *yaml_event_t) { 362 | *event = yaml_event_t{ 363 | typ: yaml_MAPPING_END_EVENT, 364 | } 365 | } 366 | 367 | // Destroy an event object. 368 | func yaml_event_delete(event *yaml_event_t) { 369 | *event = yaml_event_t{} 370 | } 371 | 372 | ///* 373 | // * Create a document object. 374 | // */ 375 | // 376 | //YAML_DECLARE(int) 377 | //yaml_document_initialize(document *yaml_document_t, 378 | // version_directive *yaml_version_directive_t, 379 | // tag_directives_start *yaml_tag_directive_t, 380 | // tag_directives_end *yaml_tag_directive_t, 381 | // start_implicit int, end_implicit int) 382 | //{ 383 | // struct { 384 | // error yaml_error_type_t 385 | // } context 386 | // struct { 387 | // start *yaml_node_t 388 | // end *yaml_node_t 389 | // top *yaml_node_t 390 | // } nodes = { NULL, NULL, NULL } 391 | // version_directive_copy *yaml_version_directive_t = NULL 392 | // struct { 393 | // start *yaml_tag_directive_t 394 | // end *yaml_tag_directive_t 395 | // top *yaml_tag_directive_t 396 | // } tag_directives_copy = { NULL, NULL, NULL } 397 | // value yaml_tag_directive_t = { NULL, NULL } 398 | // mark yaml_mark_t = { 0, 0, 0 } 399 | // 400 | // assert(document) // Non-NULL document object is expected. 401 | // assert((tag_directives_start && tag_directives_end) || 402 | // (tag_directives_start == tag_directives_end)) 403 | // // Valid tag directives are expected. 404 | // 405 | // if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error 406 | // 407 | // if (version_directive) { 408 | // version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) 409 | // if (!version_directive_copy) goto error 410 | // version_directive_copy.major = version_directive.major 411 | // version_directive_copy.minor = version_directive.minor 412 | // } 413 | // 414 | // if (tag_directives_start != tag_directives_end) { 415 | // tag_directive *yaml_tag_directive_t 416 | // if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) 417 | // goto error 418 | // for (tag_directive = tag_directives_start 419 | // tag_directive != tag_directives_end; tag_directive ++) { 420 | // assert(tag_directive.handle) 421 | // assert(tag_directive.prefix) 422 | // if (!yaml_check_utf8(tag_directive.handle, 423 | // strlen((char *)tag_directive.handle))) 424 | // goto error 425 | // if (!yaml_check_utf8(tag_directive.prefix, 426 | // strlen((char *)tag_directive.prefix))) 427 | // goto error 428 | // value.handle = yaml_strdup(tag_directive.handle) 429 | // value.prefix = yaml_strdup(tag_directive.prefix) 430 | // if (!value.handle || !value.prefix) goto error 431 | // if (!PUSH(&context, tag_directives_copy, value)) 432 | // goto error 433 | // value.handle = NULL 434 | // value.prefix = NULL 435 | // } 436 | // } 437 | // 438 | // DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, 439 | // tag_directives_copy.start, tag_directives_copy.top, 440 | // start_implicit, end_implicit, mark, mark) 441 | // 442 | // return 1 443 | // 444 | //error: 445 | // STACK_DEL(&context, nodes) 446 | // yaml_free(version_directive_copy) 447 | // while (!STACK_EMPTY(&context, tag_directives_copy)) { 448 | // value yaml_tag_directive_t = POP(&context, tag_directives_copy) 449 | // yaml_free(value.handle) 450 | // yaml_free(value.prefix) 451 | // } 452 | // STACK_DEL(&context, tag_directives_copy) 453 | // yaml_free(value.handle) 454 | // yaml_free(value.prefix) 455 | // 456 | // return 0 457 | //} 458 | // 459 | ///* 460 | // * Destroy a document object. 461 | // */ 462 | // 463 | //YAML_DECLARE(void) 464 | //yaml_document_delete(document *yaml_document_t) 465 | //{ 466 | // struct { 467 | // error yaml_error_type_t 468 | // } context 469 | // tag_directive *yaml_tag_directive_t 470 | // 471 | // context.error = YAML_NO_ERROR // Eliminate a compliler warning. 472 | // 473 | // assert(document) // Non-NULL document object is expected. 474 | // 475 | // while (!STACK_EMPTY(&context, document.nodes)) { 476 | // node yaml_node_t = POP(&context, document.nodes) 477 | // yaml_free(node.tag) 478 | // switch (node.type) { 479 | // case YAML_SCALAR_NODE: 480 | // yaml_free(node.data.scalar.value) 481 | // break 482 | // case YAML_SEQUENCE_NODE: 483 | // STACK_DEL(&context, node.data.sequence.items) 484 | // break 485 | // case YAML_MAPPING_NODE: 486 | // STACK_DEL(&context, node.data.mapping.pairs) 487 | // break 488 | // default: 489 | // assert(0) // Should not happen. 490 | // } 491 | // } 492 | // STACK_DEL(&context, document.nodes) 493 | // 494 | // yaml_free(document.version_directive) 495 | // for (tag_directive = document.tag_directives.start 496 | // tag_directive != document.tag_directives.end 497 | // tag_directive++) { 498 | // yaml_free(tag_directive.handle) 499 | // yaml_free(tag_directive.prefix) 500 | // } 501 | // yaml_free(document.tag_directives.start) 502 | // 503 | // memset(document, 0, sizeof(yaml_document_t)) 504 | //} 505 | // 506 | ///** 507 | // * Get a document node. 508 | // */ 509 | // 510 | //YAML_DECLARE(yaml_node_t *) 511 | //yaml_document_get_node(document *yaml_document_t, index int) 512 | //{ 513 | // assert(document) // Non-NULL document object is expected. 514 | // 515 | // if (index > 0 && document.nodes.start + index <= document.nodes.top) { 516 | // return document.nodes.start + index - 1 517 | // } 518 | // return NULL 519 | //} 520 | // 521 | ///** 522 | // * Get the root object. 523 | // */ 524 | // 525 | //YAML_DECLARE(yaml_node_t *) 526 | //yaml_document_get_root_node(document *yaml_document_t) 527 | //{ 528 | // assert(document) // Non-NULL document object is expected. 529 | // 530 | // if (document.nodes.top != document.nodes.start) { 531 | // return document.nodes.start 532 | // } 533 | // return NULL 534 | //} 535 | // 536 | ///* 537 | // * Add a scalar node to a document. 538 | // */ 539 | // 540 | //YAML_DECLARE(int) 541 | //yaml_document_add_scalar(document *yaml_document_t, 542 | // tag *yaml_char_t, value *yaml_char_t, length int, 543 | // style yaml_scalar_style_t) 544 | //{ 545 | // struct { 546 | // error yaml_error_type_t 547 | // } context 548 | // mark yaml_mark_t = { 0, 0, 0 } 549 | // tag_copy *yaml_char_t = NULL 550 | // value_copy *yaml_char_t = NULL 551 | // node yaml_node_t 552 | // 553 | // assert(document) // Non-NULL document object is expected. 554 | // assert(value) // Non-NULL value is expected. 555 | // 556 | // if (!tag) { 557 | // tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG 558 | // } 559 | // 560 | // if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error 561 | // tag_copy = yaml_strdup(tag) 562 | // if (!tag_copy) goto error 563 | // 564 | // if (length < 0) { 565 | // length = strlen((char *)value) 566 | // } 567 | // 568 | // if (!yaml_check_utf8(value, length)) goto error 569 | // value_copy = yaml_malloc(length+1) 570 | // if (!value_copy) goto error 571 | // memcpy(value_copy, value, length) 572 | // value_copy[length] = '\0' 573 | // 574 | // SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) 575 | // if (!PUSH(&context, document.nodes, node)) goto error 576 | // 577 | // return document.nodes.top - document.nodes.start 578 | // 579 | //error: 580 | // yaml_free(tag_copy) 581 | // yaml_free(value_copy) 582 | // 583 | // return 0 584 | //} 585 | // 586 | ///* 587 | // * Add a sequence node to a document. 588 | // */ 589 | // 590 | //YAML_DECLARE(int) 591 | //yaml_document_add_sequence(document *yaml_document_t, 592 | // tag *yaml_char_t, style yaml_sequence_style_t) 593 | //{ 594 | // struct { 595 | // error yaml_error_type_t 596 | // } context 597 | // mark yaml_mark_t = { 0, 0, 0 } 598 | // tag_copy *yaml_char_t = NULL 599 | // struct { 600 | // start *yaml_node_item_t 601 | // end *yaml_node_item_t 602 | // top *yaml_node_item_t 603 | // } items = { NULL, NULL, NULL } 604 | // node yaml_node_t 605 | // 606 | // assert(document) // Non-NULL document object is expected. 607 | // 608 | // if (!tag) { 609 | // tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG 610 | // } 611 | // 612 | // if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error 613 | // tag_copy = yaml_strdup(tag) 614 | // if (!tag_copy) goto error 615 | // 616 | // if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error 617 | // 618 | // SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, 619 | // style, mark, mark) 620 | // if (!PUSH(&context, document.nodes, node)) goto error 621 | // 622 | // return document.nodes.top - document.nodes.start 623 | // 624 | //error: 625 | // STACK_DEL(&context, items) 626 | // yaml_free(tag_copy) 627 | // 628 | // return 0 629 | //} 630 | // 631 | ///* 632 | // * Add a mapping node to a document. 633 | // */ 634 | // 635 | //YAML_DECLARE(int) 636 | //yaml_document_add_mapping(document *yaml_document_t, 637 | // tag *yaml_char_t, style yaml_mapping_style_t) 638 | //{ 639 | // struct { 640 | // error yaml_error_type_t 641 | // } context 642 | // mark yaml_mark_t = { 0, 0, 0 } 643 | // tag_copy *yaml_char_t = NULL 644 | // struct { 645 | // start *yaml_node_pair_t 646 | // end *yaml_node_pair_t 647 | // top *yaml_node_pair_t 648 | // } pairs = { NULL, NULL, NULL } 649 | // node yaml_node_t 650 | // 651 | // assert(document) // Non-NULL document object is expected. 652 | // 653 | // if (!tag) { 654 | // tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG 655 | // } 656 | // 657 | // if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error 658 | // tag_copy = yaml_strdup(tag) 659 | // if (!tag_copy) goto error 660 | // 661 | // if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error 662 | // 663 | // MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, 664 | // style, mark, mark) 665 | // if (!PUSH(&context, document.nodes, node)) goto error 666 | // 667 | // return document.nodes.top - document.nodes.start 668 | // 669 | //error: 670 | // STACK_DEL(&context, pairs) 671 | // yaml_free(tag_copy) 672 | // 673 | // return 0 674 | //} 675 | // 676 | ///* 677 | // * Append an item to a sequence node. 678 | // */ 679 | // 680 | //YAML_DECLARE(int) 681 | //yaml_document_append_sequence_item(document *yaml_document_t, 682 | // sequence int, item int) 683 | //{ 684 | // struct { 685 | // error yaml_error_type_t 686 | // } context 687 | // 688 | // assert(document) // Non-NULL document is required. 689 | // assert(sequence > 0 690 | // && document.nodes.start + sequence <= document.nodes.top) 691 | // // Valid sequence id is required. 692 | // assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) 693 | // // A sequence node is required. 694 | // assert(item > 0 && document.nodes.start + item <= document.nodes.top) 695 | // // Valid item id is required. 696 | // 697 | // if (!PUSH(&context, 698 | // document.nodes.start[sequence-1].data.sequence.items, item)) 699 | // return 0 700 | // 701 | // return 1 702 | //} 703 | // 704 | ///* 705 | // * Append a pair of a key and a value to a mapping node. 706 | // */ 707 | // 708 | //YAML_DECLARE(int) 709 | //yaml_document_append_mapping_pair(document *yaml_document_t, 710 | // mapping int, key int, value int) 711 | //{ 712 | // struct { 713 | // error yaml_error_type_t 714 | // } context 715 | // 716 | // pair yaml_node_pair_t 717 | // 718 | // assert(document) // Non-NULL document is required. 719 | // assert(mapping > 0 720 | // && document.nodes.start + mapping <= document.nodes.top) 721 | // // Valid mapping id is required. 722 | // assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) 723 | // // A mapping node is required. 724 | // assert(key > 0 && document.nodes.start + key <= document.nodes.top) 725 | // // Valid key id is required. 726 | // assert(value > 0 && document.nodes.start + value <= document.nodes.top) 727 | // // Valid value id is required. 728 | // 729 | // pair.key = key 730 | // pair.value = value 731 | // 732 | // if (!PUSH(&context, 733 | // document.nodes.start[mapping-1].data.mapping.pairs, pair)) 734 | // return 0 735 | // 736 | // return 1 737 | //} 738 | // 739 | // 740 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/decode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding" 5 | "encoding/base64" 6 | "fmt" 7 | "io" 8 | "math" 9 | "reflect" 10 | "strconv" 11 | "time" 12 | ) 13 | 14 | const ( 15 | documentNode = 1 << iota 16 | mappingNode 17 | sequenceNode 18 | scalarNode 19 | aliasNode 20 | ) 21 | 22 | type node struct { 23 | kind int 24 | line, column int 25 | tag string 26 | // For an alias node, alias holds the resolved alias. 27 | alias *node 28 | value string 29 | implicit bool 30 | children []*node 31 | anchors map[string]*node 32 | } 33 | 34 | // ---------------------------------------------------------------------------- 35 | // Parser, produces a node tree out of a libyaml event stream. 36 | 37 | type parser struct { 38 | parser yaml_parser_t 39 | event yaml_event_t 40 | doc *node 41 | doneInit bool 42 | } 43 | 44 | func newParser(b []byte) *parser { 45 | p := parser{} 46 | if !yaml_parser_initialize(&p.parser) { 47 | panic("failed to initialize YAML emitter") 48 | } 49 | if len(b) == 0 { 50 | b = []byte{'\n'} 51 | } 52 | yaml_parser_set_input_string(&p.parser, b) 53 | return &p 54 | } 55 | 56 | func newParserFromReader(r io.Reader) *parser { 57 | p := parser{} 58 | if !yaml_parser_initialize(&p.parser) { 59 | panic("failed to initialize YAML emitter") 60 | } 61 | yaml_parser_set_input_reader(&p.parser, r) 62 | return &p 63 | } 64 | 65 | func (p *parser) init() { 66 | if p.doneInit { 67 | return 68 | } 69 | p.expect(yaml_STREAM_START_EVENT) 70 | p.doneInit = true 71 | } 72 | 73 | func (p *parser) destroy() { 74 | if p.event.typ != yaml_NO_EVENT { 75 | yaml_event_delete(&p.event) 76 | } 77 | yaml_parser_delete(&p.parser) 78 | } 79 | 80 | // expect consumes an event from the event stream and 81 | // checks that it's of the expected type. 82 | func (p *parser) expect(e yaml_event_type_t) { 83 | if p.event.typ == yaml_NO_EVENT { 84 | if !yaml_parser_parse(&p.parser, &p.event) { 85 | p.fail() 86 | } 87 | } 88 | if p.event.typ == yaml_STREAM_END_EVENT { 89 | failf("attempted to go past the end of stream; corrupted value?") 90 | } 91 | if p.event.typ != e { 92 | p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) 93 | p.fail() 94 | } 95 | yaml_event_delete(&p.event) 96 | p.event.typ = yaml_NO_EVENT 97 | } 98 | 99 | // peek peeks at the next event in the event stream, 100 | // puts the results into p.event and returns the event type. 101 | func (p *parser) peek() yaml_event_type_t { 102 | if p.event.typ != yaml_NO_EVENT { 103 | return p.event.typ 104 | } 105 | if !yaml_parser_parse(&p.parser, &p.event) { 106 | p.fail() 107 | } 108 | return p.event.typ 109 | } 110 | 111 | func (p *parser) fail() { 112 | var where string 113 | var line int 114 | if p.parser.problem_mark.line != 0 { 115 | line = p.parser.problem_mark.line 116 | } else if p.parser.context_mark.line != 0 { 117 | line = p.parser.context_mark.line 118 | } 119 | if line != 0 { 120 | where = "line " + strconv.Itoa(line) + ": " 121 | } 122 | var msg string 123 | if len(p.parser.problem) > 0 { 124 | msg = p.parser.problem 125 | } else { 126 | msg = "unknown problem parsing YAML content" 127 | } 128 | failf("%s%s", where, msg) 129 | } 130 | 131 | func (p *parser) anchor(n *node, anchor []byte) { 132 | if anchor != nil { 133 | p.doc.anchors[string(anchor)] = n 134 | } 135 | } 136 | 137 | func (p *parser) parse() *node { 138 | p.init() 139 | switch p.peek() { 140 | case yaml_SCALAR_EVENT: 141 | return p.scalar() 142 | case yaml_ALIAS_EVENT: 143 | return p.alias() 144 | case yaml_MAPPING_START_EVENT: 145 | return p.mapping() 146 | case yaml_SEQUENCE_START_EVENT: 147 | return p.sequence() 148 | case yaml_DOCUMENT_START_EVENT: 149 | return p.document() 150 | case yaml_STREAM_END_EVENT: 151 | // Happens when attempting to decode an empty buffer. 152 | return nil 153 | default: 154 | panic("attempted to parse unknown event: " + p.event.typ.String()) 155 | } 156 | } 157 | 158 | func (p *parser) node(kind int) *node { 159 | return &node{ 160 | kind: kind, 161 | line: p.event.start_mark.line, 162 | column: p.event.start_mark.column, 163 | } 164 | } 165 | 166 | func (p *parser) document() *node { 167 | n := p.node(documentNode) 168 | n.anchors = make(map[string]*node) 169 | p.doc = n 170 | p.expect(yaml_DOCUMENT_START_EVENT) 171 | n.children = append(n.children, p.parse()) 172 | p.expect(yaml_DOCUMENT_END_EVENT) 173 | return n 174 | } 175 | 176 | func (p *parser) alias() *node { 177 | n := p.node(aliasNode) 178 | n.value = string(p.event.anchor) 179 | n.alias = p.doc.anchors[n.value] 180 | if n.alias == nil { 181 | failf("unknown anchor '%s' referenced", n.value) 182 | } 183 | p.expect(yaml_ALIAS_EVENT) 184 | return n 185 | } 186 | 187 | func (p *parser) scalar() *node { 188 | n := p.node(scalarNode) 189 | n.value = string(p.event.value) 190 | n.tag = string(p.event.tag) 191 | n.implicit = p.event.implicit 192 | p.anchor(n, p.event.anchor) 193 | p.expect(yaml_SCALAR_EVENT) 194 | return n 195 | } 196 | 197 | func (p *parser) sequence() *node { 198 | n := p.node(sequenceNode) 199 | p.anchor(n, p.event.anchor) 200 | p.expect(yaml_SEQUENCE_START_EVENT) 201 | for p.peek() != yaml_SEQUENCE_END_EVENT { 202 | n.children = append(n.children, p.parse()) 203 | } 204 | p.expect(yaml_SEQUENCE_END_EVENT) 205 | return n 206 | } 207 | 208 | func (p *parser) mapping() *node { 209 | n := p.node(mappingNode) 210 | p.anchor(n, p.event.anchor) 211 | p.expect(yaml_MAPPING_START_EVENT) 212 | for p.peek() != yaml_MAPPING_END_EVENT { 213 | n.children = append(n.children, p.parse(), p.parse()) 214 | } 215 | p.expect(yaml_MAPPING_END_EVENT) 216 | return n 217 | } 218 | 219 | // ---------------------------------------------------------------------------- 220 | // Decoder, unmarshals a node into a provided value. 221 | 222 | type decoder struct { 223 | doc *node 224 | aliases map[*node]bool 225 | mapType reflect.Type 226 | terrors []string 227 | strict bool 228 | } 229 | 230 | var ( 231 | mapItemType = reflect.TypeOf(MapItem{}) 232 | durationType = reflect.TypeOf(time.Duration(0)) 233 | defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) 234 | ifaceType = defaultMapType.Elem() 235 | timeType = reflect.TypeOf(time.Time{}) 236 | ptrTimeType = reflect.TypeOf(&time.Time{}) 237 | ) 238 | 239 | func newDecoder(strict bool) *decoder { 240 | d := &decoder{mapType: defaultMapType, strict: strict} 241 | d.aliases = make(map[*node]bool) 242 | return d 243 | } 244 | 245 | func (d *decoder) terror(n *node, tag string, out reflect.Value) { 246 | if n.tag != "" { 247 | tag = n.tag 248 | } 249 | value := n.value 250 | if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG { 251 | if len(value) > 10 { 252 | value = " `" + value[:7] + "...`" 253 | } else { 254 | value = " `" + value + "`" 255 | } 256 | } 257 | d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type())) 258 | } 259 | 260 | func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) { 261 | terrlen := len(d.terrors) 262 | err := u.UnmarshalYAML(func(v interface{}) (err error) { 263 | defer handleErr(&err) 264 | d.unmarshal(n, reflect.ValueOf(v)) 265 | if len(d.terrors) > terrlen { 266 | issues := d.terrors[terrlen:] 267 | d.terrors = d.terrors[:terrlen] 268 | return &TypeError{issues} 269 | } 270 | return nil 271 | }) 272 | if e, ok := err.(*TypeError); ok { 273 | d.terrors = append(d.terrors, e.Errors...) 274 | return false 275 | } 276 | if err != nil { 277 | fail(err) 278 | } 279 | return true 280 | } 281 | 282 | // d.prepare initializes and dereferences pointers and calls UnmarshalYAML 283 | // if a value is found to implement it. 284 | // It returns the initialized and dereferenced out value, whether 285 | // unmarshalling was already done by UnmarshalYAML, and if so whether 286 | // its types unmarshalled appropriately. 287 | // 288 | // If n holds a null value, prepare returns before doing anything. 289 | func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { 290 | if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) { 291 | return out, false, false 292 | } 293 | again := true 294 | for again { 295 | again = false 296 | if out.Kind() == reflect.Ptr { 297 | if out.IsNil() { 298 | out.Set(reflect.New(out.Type().Elem())) 299 | } 300 | out = out.Elem() 301 | again = true 302 | } 303 | if out.CanAddr() { 304 | if u, ok := out.Addr().Interface().(Unmarshaler); ok { 305 | good = d.callUnmarshaler(n, u) 306 | return out, true, good 307 | } 308 | } 309 | } 310 | return out, false, false 311 | } 312 | 313 | func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { 314 | switch n.kind { 315 | case documentNode: 316 | return d.document(n, out) 317 | case aliasNode: 318 | return d.alias(n, out) 319 | } 320 | out, unmarshaled, good := d.prepare(n, out) 321 | if unmarshaled { 322 | return good 323 | } 324 | switch n.kind { 325 | case scalarNode: 326 | good = d.scalar(n, out) 327 | case mappingNode: 328 | good = d.mapping(n, out) 329 | case sequenceNode: 330 | good = d.sequence(n, out) 331 | default: 332 | panic("internal error: unknown node kind: " + strconv.Itoa(n.kind)) 333 | } 334 | return good 335 | } 336 | 337 | func (d *decoder) document(n *node, out reflect.Value) (good bool) { 338 | if len(n.children) == 1 { 339 | d.doc = n 340 | d.unmarshal(n.children[0], out) 341 | return true 342 | } 343 | return false 344 | } 345 | 346 | func (d *decoder) alias(n *node, out reflect.Value) (good bool) { 347 | if d.aliases[n] { 348 | // TODO this could actually be allowed in some circumstances. 349 | failf("anchor '%s' value contains itself", n.value) 350 | } 351 | d.aliases[n] = true 352 | good = d.unmarshal(n.alias, out) 353 | delete(d.aliases, n) 354 | return good 355 | } 356 | 357 | var zeroValue reflect.Value 358 | 359 | func resetMap(out reflect.Value) { 360 | for _, k := range out.MapKeys() { 361 | out.SetMapIndex(k, zeroValue) 362 | } 363 | } 364 | 365 | func (d *decoder) scalar(n *node, out reflect.Value) bool { 366 | var tag string 367 | var resolved interface{} 368 | if n.tag == "" && !n.implicit { 369 | tag = yaml_STR_TAG 370 | resolved = n.value 371 | } else { 372 | tag, resolved = resolve(n.tag, n.value) 373 | if tag == yaml_BINARY_TAG { 374 | data, err := base64.StdEncoding.DecodeString(resolved.(string)) 375 | if err != nil { 376 | failf("!!binary value contains invalid base64 data") 377 | } 378 | resolved = string(data) 379 | } 380 | } 381 | if resolved == nil { 382 | if out.Kind() == reflect.Map && !out.CanAddr() { 383 | resetMap(out) 384 | } else { 385 | out.Set(reflect.Zero(out.Type())) 386 | } 387 | return true 388 | } 389 | if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { 390 | // We've resolved to exactly the type we want, so use that. 391 | out.Set(resolvedv) 392 | return true 393 | } 394 | // Perhaps we can use the value as a TextUnmarshaler to 395 | // set its value. 396 | if out.CanAddr() { 397 | u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) 398 | if ok { 399 | var text []byte 400 | if tag == yaml_BINARY_TAG { 401 | text = []byte(resolved.(string)) 402 | } else { 403 | // We let any value be unmarshaled into TextUnmarshaler. 404 | // That might be more lax than we'd like, but the 405 | // TextUnmarshaler itself should bowl out any dubious values. 406 | text = []byte(n.value) 407 | } 408 | err := u.UnmarshalText(text) 409 | if err != nil { 410 | fail(err) 411 | } 412 | return true 413 | } 414 | } 415 | switch out.Kind() { 416 | case reflect.String: 417 | if tag == yaml_BINARY_TAG { 418 | out.SetString(resolved.(string)) 419 | return true 420 | } 421 | if resolved != nil { 422 | out.SetString(n.value) 423 | return true 424 | } 425 | case reflect.Interface: 426 | if resolved == nil { 427 | out.Set(reflect.Zero(out.Type())) 428 | } else if tag == yaml_TIMESTAMP_TAG { 429 | // It looks like a timestamp but for backward compatibility 430 | // reasons we set it as a string, so that code that unmarshals 431 | // timestamp-like values into interface{} will continue to 432 | // see a string and not a time.Time. 433 | out.Set(reflect.ValueOf(n.value)) 434 | } else { 435 | out.Set(reflect.ValueOf(resolved)) 436 | } 437 | return true 438 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 439 | switch resolved := resolved.(type) { 440 | case int: 441 | if !out.OverflowInt(int64(resolved)) { 442 | out.SetInt(int64(resolved)) 443 | return true 444 | } 445 | case int64: 446 | if !out.OverflowInt(resolved) { 447 | out.SetInt(resolved) 448 | return true 449 | } 450 | case uint64: 451 | if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { 452 | out.SetInt(int64(resolved)) 453 | return true 454 | } 455 | case float64: 456 | if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { 457 | out.SetInt(int64(resolved)) 458 | return true 459 | } 460 | case string: 461 | if out.Type() == durationType { 462 | d, err := time.ParseDuration(resolved) 463 | if err == nil { 464 | out.SetInt(int64(d)) 465 | return true 466 | } 467 | } 468 | } 469 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 470 | switch resolved := resolved.(type) { 471 | case int: 472 | if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { 473 | out.SetUint(uint64(resolved)) 474 | return true 475 | } 476 | case int64: 477 | if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { 478 | out.SetUint(uint64(resolved)) 479 | return true 480 | } 481 | case uint64: 482 | if !out.OverflowUint(uint64(resolved)) { 483 | out.SetUint(uint64(resolved)) 484 | return true 485 | } 486 | case float64: 487 | if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { 488 | out.SetUint(uint64(resolved)) 489 | return true 490 | } 491 | } 492 | case reflect.Bool: 493 | switch resolved := resolved.(type) { 494 | case bool: 495 | out.SetBool(resolved) 496 | return true 497 | } 498 | case reflect.Float32, reflect.Float64: 499 | switch resolved := resolved.(type) { 500 | case int: 501 | out.SetFloat(float64(resolved)) 502 | return true 503 | case int64: 504 | out.SetFloat(float64(resolved)) 505 | return true 506 | case uint64: 507 | out.SetFloat(float64(resolved)) 508 | return true 509 | case float64: 510 | out.SetFloat(resolved) 511 | return true 512 | } 513 | case reflect.Struct: 514 | if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { 515 | out.Set(resolvedv) 516 | return true 517 | } 518 | case reflect.Ptr: 519 | if out.Type().Elem() == reflect.TypeOf(resolved) { 520 | // TODO DOes this make sense? When is out a Ptr except when decoding a nil value? 521 | elem := reflect.New(out.Type().Elem()) 522 | elem.Elem().Set(reflect.ValueOf(resolved)) 523 | out.Set(elem) 524 | return true 525 | } 526 | } 527 | d.terror(n, tag, out) 528 | return false 529 | } 530 | 531 | func settableValueOf(i interface{}) reflect.Value { 532 | v := reflect.ValueOf(i) 533 | sv := reflect.New(v.Type()).Elem() 534 | sv.Set(v) 535 | return sv 536 | } 537 | 538 | func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { 539 | l := len(n.children) 540 | 541 | var iface reflect.Value 542 | switch out.Kind() { 543 | case reflect.Slice: 544 | out.Set(reflect.MakeSlice(out.Type(), l, l)) 545 | case reflect.Interface: 546 | // No type hints. Will have to use a generic sequence. 547 | iface = out 548 | out = settableValueOf(make([]interface{}, l)) 549 | default: 550 | d.terror(n, yaml_SEQ_TAG, out) 551 | return false 552 | } 553 | et := out.Type().Elem() 554 | 555 | j := 0 556 | for i := 0; i < l; i++ { 557 | e := reflect.New(et).Elem() 558 | if ok := d.unmarshal(n.children[i], e); ok { 559 | out.Index(j).Set(e) 560 | j++ 561 | } 562 | } 563 | out.Set(out.Slice(0, j)) 564 | if iface.IsValid() { 565 | iface.Set(out) 566 | } 567 | return true 568 | } 569 | 570 | func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { 571 | switch out.Kind() { 572 | case reflect.Struct: 573 | return d.mappingStruct(n, out) 574 | case reflect.Slice: 575 | return d.mappingSlice(n, out) 576 | case reflect.Map: 577 | // okay 578 | case reflect.Interface: 579 | if d.mapType.Kind() == reflect.Map { 580 | iface := out 581 | out = reflect.MakeMap(d.mapType) 582 | iface.Set(out) 583 | } else { 584 | slicev := reflect.New(d.mapType).Elem() 585 | if !d.mappingSlice(n, slicev) { 586 | return false 587 | } 588 | out.Set(slicev) 589 | return true 590 | } 591 | default: 592 | d.terror(n, yaml_MAP_TAG, out) 593 | return false 594 | } 595 | outt := out.Type() 596 | kt := outt.Key() 597 | et := outt.Elem() 598 | 599 | mapType := d.mapType 600 | if outt.Key() == ifaceType && outt.Elem() == ifaceType { 601 | d.mapType = outt 602 | } 603 | 604 | if out.IsNil() { 605 | out.Set(reflect.MakeMap(outt)) 606 | } 607 | l := len(n.children) 608 | for i := 0; i < l; i += 2 { 609 | if isMerge(n.children[i]) { 610 | d.merge(n.children[i+1], out) 611 | continue 612 | } 613 | k := reflect.New(kt).Elem() 614 | if d.unmarshal(n.children[i], k) { 615 | kkind := k.Kind() 616 | if kkind == reflect.Interface { 617 | kkind = k.Elem().Kind() 618 | } 619 | if kkind == reflect.Map || kkind == reflect.Slice { 620 | failf("invalid map key: %#v", k.Interface()) 621 | } 622 | e := reflect.New(et).Elem() 623 | if d.unmarshal(n.children[i+1], e) { 624 | d.setMapIndex(n.children[i+1], out, k, e) 625 | } 626 | } 627 | } 628 | d.mapType = mapType 629 | return true 630 | } 631 | 632 | func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) { 633 | if d.strict && out.MapIndex(k) != zeroValue { 634 | d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface())) 635 | return 636 | } 637 | out.SetMapIndex(k, v) 638 | } 639 | 640 | func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) { 641 | outt := out.Type() 642 | if outt.Elem() != mapItemType { 643 | d.terror(n, yaml_MAP_TAG, out) 644 | return false 645 | } 646 | 647 | mapType := d.mapType 648 | d.mapType = outt 649 | 650 | var slice []MapItem 651 | var l = len(n.children) 652 | for i := 0; i < l; i += 2 { 653 | if isMerge(n.children[i]) { 654 | d.merge(n.children[i+1], out) 655 | continue 656 | } 657 | item := MapItem{} 658 | k := reflect.ValueOf(&item.Key).Elem() 659 | if d.unmarshal(n.children[i], k) { 660 | v := reflect.ValueOf(&item.Value).Elem() 661 | if d.unmarshal(n.children[i+1], v) { 662 | slice = append(slice, item) 663 | } 664 | } 665 | } 666 | out.Set(reflect.ValueOf(slice)) 667 | d.mapType = mapType 668 | return true 669 | } 670 | 671 | func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) { 672 | sinfo, err := getStructInfo(out.Type()) 673 | if err != nil { 674 | panic(err) 675 | } 676 | name := settableValueOf("") 677 | l := len(n.children) 678 | 679 | var inlineMap reflect.Value 680 | var elemType reflect.Type 681 | if sinfo.InlineMap != -1 { 682 | inlineMap = out.Field(sinfo.InlineMap) 683 | inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) 684 | elemType = inlineMap.Type().Elem() 685 | } 686 | 687 | var doneFields []bool 688 | if d.strict { 689 | doneFields = make([]bool, len(sinfo.FieldsList)) 690 | } 691 | for i := 0; i < l; i += 2 { 692 | ni := n.children[i] 693 | if isMerge(ni) { 694 | d.merge(n.children[i+1], out) 695 | continue 696 | } 697 | if !d.unmarshal(ni, name) { 698 | continue 699 | } 700 | if info, ok := sinfo.FieldsMap[name.String()]; ok { 701 | if d.strict { 702 | if doneFields[info.Id] { 703 | d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type())) 704 | continue 705 | } 706 | doneFields[info.Id] = true 707 | } 708 | var field reflect.Value 709 | if info.Inline == nil { 710 | field = out.Field(info.Num) 711 | } else { 712 | field = out.FieldByIndex(info.Inline) 713 | } 714 | d.unmarshal(n.children[i+1], field) 715 | } else if sinfo.InlineMap != -1 { 716 | if inlineMap.IsNil() { 717 | inlineMap.Set(reflect.MakeMap(inlineMap.Type())) 718 | } 719 | value := reflect.New(elemType).Elem() 720 | d.unmarshal(n.children[i+1], value) 721 | d.setMapIndex(n.children[i+1], inlineMap, name, value) 722 | } else if d.strict { 723 | d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type())) 724 | } 725 | } 726 | return true 727 | } 728 | 729 | func failWantMap() { 730 | failf("map merge requires map or sequence of maps as the value") 731 | } 732 | 733 | func (d *decoder) merge(n *node, out reflect.Value) { 734 | switch n.kind { 735 | case mappingNode: 736 | d.unmarshal(n, out) 737 | case aliasNode: 738 | an, ok := d.doc.anchors[n.value] 739 | if ok && an.kind != mappingNode { 740 | failWantMap() 741 | } 742 | d.unmarshal(n, out) 743 | case sequenceNode: 744 | // Step backwards as earlier nodes take precedence. 745 | for i := len(n.children) - 1; i >= 0; i-- { 746 | ni := n.children[i] 747 | if ni.kind == aliasNode { 748 | an, ok := d.doc.anchors[ni.value] 749 | if ok && an.kind != mappingNode { 750 | failWantMap() 751 | } 752 | } else if ni.kind != mappingNode { 753 | failWantMap() 754 | } 755 | d.unmarshal(ni, out) 756 | } 757 | default: 758 | failWantMap() 759 | } 760 | } 761 | 762 | func isMerge(n *node) bool { 763 | return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG) 764 | } 765 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/decode_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "math" 7 | "reflect" 8 | "strings" 9 | "time" 10 | 11 | . "gopkg.in/check.v1" 12 | "gopkg.in/yaml.v2" 13 | ) 14 | 15 | var unmarshalIntTest = 123 16 | 17 | var unmarshalTests = []struct { 18 | data string 19 | value interface{} 20 | }{ 21 | { 22 | "", 23 | (*struct{})(nil), 24 | }, 25 | { 26 | "{}", &struct{}{}, 27 | }, { 28 | "v: hi", 29 | map[string]string{"v": "hi"}, 30 | }, { 31 | "v: hi", map[string]interface{}{"v": "hi"}, 32 | }, { 33 | "v: true", 34 | map[string]string{"v": "true"}, 35 | }, { 36 | "v: true", 37 | map[string]interface{}{"v": true}, 38 | }, { 39 | "v: 10", 40 | map[string]interface{}{"v": 10}, 41 | }, { 42 | "v: 0b10", 43 | map[string]interface{}{"v": 2}, 44 | }, { 45 | "v: 0xA", 46 | map[string]interface{}{"v": 10}, 47 | }, { 48 | "v: 4294967296", 49 | map[string]int64{"v": 4294967296}, 50 | }, { 51 | "v: 0.1", 52 | map[string]interface{}{"v": 0.1}, 53 | }, { 54 | "v: .1", 55 | map[string]interface{}{"v": 0.1}, 56 | }, { 57 | "v: .Inf", 58 | map[string]interface{}{"v": math.Inf(+1)}, 59 | }, { 60 | "v: -.Inf", 61 | map[string]interface{}{"v": math.Inf(-1)}, 62 | }, { 63 | "v: -10", 64 | map[string]interface{}{"v": -10}, 65 | }, { 66 | "v: -.1", 67 | map[string]interface{}{"v": -0.1}, 68 | }, 69 | 70 | // Simple values. 71 | { 72 | "123", 73 | &unmarshalIntTest, 74 | }, 75 | 76 | // Floats from spec 77 | { 78 | "canonical: 6.8523e+5", 79 | map[string]interface{}{"canonical": 6.8523e+5}, 80 | }, { 81 | "expo: 685.230_15e+03", 82 | map[string]interface{}{"expo": 685.23015e+03}, 83 | }, { 84 | "fixed: 685_230.15", 85 | map[string]interface{}{"fixed": 685230.15}, 86 | }, { 87 | "neginf: -.inf", 88 | map[string]interface{}{"neginf": math.Inf(-1)}, 89 | }, { 90 | "fixed: 685_230.15", 91 | map[string]float64{"fixed": 685230.15}, 92 | }, 93 | //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported 94 | //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. 95 | 96 | // Bools from spec 97 | { 98 | "canonical: y", 99 | map[string]interface{}{"canonical": true}, 100 | }, { 101 | "answer: NO", 102 | map[string]interface{}{"answer": false}, 103 | }, { 104 | "logical: True", 105 | map[string]interface{}{"logical": true}, 106 | }, { 107 | "option: on", 108 | map[string]interface{}{"option": true}, 109 | }, { 110 | "option: on", 111 | map[string]bool{"option": true}, 112 | }, 113 | // Ints from spec 114 | { 115 | "canonical: 685230", 116 | map[string]interface{}{"canonical": 685230}, 117 | }, { 118 | "decimal: +685_230", 119 | map[string]interface{}{"decimal": 685230}, 120 | }, { 121 | "octal: 02472256", 122 | map[string]interface{}{"octal": 685230}, 123 | }, { 124 | "hexa: 0x_0A_74_AE", 125 | map[string]interface{}{"hexa": 685230}, 126 | }, { 127 | "bin: 0b1010_0111_0100_1010_1110", 128 | map[string]interface{}{"bin": 685230}, 129 | }, { 130 | "bin: -0b101010", 131 | map[string]interface{}{"bin": -42}, 132 | }, { 133 | "decimal: +685_230", 134 | map[string]int{"decimal": 685230}, 135 | }, 136 | 137 | //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported 138 | 139 | // Nulls from spec 140 | { 141 | "empty:", 142 | map[string]interface{}{"empty": nil}, 143 | }, { 144 | "canonical: ~", 145 | map[string]interface{}{"canonical": nil}, 146 | }, { 147 | "english: null", 148 | map[string]interface{}{"english": nil}, 149 | }, { 150 | "~: null key", 151 | map[interface{}]string{nil: "null key"}, 152 | }, { 153 | "empty:", 154 | map[string]*bool{"empty": nil}, 155 | }, 156 | 157 | // Flow sequence 158 | { 159 | "seq: [A,B]", 160 | map[string]interface{}{"seq": []interface{}{"A", "B"}}, 161 | }, { 162 | "seq: [A,B,C,]", 163 | map[string][]string{"seq": []string{"A", "B", "C"}}, 164 | }, { 165 | "seq: [A,1,C]", 166 | map[string][]string{"seq": []string{"A", "1", "C"}}, 167 | }, { 168 | "seq: [A,1,C]", 169 | map[string][]int{"seq": []int{1}}, 170 | }, { 171 | "seq: [A,1,C]", 172 | map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 173 | }, 174 | // Block sequence 175 | { 176 | "seq:\n - A\n - B", 177 | map[string]interface{}{"seq": []interface{}{"A", "B"}}, 178 | }, { 179 | "seq:\n - A\n - B\n - C", 180 | map[string][]string{"seq": []string{"A", "B", "C"}}, 181 | }, { 182 | "seq:\n - A\n - 1\n - C", 183 | map[string][]string{"seq": []string{"A", "1", "C"}}, 184 | }, { 185 | "seq:\n - A\n - 1\n - C", 186 | map[string][]int{"seq": []int{1}}, 187 | }, { 188 | "seq:\n - A\n - 1\n - C", 189 | map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 190 | }, 191 | 192 | // Literal block scalar 193 | { 194 | "scalar: | # Comment\n\n literal\n\n \ttext\n\n", 195 | map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, 196 | }, 197 | 198 | // Folded block scalar 199 | { 200 | "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", 201 | map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, 202 | }, 203 | 204 | // Map inside interface with no type hints. 205 | { 206 | "a: {b: c}", 207 | map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 208 | }, 209 | 210 | // Structs and type conversions. 211 | { 212 | "hello: world", 213 | &struct{ Hello string }{"world"}, 214 | }, { 215 | "a: {b: c}", 216 | &struct{ A struct{ B string } }{struct{ B string }{"c"}}, 217 | }, { 218 | "a: {b: c}", 219 | &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, 220 | }, { 221 | "a: {b: c}", 222 | &struct{ A map[string]string }{map[string]string{"b": "c"}}, 223 | }, { 224 | "a: {b: c}", 225 | &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, 226 | }, { 227 | "a:", 228 | &struct{ A map[string]string }{}, 229 | }, { 230 | "a: 1", 231 | &struct{ A int }{1}, 232 | }, { 233 | "a: 1", 234 | &struct{ A float64 }{1}, 235 | }, { 236 | "a: 1.0", 237 | &struct{ A int }{1}, 238 | }, { 239 | "a: 1.0", 240 | &struct{ A uint }{1}, 241 | }, { 242 | "a: [1, 2]", 243 | &struct{ A []int }{[]int{1, 2}}, 244 | }, { 245 | "a: 1", 246 | &struct{ B int }{0}, 247 | }, { 248 | "a: 1", 249 | &struct { 250 | B int "a" 251 | }{1}, 252 | }, { 253 | "a: y", 254 | &struct{ A bool }{true}, 255 | }, 256 | 257 | // Some cross type conversions 258 | { 259 | "v: 42", 260 | map[string]uint{"v": 42}, 261 | }, { 262 | "v: -42", 263 | map[string]uint{}, 264 | }, { 265 | "v: 4294967296", 266 | map[string]uint64{"v": 4294967296}, 267 | }, { 268 | "v: -4294967296", 269 | map[string]uint64{}, 270 | }, 271 | 272 | // int 273 | { 274 | "int_max: 2147483647", 275 | map[string]int{"int_max": math.MaxInt32}, 276 | }, 277 | { 278 | "int_min: -2147483648", 279 | map[string]int{"int_min": math.MinInt32}, 280 | }, 281 | { 282 | "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 283 | map[string]int{}, 284 | }, 285 | 286 | // int64 287 | { 288 | "int64_max: 9223372036854775807", 289 | map[string]int64{"int64_max": math.MaxInt64}, 290 | }, 291 | { 292 | "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", 293 | map[string]int64{"int64_max_base2": math.MaxInt64}, 294 | }, 295 | { 296 | "int64_min: -9223372036854775808", 297 | map[string]int64{"int64_min": math.MinInt64}, 298 | }, 299 | { 300 | "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", 301 | map[string]int64{"int64_neg_base2": -math.MaxInt64}, 302 | }, 303 | { 304 | "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 305 | map[string]int64{}, 306 | }, 307 | 308 | // uint 309 | { 310 | "uint_min: 0", 311 | map[string]uint{"uint_min": 0}, 312 | }, 313 | { 314 | "uint_max: 4294967295", 315 | map[string]uint{"uint_max": math.MaxUint32}, 316 | }, 317 | { 318 | "uint_underflow: -1", 319 | map[string]uint{}, 320 | }, 321 | 322 | // uint64 323 | { 324 | "uint64_min: 0", 325 | map[string]uint{"uint64_min": 0}, 326 | }, 327 | { 328 | "uint64_max: 18446744073709551615", 329 | map[string]uint64{"uint64_max": math.MaxUint64}, 330 | }, 331 | { 332 | "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", 333 | map[string]uint64{"uint64_max_base2": math.MaxUint64}, 334 | }, 335 | { 336 | "uint64_maxint64: 9223372036854775807", 337 | map[string]uint64{"uint64_maxint64": math.MaxInt64}, 338 | }, 339 | { 340 | "uint64_underflow: -1", 341 | map[string]uint64{}, 342 | }, 343 | 344 | // float32 345 | { 346 | "float32_max: 3.40282346638528859811704183484516925440e+38", 347 | map[string]float32{"float32_max": math.MaxFloat32}, 348 | }, 349 | { 350 | "float32_nonzero: 1.401298464324817070923729583289916131280e-45", 351 | map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32}, 352 | }, 353 | { 354 | "float32_maxuint64: 18446744073709551615", 355 | map[string]float32{"float32_maxuint64": float32(math.MaxUint64)}, 356 | }, 357 | { 358 | "float32_maxuint64+1: 18446744073709551616", 359 | map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)}, 360 | }, 361 | 362 | // float64 363 | { 364 | "float64_max: 1.797693134862315708145274237317043567981e+308", 365 | map[string]float64{"float64_max": math.MaxFloat64}, 366 | }, 367 | { 368 | "float64_nonzero: 4.940656458412465441765687928682213723651e-324", 369 | map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64}, 370 | }, 371 | { 372 | "float64_maxuint64: 18446744073709551615", 373 | map[string]float64{"float64_maxuint64": float64(math.MaxUint64)}, 374 | }, 375 | { 376 | "float64_maxuint64+1: 18446744073709551616", 377 | map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)}, 378 | }, 379 | 380 | // Overflow cases. 381 | { 382 | "v: 4294967297", 383 | map[string]int32{}, 384 | }, { 385 | "v: 128", 386 | map[string]int8{}, 387 | }, 388 | 389 | // Quoted values. 390 | { 391 | "'1': '\"2\"'", 392 | map[interface{}]interface{}{"1": "\"2\""}, 393 | }, { 394 | "v:\n- A\n- 'B\n\n C'\n", 395 | map[string][]string{"v": []string{"A", "B\nC"}}, 396 | }, 397 | 398 | // Explicit tags. 399 | { 400 | "v: !!float '1.1'", 401 | map[string]interface{}{"v": 1.1}, 402 | }, { 403 | "v: !!null ''", 404 | map[string]interface{}{"v": nil}, 405 | }, { 406 | "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", 407 | map[string]interface{}{"v": 1}, 408 | }, 409 | 410 | // Non-specific tag (Issue #75) 411 | { 412 | "v: ! test", 413 | map[string]interface{}{"v": "test"}, 414 | }, 415 | 416 | // Anchors and aliases. 417 | { 418 | "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", 419 | &struct{ A, B, C, D int }{1, 2, 1, 2}, 420 | }, { 421 | "a: &a {c: 1}\nb: *a", 422 | &struct { 423 | A, B struct { 424 | C int 425 | } 426 | }{struct{ C int }{1}, struct{ C int }{1}}, 427 | }, { 428 | "a: &a [1, 2]\nb: *a", 429 | &struct{ B []int }{[]int{1, 2}}, 430 | }, 431 | 432 | // Bug #1133337 433 | { 434 | "foo: ''", 435 | map[string]*string{"foo": new(string)}, 436 | }, { 437 | "foo: null", 438 | map[string]*string{"foo": nil}, 439 | }, { 440 | "foo: null", 441 | map[string]string{"foo": ""}, 442 | }, { 443 | "foo: null", 444 | map[string]interface{}{"foo": nil}, 445 | }, 446 | 447 | // Support for ~ 448 | { 449 | "foo: ~", 450 | map[string]*string{"foo": nil}, 451 | }, { 452 | "foo: ~", 453 | map[string]string{"foo": ""}, 454 | }, { 455 | "foo: ~", 456 | map[string]interface{}{"foo": nil}, 457 | }, 458 | 459 | // Ignored field 460 | { 461 | "a: 1\nb: 2\n", 462 | &struct { 463 | A int 464 | B int "-" 465 | }{1, 0}, 466 | }, 467 | 468 | // Bug #1191981 469 | { 470 | "" + 471 | "%YAML 1.1\n" + 472 | "--- !!str\n" + 473 | `"Generic line break (no glyph)\n\` + "\n" + 474 | ` Generic line break (glyphed)\n\` + "\n" + 475 | ` Line separator\u2028\` + "\n" + 476 | ` Paragraph separator\u2029"` + "\n", 477 | "" + 478 | "Generic line break (no glyph)\n" + 479 | "Generic line break (glyphed)\n" + 480 | "Line separator\u2028Paragraph separator\u2029", 481 | }, 482 | 483 | // Struct inlining 484 | { 485 | "a: 1\nb: 2\nc: 3\n", 486 | &struct { 487 | A int 488 | C inlineB `yaml:",inline"` 489 | }{1, inlineB{2, inlineC{3}}}, 490 | }, 491 | 492 | // Map inlining 493 | { 494 | "a: 1\nb: 2\nc: 3\n", 495 | &struct { 496 | A int 497 | C map[string]int `yaml:",inline"` 498 | }{1, map[string]int{"b": 2, "c": 3}}, 499 | }, 500 | 501 | // bug 1243827 502 | { 503 | "a: -b_c", 504 | map[string]interface{}{"a": "-b_c"}, 505 | }, 506 | { 507 | "a: +b_c", 508 | map[string]interface{}{"a": "+b_c"}, 509 | }, 510 | { 511 | "a: 50cent_of_dollar", 512 | map[string]interface{}{"a": "50cent_of_dollar"}, 513 | }, 514 | 515 | // issue #295 (allow scalars with colons in flow mappings and sequences) 516 | { 517 | "a: {b: https://github.com/go-yaml/yaml}", 518 | map[string]interface{}{"a": map[interface{}]interface{}{ 519 | "b": "https://github.com/go-yaml/yaml", 520 | }}, 521 | }, 522 | { 523 | "a: [https://github.com/go-yaml/yaml]", 524 | map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}}, 525 | }, 526 | 527 | // Duration 528 | { 529 | "a: 3s", 530 | map[string]time.Duration{"a": 3 * time.Second}, 531 | }, 532 | 533 | // Issue #24. 534 | { 535 | "a: ", 536 | map[string]string{"a": ""}, 537 | }, 538 | 539 | // Base 60 floats are obsolete and unsupported. 540 | { 541 | "a: 1:1\n", 542 | map[string]string{"a": "1:1"}, 543 | }, 544 | 545 | // Binary data. 546 | { 547 | "a: !!binary gIGC\n", 548 | map[string]string{"a": "\x80\x81\x82"}, 549 | }, { 550 | "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 551 | map[string]string{"a": strings.Repeat("\x90", 54)}, 552 | }, { 553 | "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", 554 | map[string]string{"a": strings.Repeat("\x00", 52)}, 555 | }, 556 | 557 | // Ordered maps. 558 | { 559 | "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}", 560 | &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, 561 | }, 562 | 563 | // Issue #39. 564 | { 565 | "a:\n b:\n c: d\n", 566 | map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}}, 567 | }, 568 | 569 | // Custom map type. 570 | { 571 | "a: {b: c}", 572 | M{"a": M{"b": "c"}}, 573 | }, 574 | 575 | // Support encoding.TextUnmarshaler. 576 | { 577 | "a: 1.2.3.4\n", 578 | map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}}, 579 | }, 580 | { 581 | "a: 2015-02-24T18:19:39Z\n", 582 | map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}}, 583 | }, 584 | 585 | // Timestamps 586 | { 587 | // Date only. 588 | "a: 2015-01-01\n", 589 | map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 590 | }, 591 | { 592 | // RFC3339 593 | "a: 2015-02-24T18:19:39.12Z\n", 594 | map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)}, 595 | }, 596 | { 597 | // RFC3339 with short dates. 598 | "a: 2015-2-3T3:4:5Z", 599 | map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)}, 600 | }, 601 | { 602 | // ISO8601 lower case t 603 | "a: 2015-02-24t18:19:39Z\n", 604 | map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, 605 | }, 606 | { 607 | // space separate, no time zone 608 | "a: 2015-02-24 18:19:39\n", 609 | map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, 610 | }, 611 | // Some cases not currently handled. Uncomment these when 612 | // the code is fixed. 613 | // { 614 | // // space separated with time zone 615 | // "a: 2001-12-14 21:59:43.10 -5", 616 | // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, 617 | // }, 618 | // { 619 | // // arbitrary whitespace between fields 620 | // "a: 2001-12-14 \t\t \t21:59:43.10 \t Z", 621 | // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, 622 | // }, 623 | { 624 | // explicit string tag 625 | "a: !!str 2015-01-01", 626 | map[string]interface{}{"a": "2015-01-01"}, 627 | }, 628 | { 629 | // explicit timestamp tag on quoted string 630 | "a: !!timestamp \"2015-01-01\"", 631 | map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 632 | }, 633 | { 634 | // explicit timestamp tag on unquoted string 635 | "a: !!timestamp 2015-01-01", 636 | map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 637 | }, 638 | { 639 | // quoted string that's a valid timestamp 640 | "a: \"2015-01-01\"", 641 | map[string]interface{}{"a": "2015-01-01"}, 642 | }, 643 | { 644 | // explicit timestamp tag into interface. 645 | "a: !!timestamp \"2015-01-01\"", 646 | map[string]interface{}{"a": "2015-01-01"}, 647 | }, 648 | { 649 | // implicit timestamp tag into interface. 650 | "a: 2015-01-01", 651 | map[string]interface{}{"a": "2015-01-01"}, 652 | }, 653 | 654 | // Encode empty lists as zero-length slices. 655 | { 656 | "a: []", 657 | &struct{ A []int }{[]int{}}, 658 | }, 659 | 660 | // UTF-16-LE 661 | { 662 | "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00", 663 | M{"ñoño": "very yes"}, 664 | }, 665 | // UTF-16-LE with surrogate. 666 | { 667 | "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00", 668 | M{"ñoño": "very yes 🟔"}, 669 | }, 670 | 671 | // UTF-16-BE 672 | { 673 | "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n", 674 | M{"ñoño": "very yes"}, 675 | }, 676 | // UTF-16-BE with surrogate. 677 | { 678 | "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n", 679 | M{"ñoño": "very yes 🟔"}, 680 | }, 681 | 682 | // YAML Float regex shouldn't match this 683 | { 684 | "a: 123456e1\n", 685 | M{"a": "123456e1"}, 686 | }, { 687 | "a: 123456E1\n", 688 | M{"a": "123456E1"}, 689 | }, 690 | // yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes 691 | { 692 | "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n", 693 | map[interface{}]interface{}{ 694 | "Reuse anchor": "Bar", 695 | "First occurrence": "Foo", 696 | "Second occurrence": "Foo", 697 | "Override anchor": "Bar", 698 | }, 699 | }, 700 | // Single document with garbage following it. 701 | { 702 | "---\nhello\n...\n}not yaml", 703 | "hello", 704 | }, 705 | } 706 | 707 | type M map[interface{}]interface{} 708 | 709 | type inlineB struct { 710 | B int 711 | inlineC `yaml:",inline"` 712 | } 713 | 714 | type inlineC struct { 715 | C int 716 | } 717 | 718 | func (s *S) TestUnmarshal(c *C) { 719 | for i, item := range unmarshalTests { 720 | c.Logf("test %d: %q", i, item.data) 721 | t := reflect.ValueOf(item.value).Type() 722 | value := reflect.New(t) 723 | err := yaml.Unmarshal([]byte(item.data), value.Interface()) 724 | if _, ok := err.(*yaml.TypeError); !ok { 725 | c.Assert(err, IsNil) 726 | } 727 | c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err)) 728 | } 729 | } 730 | 731 | func (s *S) TestDecoderSingleDocument(c *C) { 732 | // Test that Decoder.Decode works as expected on 733 | // all the unmarshal tests. 734 | for i, item := range unmarshalTests { 735 | c.Logf("test %d: %q", i, item.data) 736 | if item.data == "" { 737 | // Behaviour differs when there's no YAML. 738 | continue 739 | } 740 | t := reflect.ValueOf(item.value).Type() 741 | value := reflect.New(t) 742 | err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface()) 743 | if _, ok := err.(*yaml.TypeError); !ok { 744 | c.Assert(err, IsNil) 745 | } 746 | c.Assert(value.Elem().Interface(), DeepEquals, item.value) 747 | } 748 | } 749 | 750 | var decoderTests = []struct { 751 | data string 752 | values []interface{} 753 | }{{ 754 | "", 755 | nil, 756 | }, { 757 | "a: b", 758 | []interface{}{ 759 | map[interface{}]interface{}{"a": "b"}, 760 | }, 761 | }, { 762 | "---\na: b\n...\n", 763 | []interface{}{ 764 | map[interface{}]interface{}{"a": "b"}, 765 | }, 766 | }, { 767 | "---\n'hello'\n...\n---\ngoodbye\n...\n", 768 | []interface{}{ 769 | "hello", 770 | "goodbye", 771 | }, 772 | }} 773 | 774 | func (s *S) TestDecoder(c *C) { 775 | for i, item := range decoderTests { 776 | c.Logf("test %d: %q", i, item.data) 777 | var values []interface{} 778 | dec := yaml.NewDecoder(strings.NewReader(item.data)) 779 | for { 780 | var value interface{} 781 | err := dec.Decode(&value) 782 | if err == io.EOF { 783 | break 784 | } 785 | c.Assert(err, IsNil) 786 | values = append(values, value) 787 | } 788 | c.Assert(values, DeepEquals, item.values) 789 | } 790 | } 791 | 792 | type errReader struct{} 793 | 794 | func (errReader) Read([]byte) (int, error) { 795 | return 0, errors.New("some read error") 796 | } 797 | 798 | func (s *S) TestDecoderReadError(c *C) { 799 | err := yaml.NewDecoder(errReader{}).Decode(&struct{}{}) 800 | c.Assert(err, ErrorMatches, `yaml: input error: some read error`) 801 | } 802 | 803 | func (s *S) TestUnmarshalNaN(c *C) { 804 | value := map[string]interface{}{} 805 | err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) 806 | c.Assert(err, IsNil) 807 | c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) 808 | } 809 | 810 | var unmarshalErrorTests = []struct { 811 | data, error string 812 | }{ 813 | {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, 814 | {"v: [A,", "yaml: line 1: did not find expected node content"}, 815 | {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, 816 | {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, 817 | {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, 818 | {"value: -", "yaml: block sequence entries are not allowed in this context"}, 819 | {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, 820 | {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, 821 | {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, 822 | {"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`}, 823 | {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"}, 824 | } 825 | 826 | func (s *S) TestUnmarshalErrors(c *C) { 827 | for i, item := range unmarshalErrorTests { 828 | c.Logf("test %d: %q", i, item.data) 829 | var value interface{} 830 | err := yaml.Unmarshal([]byte(item.data), &value) 831 | c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 832 | } 833 | } 834 | 835 | func (s *S) TestDecoderErrors(c *C) { 836 | for _, item := range unmarshalErrorTests { 837 | var value interface{} 838 | err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value) 839 | c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 840 | } 841 | } 842 | 843 | var unmarshalerTests = []struct { 844 | data, tag string 845 | value interface{} 846 | }{ 847 | {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, 848 | {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, 849 | {"_: 10", "!!int", 10}, 850 | {"_: null", "!!null", nil}, 851 | {`_: BAR!`, "!!str", "BAR!"}, 852 | {`_: "BAR!"`, "!!str", "BAR!"}, 853 | {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, 854 | {`_: ""`, "!!str", ""}, 855 | } 856 | 857 | var unmarshalerResult = map[int]error{} 858 | 859 | type unmarshalerType struct { 860 | value interface{} 861 | } 862 | 863 | func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { 864 | if err := unmarshal(&o.value); err != nil { 865 | return err 866 | } 867 | if i, ok := o.value.(int); ok { 868 | if result, ok := unmarshalerResult[i]; ok { 869 | return result 870 | } 871 | } 872 | return nil 873 | } 874 | 875 | type unmarshalerPointer struct { 876 | Field *unmarshalerType "_" 877 | } 878 | 879 | type unmarshalerValue struct { 880 | Field unmarshalerType "_" 881 | } 882 | 883 | func (s *S) TestUnmarshalerPointerField(c *C) { 884 | for _, item := range unmarshalerTests { 885 | obj := &unmarshalerPointer{} 886 | err := yaml.Unmarshal([]byte(item.data), obj) 887 | c.Assert(err, IsNil) 888 | if item.value == nil { 889 | c.Assert(obj.Field, IsNil) 890 | } else { 891 | c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 892 | c.Assert(obj.Field.value, DeepEquals, item.value) 893 | } 894 | } 895 | } 896 | 897 | func (s *S) TestUnmarshalerValueField(c *C) { 898 | for _, item := range unmarshalerTests { 899 | obj := &unmarshalerValue{} 900 | err := yaml.Unmarshal([]byte(item.data), obj) 901 | c.Assert(err, IsNil) 902 | c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 903 | c.Assert(obj.Field.value, DeepEquals, item.value) 904 | } 905 | } 906 | 907 | func (s *S) TestUnmarshalerWholeDocument(c *C) { 908 | obj := &unmarshalerType{} 909 | err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) 910 | c.Assert(err, IsNil) 911 | value, ok := obj.value.(map[interface{}]interface{}) 912 | c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) 913 | c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) 914 | } 915 | 916 | func (s *S) TestUnmarshalerTypeError(c *C) { 917 | unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} 918 | unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} 919 | defer func() { 920 | delete(unmarshalerResult, 2) 921 | delete(unmarshalerResult, 4) 922 | }() 923 | 924 | type T struct { 925 | Before int 926 | After int 927 | M map[string]*unmarshalerType 928 | } 929 | var v T 930 | data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` 931 | err := yaml.Unmarshal([]byte(data), &v) 932 | c.Assert(err, ErrorMatches, ""+ 933 | "yaml: unmarshal errors:\n"+ 934 | " line 1: cannot unmarshal !!str `A` into int\n"+ 935 | " foo\n"+ 936 | " bar\n"+ 937 | " line 1: cannot unmarshal !!str `B` into int") 938 | c.Assert(v.M["abc"], NotNil) 939 | c.Assert(v.M["def"], IsNil) 940 | c.Assert(v.M["ghi"], NotNil) 941 | c.Assert(v.M["jkl"], IsNil) 942 | 943 | c.Assert(v.M["abc"].value, Equals, 1) 944 | c.Assert(v.M["ghi"].value, Equals, 3) 945 | } 946 | 947 | type proxyTypeError struct{} 948 | 949 | func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { 950 | var s string 951 | var a int32 952 | var b int64 953 | if err := unmarshal(&s); err != nil { 954 | panic(err) 955 | } 956 | if s == "a" { 957 | if err := unmarshal(&b); err == nil { 958 | panic("should have failed") 959 | } 960 | return unmarshal(&a) 961 | } 962 | if err := unmarshal(&a); err == nil { 963 | panic("should have failed") 964 | } 965 | return unmarshal(&b) 966 | } 967 | 968 | func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { 969 | type T struct { 970 | Before int 971 | After int 972 | M map[string]*proxyTypeError 973 | } 974 | var v T 975 | data := `{before: A, m: {abc: a, def: b}, after: B}` 976 | err := yaml.Unmarshal([]byte(data), &v) 977 | c.Assert(err, ErrorMatches, ""+ 978 | "yaml: unmarshal errors:\n"+ 979 | " line 1: cannot unmarshal !!str `A` into int\n"+ 980 | " line 1: cannot unmarshal !!str `a` into int32\n"+ 981 | " line 1: cannot unmarshal !!str `b` into int64\n"+ 982 | " line 1: cannot unmarshal !!str `B` into int") 983 | } 984 | 985 | type failingUnmarshaler struct{} 986 | 987 | var failingErr = errors.New("failingErr") 988 | 989 | func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 990 | return failingErr 991 | } 992 | 993 | func (s *S) TestUnmarshalerError(c *C) { 994 | err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) 995 | c.Assert(err, Equals, failingErr) 996 | } 997 | 998 | type sliceUnmarshaler []int 999 | 1000 | func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 1001 | var slice []int 1002 | err := unmarshal(&slice) 1003 | if err == nil { 1004 | *su = slice 1005 | return nil 1006 | } 1007 | 1008 | var intVal int 1009 | err = unmarshal(&intVal) 1010 | if err == nil { 1011 | *su = []int{intVal} 1012 | return nil 1013 | } 1014 | 1015 | return err 1016 | } 1017 | 1018 | func (s *S) TestUnmarshalerRetry(c *C) { 1019 | var su sliceUnmarshaler 1020 | err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) 1021 | c.Assert(err, IsNil) 1022 | c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) 1023 | 1024 | err = yaml.Unmarshal([]byte("1"), &su) 1025 | c.Assert(err, IsNil) 1026 | c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) 1027 | } 1028 | 1029 | // From http://yaml.org/type/merge.html 1030 | var mergeTests = ` 1031 | anchors: 1032 | list: 1033 | - &CENTER { "x": 1, "y": 2 } 1034 | - &LEFT { "x": 0, "y": 2 } 1035 | - &BIG { "r": 10 } 1036 | - &SMALL { "r": 1 } 1037 | 1038 | # All the following maps are equal: 1039 | 1040 | plain: 1041 | # Explicit keys 1042 | "x": 1 1043 | "y": 2 1044 | "r": 10 1045 | label: center/big 1046 | 1047 | mergeOne: 1048 | # Merge one map 1049 | << : *CENTER 1050 | "r": 10 1051 | label: center/big 1052 | 1053 | mergeMultiple: 1054 | # Merge multiple maps 1055 | << : [ *CENTER, *BIG ] 1056 | label: center/big 1057 | 1058 | override: 1059 | # Override 1060 | << : [ *BIG, *LEFT, *SMALL ] 1061 | "x": 1 1062 | label: center/big 1063 | 1064 | shortTag: 1065 | # Explicit short merge tag 1066 | !!merge "<<" : [ *CENTER, *BIG ] 1067 | label: center/big 1068 | 1069 | longTag: 1070 | # Explicit merge long tag 1071 | ! "<<" : [ *CENTER, *BIG ] 1072 | label: center/big 1073 | 1074 | inlineMap: 1075 | # Inlined map 1076 | << : {"x": 1, "y": 2, "r": 10} 1077 | label: center/big 1078 | 1079 | inlineSequenceMap: 1080 | # Inlined map in sequence 1081 | << : [ *CENTER, {"r": 10} ] 1082 | label: center/big 1083 | ` 1084 | 1085 | func (s *S) TestMerge(c *C) { 1086 | var want = map[interface{}]interface{}{ 1087 | "x": 1, 1088 | "y": 2, 1089 | "r": 10, 1090 | "label": "center/big", 1091 | } 1092 | 1093 | var m map[interface{}]interface{} 1094 | err := yaml.Unmarshal([]byte(mergeTests), &m) 1095 | c.Assert(err, IsNil) 1096 | for name, test := range m { 1097 | if name == "anchors" { 1098 | continue 1099 | } 1100 | c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) 1101 | } 1102 | } 1103 | 1104 | func (s *S) TestMergeStruct(c *C) { 1105 | type Data struct { 1106 | X, Y, R int 1107 | Label string 1108 | } 1109 | want := Data{1, 2, 10, "center/big"} 1110 | 1111 | var m map[string]Data 1112 | err := yaml.Unmarshal([]byte(mergeTests), &m) 1113 | c.Assert(err, IsNil) 1114 | for name, test := range m { 1115 | if name == "anchors" { 1116 | continue 1117 | } 1118 | c.Assert(test, Equals, want, Commentf("test %q failed", name)) 1119 | } 1120 | } 1121 | 1122 | var unmarshalNullTests = []func() interface{}{ 1123 | func() interface{} { var v interface{}; v = "v"; return &v }, 1124 | func() interface{} { var s = "s"; return &s }, 1125 | func() interface{} { var s = "s"; sptr := &s; return &sptr }, 1126 | func() interface{} { var i = 1; return &i }, 1127 | func() interface{} { var i = 1; iptr := &i; return &iptr }, 1128 | func() interface{} { m := map[string]int{"s": 1}; return &m }, 1129 | func() interface{} { m := map[string]int{"s": 1}; return m }, 1130 | } 1131 | 1132 | func (s *S) TestUnmarshalNull(c *C) { 1133 | for _, test := range unmarshalNullTests { 1134 | item := test() 1135 | zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() 1136 | err := yaml.Unmarshal([]byte("null"), item) 1137 | c.Assert(err, IsNil) 1138 | if reflect.TypeOf(item).Kind() == reflect.Map { 1139 | c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) 1140 | } else { 1141 | c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) 1142 | } 1143 | } 1144 | } 1145 | 1146 | func (s *S) TestUnmarshalSliceOnPreset(c *C) { 1147 | // Issue #48. 1148 | v := struct{ A []int }{[]int{1}} 1149 | yaml.Unmarshal([]byte("a: [2]"), &v) 1150 | c.Assert(v.A, DeepEquals, []int{2}) 1151 | } 1152 | 1153 | var unmarshalStrictTests = []struct { 1154 | data string 1155 | value interface{} 1156 | error string 1157 | }{{ 1158 | data: "a: 1\nc: 2\n", 1159 | value: struct{ A, B int }{A: 1}, 1160 | error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`, 1161 | }, { 1162 | data: "a: 1\nb: 2\na: 3\n", 1163 | value: struct{ A, B int }{A: 3, B: 2}, 1164 | error: `yaml: unmarshal errors:\n line 3: field a already set in type struct { A int; B int }`, 1165 | }, { 1166 | data: "c: 3\na: 1\nb: 2\nc: 4\n", 1167 | value: struct { 1168 | A int 1169 | inlineB `yaml:",inline"` 1170 | }{ 1171 | A: 1, 1172 | inlineB: inlineB{ 1173 | B: 2, 1174 | inlineC: inlineC{ 1175 | C: 4, 1176 | }, 1177 | }, 1178 | }, 1179 | error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`, 1180 | }, { 1181 | data: "c: 0\na: 1\nb: 2\nc: 1\n", 1182 | value: struct { 1183 | A int 1184 | inlineB `yaml:",inline"` 1185 | }{ 1186 | A: 1, 1187 | inlineB: inlineB{ 1188 | B: 2, 1189 | inlineC: inlineC{ 1190 | C: 1, 1191 | }, 1192 | }, 1193 | }, 1194 | error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`, 1195 | }, { 1196 | data: "c: 1\na: 1\nb: 2\nc: 3\n", 1197 | value: struct { 1198 | A int 1199 | M map[string]interface{} `yaml:",inline"` 1200 | }{ 1201 | A: 1, 1202 | M: map[string]interface{}{ 1203 | "b": 2, 1204 | "c": 3, 1205 | }, 1206 | }, 1207 | error: `yaml: unmarshal errors:\n line 4: key "c" already set in map`, 1208 | }, { 1209 | data: "a: 1\n9: 2\nnull: 3\n9: 4", 1210 | value: map[interface{}]interface{}{ 1211 | "a": 1, 1212 | nil: 3, 1213 | 9: 4, 1214 | }, 1215 | error: `yaml: unmarshal errors:\n line 4: key 9 already set in map`, 1216 | }} 1217 | 1218 | func (s *S) TestUnmarshalStrict(c *C) { 1219 | for i, item := range unmarshalStrictTests { 1220 | c.Logf("test %d: %q", i, item.data) 1221 | // First test that normal Unmarshal unmarshals to the expected value. 1222 | t := reflect.ValueOf(item.value).Type() 1223 | value := reflect.New(t) 1224 | err := yaml.Unmarshal([]byte(item.data), value.Interface()) 1225 | c.Assert(err, Equals, nil) 1226 | c.Assert(value.Elem().Interface(), DeepEquals, item.value) 1227 | 1228 | // Then test that UnmarshalStrict fails on the same thing. 1229 | t = reflect.ValueOf(item.value).Type() 1230 | value = reflect.New(t) 1231 | err = yaml.UnmarshalStrict([]byte(item.data), value.Interface()) 1232 | c.Assert(err, ErrorMatches, item.error) 1233 | } 1234 | } 1235 | 1236 | type textUnmarshaler struct { 1237 | S string 1238 | } 1239 | 1240 | func (t *textUnmarshaler) UnmarshalText(s []byte) error { 1241 | t.S = string(s) 1242 | return nil 1243 | } 1244 | 1245 | //var data []byte 1246 | //func init() { 1247 | // var err error 1248 | // data, err = ioutil.ReadFile("/tmp/file.yaml") 1249 | // if err != nil { 1250 | // panic(err) 1251 | // } 1252 | //} 1253 | // 1254 | //func (s *S) BenchmarkUnmarshal(c *C) { 1255 | // var err error 1256 | // for i := 0; i < c.N; i++ { 1257 | // var v map[string]interface{} 1258 | // err = yaml.Unmarshal(data, &v) 1259 | // } 1260 | // if err != nil { 1261 | // panic(err) 1262 | // } 1263 | //} 1264 | // 1265 | //func (s *S) BenchmarkMarshal(c *C) { 1266 | // var v map[string]interface{} 1267 | // yaml.Unmarshal(data, &v) 1268 | // c.ResetTimer() 1269 | // for i := 0; i < c.N; i++ { 1270 | // yaml.Marshal(&v) 1271 | // } 1272 | //} 1273 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/encode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding" 5 | "fmt" 6 | "io" 7 | "reflect" 8 | "regexp" 9 | "sort" 10 | "strconv" 11 | "strings" 12 | "time" 13 | "unicode/utf8" 14 | ) 15 | 16 | type encoder struct { 17 | emitter yaml_emitter_t 18 | event yaml_event_t 19 | out []byte 20 | flow bool 21 | // doneInit holds whether the initial stream_start_event has been 22 | // emitted. 23 | doneInit bool 24 | } 25 | 26 | func newEncoder() *encoder { 27 | e := &encoder{} 28 | yaml_emitter_initialize(&e.emitter) 29 | yaml_emitter_set_output_string(&e.emitter, &e.out) 30 | yaml_emitter_set_unicode(&e.emitter, true) 31 | return e 32 | } 33 | 34 | func newEncoderWithWriter(w io.Writer) *encoder { 35 | e := &encoder{} 36 | yaml_emitter_initialize(&e.emitter) 37 | yaml_emitter_set_output_writer(&e.emitter, w) 38 | yaml_emitter_set_unicode(&e.emitter, true) 39 | return e 40 | } 41 | 42 | func (e *encoder) init() { 43 | if e.doneInit { 44 | return 45 | } 46 | yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) 47 | e.emit() 48 | e.doneInit = true 49 | } 50 | 51 | func (e *encoder) finish() { 52 | e.emitter.open_ended = false 53 | yaml_stream_end_event_initialize(&e.event) 54 | e.emit() 55 | } 56 | 57 | func (e *encoder) destroy() { 58 | yaml_emitter_delete(&e.emitter) 59 | } 60 | 61 | func (e *encoder) emit() { 62 | // This will internally delete the e.event value. 63 | e.must(yaml_emitter_emit(&e.emitter, &e.event)) 64 | } 65 | 66 | func (e *encoder) must(ok bool) { 67 | if !ok { 68 | msg := e.emitter.problem 69 | if msg == "" { 70 | msg = "unknown problem generating YAML content" 71 | } 72 | failf("%s", msg) 73 | } 74 | } 75 | 76 | func (e *encoder) marshalDoc(tag string, in reflect.Value) { 77 | e.init() 78 | yaml_document_start_event_initialize(&e.event, nil, nil, true) 79 | e.emit() 80 | e.marshal(tag, in) 81 | yaml_document_end_event_initialize(&e.event, true) 82 | e.emit() 83 | } 84 | 85 | func (e *encoder) marshal(tag string, in reflect.Value) { 86 | if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { 87 | e.nilv() 88 | return 89 | } 90 | iface := in.Interface() 91 | switch m := iface.(type) { 92 | case time.Time, *time.Time: 93 | // Although time.Time implements TextMarshaler, 94 | // we don't want to treat it as a string for YAML 95 | // purposes because YAML has special support for 96 | // timestamps. 97 | case Marshaler: 98 | v, err := m.MarshalYAML() 99 | if err != nil { 100 | fail(err) 101 | } 102 | if v == nil { 103 | e.nilv() 104 | return 105 | } 106 | in = reflect.ValueOf(v) 107 | case encoding.TextMarshaler: 108 | text, err := m.MarshalText() 109 | if err != nil { 110 | fail(err) 111 | } 112 | in = reflect.ValueOf(string(text)) 113 | case nil: 114 | e.nilv() 115 | return 116 | } 117 | switch in.Kind() { 118 | case reflect.Interface: 119 | e.marshal(tag, in.Elem()) 120 | case reflect.Map: 121 | e.mapv(tag, in) 122 | case reflect.Ptr: 123 | if in.Type() == ptrTimeType { 124 | e.timev(tag, in.Elem()) 125 | } else { 126 | e.marshal(tag, in.Elem()) 127 | } 128 | case reflect.Struct: 129 | if in.Type() == timeType { 130 | e.timev(tag, in) 131 | } else { 132 | e.structv(tag, in) 133 | } 134 | case reflect.Slice: 135 | if in.Type().Elem() == mapItemType { 136 | e.itemsv(tag, in) 137 | } else { 138 | e.slicev(tag, in) 139 | } 140 | case reflect.String: 141 | e.stringv(tag, in) 142 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 143 | if in.Type() == durationType { 144 | e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) 145 | } else { 146 | e.intv(tag, in) 147 | } 148 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 149 | e.uintv(tag, in) 150 | case reflect.Float32, reflect.Float64: 151 | e.floatv(tag, in) 152 | case reflect.Bool: 153 | e.boolv(tag, in) 154 | default: 155 | panic("cannot marshal type: " + in.Type().String()) 156 | } 157 | } 158 | 159 | func (e *encoder) mapv(tag string, in reflect.Value) { 160 | e.mappingv(tag, func() { 161 | keys := keyList(in.MapKeys()) 162 | sort.Sort(keys) 163 | for _, k := range keys { 164 | e.marshal("", k) 165 | e.marshal("", in.MapIndex(k)) 166 | } 167 | }) 168 | } 169 | 170 | func (e *encoder) itemsv(tag string, in reflect.Value) { 171 | e.mappingv(tag, func() { 172 | slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) 173 | for _, item := range slice { 174 | e.marshal("", reflect.ValueOf(item.Key)) 175 | e.marshal("", reflect.ValueOf(item.Value)) 176 | } 177 | }) 178 | } 179 | 180 | func (e *encoder) structv(tag string, in reflect.Value) { 181 | sinfo, err := getStructInfo(in.Type()) 182 | if err != nil { 183 | panic(err) 184 | } 185 | e.mappingv(tag, func() { 186 | for _, info := range sinfo.FieldsList { 187 | var value reflect.Value 188 | if info.Inline == nil { 189 | value = in.Field(info.Num) 190 | } else { 191 | value = in.FieldByIndex(info.Inline) 192 | } 193 | if info.OmitEmpty && isZero(value) { 194 | continue 195 | } 196 | e.marshal("", reflect.ValueOf(info.Key)) 197 | e.flow = info.Flow 198 | e.marshal("", value) 199 | } 200 | if sinfo.InlineMap >= 0 { 201 | m := in.Field(sinfo.InlineMap) 202 | if m.Len() > 0 { 203 | e.flow = false 204 | keys := keyList(m.MapKeys()) 205 | sort.Sort(keys) 206 | for _, k := range keys { 207 | if _, found := sinfo.FieldsMap[k.String()]; found { 208 | panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String())) 209 | } 210 | e.marshal("", k) 211 | e.flow = false 212 | e.marshal("", m.MapIndex(k)) 213 | } 214 | } 215 | } 216 | }) 217 | } 218 | 219 | func (e *encoder) mappingv(tag string, f func()) { 220 | implicit := tag == "" 221 | style := yaml_BLOCK_MAPPING_STYLE 222 | if e.flow { 223 | e.flow = false 224 | style = yaml_FLOW_MAPPING_STYLE 225 | } 226 | yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) 227 | e.emit() 228 | f() 229 | yaml_mapping_end_event_initialize(&e.event) 230 | e.emit() 231 | } 232 | 233 | func (e *encoder) slicev(tag string, in reflect.Value) { 234 | implicit := tag == "" 235 | style := yaml_BLOCK_SEQUENCE_STYLE 236 | if e.flow { 237 | e.flow = false 238 | style = yaml_FLOW_SEQUENCE_STYLE 239 | } 240 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 241 | e.emit() 242 | n := in.Len() 243 | for i := 0; i < n; i++ { 244 | e.marshal("", in.Index(i)) 245 | } 246 | e.must(yaml_sequence_end_event_initialize(&e.event)) 247 | e.emit() 248 | } 249 | 250 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. 251 | // 252 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported 253 | // in YAML 1.2 and by this package, but these should be marshalled quoted for 254 | // the time being for compatibility with other parsers. 255 | func isBase60Float(s string) (result bool) { 256 | // Fast path. 257 | if s == "" { 258 | return false 259 | } 260 | c := s[0] 261 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { 262 | return false 263 | } 264 | // Do the full match. 265 | return base60float.MatchString(s) 266 | } 267 | 268 | // From http://yaml.org/type/float.html, except the regular expression there 269 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. 270 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) 271 | 272 | func (e *encoder) stringv(tag string, in reflect.Value) { 273 | var style yaml_scalar_style_t 274 | s := in.String() 275 | canUsePlain := true 276 | switch { 277 | case !utf8.ValidString(s): 278 | if tag == yaml_BINARY_TAG { 279 | failf("explicitly tagged !!binary data must be base64-encoded") 280 | } 281 | if tag != "" { 282 | failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) 283 | } 284 | // It can't be encoded directly as YAML so use a binary tag 285 | // and encode it as base64. 286 | tag = yaml_BINARY_TAG 287 | s = encodeBase64(s) 288 | case tag == "": 289 | // Check to see if it would resolve to a specific 290 | // tag when encoded unquoted. If it doesn't, 291 | // there's no need to quote it. 292 | rtag, _ := resolve("", s) 293 | canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s) 294 | } 295 | // Note: it's possible for user code to emit invalid YAML 296 | // if they explicitly specify a tag and a string containing 297 | // text that's incompatible with that tag. 298 | switch { 299 | case strings.Contains(s, "\n"): 300 | style = yaml_LITERAL_SCALAR_STYLE 301 | case canUsePlain: 302 | style = yaml_PLAIN_SCALAR_STYLE 303 | default: 304 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 305 | } 306 | e.emitScalar(s, "", tag, style) 307 | } 308 | 309 | func (e *encoder) boolv(tag string, in reflect.Value) { 310 | var s string 311 | if in.Bool() { 312 | s = "true" 313 | } else { 314 | s = "false" 315 | } 316 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 317 | } 318 | 319 | func (e *encoder) intv(tag string, in reflect.Value) { 320 | s := strconv.FormatInt(in.Int(), 10) 321 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 322 | } 323 | 324 | func (e *encoder) uintv(tag string, in reflect.Value) { 325 | s := strconv.FormatUint(in.Uint(), 10) 326 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 327 | } 328 | 329 | func (e *encoder) timev(tag string, in reflect.Value) { 330 | t := in.Interface().(time.Time) 331 | if tag == "" { 332 | tag = yaml_TIMESTAMP_TAG 333 | } 334 | e.emitScalar(t.Format(time.RFC3339Nano), "", tag, yaml_PLAIN_SCALAR_STYLE) 335 | } 336 | 337 | func (e *encoder) floatv(tag string, in reflect.Value) { 338 | s := strconv.FormatFloat(in.Float(), 'g', -1, 64) 339 | switch s { 340 | case "+Inf": 341 | s = ".inf" 342 | case "-Inf": 343 | s = "-.inf" 344 | case "NaN": 345 | s = ".nan" 346 | } 347 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 348 | } 349 | 350 | func (e *encoder) nilv() { 351 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) 352 | } 353 | 354 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { 355 | implicit := tag == "" 356 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) 357 | e.emit() 358 | } 359 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/encode_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math" 7 | "strconv" 8 | "strings" 9 | "time" 10 | 11 | "net" 12 | "os" 13 | 14 | . "gopkg.in/check.v1" 15 | "gopkg.in/yaml.v2" 16 | ) 17 | 18 | var marshalIntTest = 123 19 | 20 | var marshalTests = []struct { 21 | value interface{} 22 | data string 23 | }{ 24 | { 25 | nil, 26 | "null\n", 27 | }, { 28 | (*marshalerType)(nil), 29 | "null\n", 30 | }, { 31 | &struct{}{}, 32 | "{}\n", 33 | }, { 34 | map[string]string{"v": "hi"}, 35 | "v: hi\n", 36 | }, { 37 | map[string]interface{}{"v": "hi"}, 38 | "v: hi\n", 39 | }, { 40 | map[string]string{"v": "true"}, 41 | "v: \"true\"\n", 42 | }, { 43 | map[string]string{"v": "false"}, 44 | "v: \"false\"\n", 45 | }, { 46 | map[string]interface{}{"v": true}, 47 | "v: true\n", 48 | }, { 49 | map[string]interface{}{"v": false}, 50 | "v: false\n", 51 | }, { 52 | map[string]interface{}{"v": 10}, 53 | "v: 10\n", 54 | }, { 55 | map[string]interface{}{"v": -10}, 56 | "v: -10\n", 57 | }, { 58 | map[string]uint{"v": 42}, 59 | "v: 42\n", 60 | }, { 61 | map[string]interface{}{"v": int64(4294967296)}, 62 | "v: 4294967296\n", 63 | }, { 64 | map[string]int64{"v": int64(4294967296)}, 65 | "v: 4294967296\n", 66 | }, { 67 | map[string]uint64{"v": 4294967296}, 68 | "v: 4294967296\n", 69 | }, { 70 | map[string]interface{}{"v": "10"}, 71 | "v: \"10\"\n", 72 | }, { 73 | map[string]interface{}{"v": 0.1}, 74 | "v: 0.1\n", 75 | }, { 76 | map[string]interface{}{"v": float64(0.1)}, 77 | "v: 0.1\n", 78 | }, { 79 | map[string]interface{}{"v": -0.1}, 80 | "v: -0.1\n", 81 | }, { 82 | map[string]interface{}{"v": math.Inf(+1)}, 83 | "v: .inf\n", 84 | }, { 85 | map[string]interface{}{"v": math.Inf(-1)}, 86 | "v: -.inf\n", 87 | }, { 88 | map[string]interface{}{"v": math.NaN()}, 89 | "v: .nan\n", 90 | }, { 91 | map[string]interface{}{"v": nil}, 92 | "v: null\n", 93 | }, { 94 | map[string]interface{}{"v": ""}, 95 | "v: \"\"\n", 96 | }, { 97 | map[string][]string{"v": []string{"A", "B"}}, 98 | "v:\n- A\n- B\n", 99 | }, { 100 | map[string][]string{"v": []string{"A", "B\nC"}}, 101 | "v:\n- A\n- |-\n B\n C\n", 102 | }, { 103 | map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, 104 | "v:\n- A\n- 1\n- B:\n - 2\n - 3\n", 105 | }, { 106 | map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 107 | "a:\n b: c\n", 108 | }, { 109 | map[string]interface{}{"a": "-"}, 110 | "a: '-'\n", 111 | }, 112 | 113 | // Simple values. 114 | { 115 | &marshalIntTest, 116 | "123\n", 117 | }, 118 | 119 | // Structures 120 | { 121 | &struct{ Hello string }{"world"}, 122 | "hello: world\n", 123 | }, { 124 | &struct { 125 | A struct { 126 | B string 127 | } 128 | }{struct{ B string }{"c"}}, 129 | "a:\n b: c\n", 130 | }, { 131 | &struct { 132 | A *struct { 133 | B string 134 | } 135 | }{&struct{ B string }{"c"}}, 136 | "a:\n b: c\n", 137 | }, { 138 | &struct { 139 | A *struct { 140 | B string 141 | } 142 | }{}, 143 | "a: null\n", 144 | }, { 145 | &struct{ A int }{1}, 146 | "a: 1\n", 147 | }, { 148 | &struct{ A []int }{[]int{1, 2}}, 149 | "a:\n- 1\n- 2\n", 150 | }, { 151 | &struct { 152 | B int "a" 153 | }{1}, 154 | "a: 1\n", 155 | }, { 156 | &struct{ A bool }{true}, 157 | "a: true\n", 158 | }, 159 | 160 | // Conditional flag 161 | { 162 | &struct { 163 | A int "a,omitempty" 164 | B int "b,omitempty" 165 | }{1, 0}, 166 | "a: 1\n", 167 | }, { 168 | &struct { 169 | A int "a,omitempty" 170 | B int "b,omitempty" 171 | }{0, 0}, 172 | "{}\n", 173 | }, { 174 | &struct { 175 | A *struct{ X, y int } "a,omitempty,flow" 176 | }{&struct{ X, y int }{1, 2}}, 177 | "a: {x: 1}\n", 178 | }, { 179 | &struct { 180 | A *struct{ X, y int } "a,omitempty,flow" 181 | }{nil}, 182 | "{}\n", 183 | }, { 184 | &struct { 185 | A *struct{ X, y int } "a,omitempty,flow" 186 | }{&struct{ X, y int }{}}, 187 | "a: {x: 0}\n", 188 | }, { 189 | &struct { 190 | A struct{ X, y int } "a,omitempty,flow" 191 | }{struct{ X, y int }{1, 2}}, 192 | "a: {x: 1}\n", 193 | }, { 194 | &struct { 195 | A struct{ X, y int } "a,omitempty,flow" 196 | }{struct{ X, y int }{0, 1}}, 197 | "{}\n", 198 | }, { 199 | &struct { 200 | A float64 "a,omitempty" 201 | B float64 "b,omitempty" 202 | }{1, 0}, 203 | "a: 1\n", 204 | }, 205 | { 206 | &struct { 207 | T1 time.Time "t1,omitempty" 208 | T2 time.Time "t2,omitempty" 209 | T3 *time.Time "t3,omitempty" 210 | T4 *time.Time "t4,omitempty" 211 | }{ 212 | T2: time.Date(2018, 1, 9, 10, 40, 47, 0, time.UTC), 213 | T4: newTime(time.Date(2098, 1, 9, 10, 40, 47, 0, time.UTC)), 214 | }, 215 | "t2: !!timestamp 2018-01-09T10:40:47Z\nt4: !!timestamp 2098-01-09T10:40:47Z\n", 216 | }, 217 | // Nil interface that implements Marshaler. 218 | { 219 | map[string]yaml.Marshaler{ 220 | "a": nil, 221 | }, 222 | "a: null\n", 223 | }, 224 | 225 | // Flow flag 226 | { 227 | &struct { 228 | A []int "a,flow" 229 | }{[]int{1, 2}}, 230 | "a: [1, 2]\n", 231 | }, { 232 | &struct { 233 | A map[string]string "a,flow" 234 | }{map[string]string{"b": "c", "d": "e"}}, 235 | "a: {b: c, d: e}\n", 236 | }, { 237 | &struct { 238 | A struct { 239 | B, D string 240 | } "a,flow" 241 | }{struct{ B, D string }{"c", "e"}}, 242 | "a: {b: c, d: e}\n", 243 | }, 244 | 245 | // Unexported field 246 | { 247 | &struct { 248 | u int 249 | A int 250 | }{0, 1}, 251 | "a: 1\n", 252 | }, 253 | 254 | // Ignored field 255 | { 256 | &struct { 257 | A int 258 | B int "-" 259 | }{1, 2}, 260 | "a: 1\n", 261 | }, 262 | 263 | // Struct inlining 264 | { 265 | &struct { 266 | A int 267 | C inlineB `yaml:",inline"` 268 | }{1, inlineB{2, inlineC{3}}}, 269 | "a: 1\nb: 2\nc: 3\n", 270 | }, 271 | 272 | // Map inlining 273 | { 274 | &struct { 275 | A int 276 | C map[string]int `yaml:",inline"` 277 | }{1, map[string]int{"b": 2, "c": 3}}, 278 | "a: 1\nb: 2\nc: 3\n", 279 | }, 280 | 281 | // Duration 282 | { 283 | map[string]time.Duration{"a": 3 * time.Second}, 284 | "a: 3s\n", 285 | }, 286 | 287 | // Issue #24: bug in map merging logic. 288 | { 289 | map[string]string{"a": ""}, 290 | "a: \n", 291 | }, 292 | 293 | // Issue #34: marshal unsupported base 60 floats quoted for compatibility 294 | // with old YAML 1.1 parsers. 295 | { 296 | map[string]string{"a": "1:1"}, 297 | "a: \"1:1\"\n", 298 | }, 299 | 300 | // Binary data. 301 | { 302 | map[string]string{"a": "\x00"}, 303 | "a: \"\\0\"\n", 304 | }, { 305 | map[string]string{"a": "\x80\x81\x82"}, 306 | "a: !!binary gIGC\n", 307 | }, { 308 | map[string]string{"a": strings.Repeat("\x90", 54)}, 309 | "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 310 | }, 311 | 312 | // Ordered maps. 313 | { 314 | &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, 315 | "b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n", 316 | }, 317 | 318 | // Encode unicode as utf-8 rather than in escaped form. 319 | { 320 | map[string]string{"a": "你好"}, 321 | "a: 你好\n", 322 | }, 323 | 324 | // Support encoding.TextMarshaler. 325 | { 326 | map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, 327 | "a: 1.2.3.4\n", 328 | }, 329 | // time.Time gets a timestamp tag. 330 | { 331 | map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, 332 | "a: !!timestamp 2015-02-24T18:19:39Z\n", 333 | }, 334 | { 335 | map[string]*time.Time{"a": newTime(time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC))}, 336 | "a: !!timestamp 2015-02-24T18:19:39Z\n", 337 | }, 338 | // Ensure timestamp-like strings are quoted. 339 | { 340 | map[string]string{"a": "2015-02-24T18:19:39Z"}, 341 | "a: \"2015-02-24T18:19:39Z\"\n", 342 | }, 343 | 344 | // Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible). 345 | { 346 | map[string]string{"a": "b: c"}, 347 | "a: 'b: c'\n", 348 | }, 349 | 350 | // Containing hash mark ('#') in string should be quoted 351 | { 352 | map[string]string{"a": "Hello #comment"}, 353 | "a: 'Hello #comment'\n", 354 | }, 355 | { 356 | map[string]string{"a": "你好 #comment"}, 357 | "a: '你好 #comment'\n", 358 | }, 359 | } 360 | 361 | func (s *S) TestMarshal(c *C) { 362 | defer os.Setenv("TZ", os.Getenv("TZ")) 363 | os.Setenv("TZ", "UTC") 364 | for i, item := range marshalTests { 365 | c.Logf("test %d: %q", i, item.data) 366 | data, err := yaml.Marshal(item.value) 367 | c.Assert(err, IsNil) 368 | c.Assert(string(data), Equals, item.data) 369 | } 370 | } 371 | 372 | func (s *S) TestEncoderSingleDocument(c *C) { 373 | for i, item := range marshalTests { 374 | c.Logf("test %d. %q", i, item.data) 375 | var buf bytes.Buffer 376 | enc := yaml.NewEncoder(&buf) 377 | err := enc.Encode(item.value) 378 | c.Assert(err, Equals, nil) 379 | err = enc.Close() 380 | c.Assert(err, Equals, nil) 381 | c.Assert(buf.String(), Equals, item.data) 382 | } 383 | } 384 | 385 | func (s *S) TestEncoderMultipleDocuments(c *C) { 386 | var buf bytes.Buffer 387 | enc := yaml.NewEncoder(&buf) 388 | err := enc.Encode(map[string]string{"a": "b"}) 389 | c.Assert(err, Equals, nil) 390 | err = enc.Encode(map[string]string{"c": "d"}) 391 | c.Assert(err, Equals, nil) 392 | err = enc.Close() 393 | c.Assert(err, Equals, nil) 394 | c.Assert(buf.String(), Equals, "a: b\n---\nc: d\n") 395 | } 396 | 397 | func (s *S) TestEncoderWriteError(c *C) { 398 | enc := yaml.NewEncoder(errorWriter{}) 399 | err := enc.Encode(map[string]string{"a": "b"}) 400 | c.Assert(err, ErrorMatches, `yaml: write error: some write error`) // Data not flushed yet 401 | } 402 | 403 | type errorWriter struct{} 404 | 405 | func (errorWriter) Write([]byte) (int, error) { 406 | return 0, fmt.Errorf("some write error") 407 | } 408 | 409 | var marshalErrorTests = []struct { 410 | value interface{} 411 | error string 412 | panic string 413 | }{{ 414 | value: &struct { 415 | B int 416 | inlineB ",inline" 417 | }{1, inlineB{2, inlineC{3}}}, 418 | panic: `Duplicated key 'b' in struct struct \{ B int; .*`, 419 | }, { 420 | value: &struct { 421 | A int 422 | B map[string]int ",inline" 423 | }{1, map[string]int{"a": 2}}, 424 | panic: `Can't have key "a" in inlined map; conflicts with struct field`, 425 | }} 426 | 427 | func (s *S) TestMarshalErrors(c *C) { 428 | for _, item := range marshalErrorTests { 429 | if item.panic != "" { 430 | c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) 431 | } else { 432 | _, err := yaml.Marshal(item.value) 433 | c.Assert(err, ErrorMatches, item.error) 434 | } 435 | } 436 | } 437 | 438 | func (s *S) TestMarshalTypeCache(c *C) { 439 | var data []byte 440 | var err error 441 | func() { 442 | type T struct{ A int } 443 | data, err = yaml.Marshal(&T{}) 444 | c.Assert(err, IsNil) 445 | }() 446 | func() { 447 | type T struct{ B int } 448 | data, err = yaml.Marshal(&T{}) 449 | c.Assert(err, IsNil) 450 | }() 451 | c.Assert(string(data), Equals, "b: 0\n") 452 | } 453 | 454 | var marshalerTests = []struct { 455 | data string 456 | value interface{} 457 | }{ 458 | {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}}, 459 | {"_:\n- 1\n- A\n", []interface{}{1, "A"}}, 460 | {"_: 10\n", 10}, 461 | {"_: null\n", nil}, 462 | {"_: BAR!\n", "BAR!"}, 463 | } 464 | 465 | type marshalerType struct { 466 | value interface{} 467 | } 468 | 469 | func (o marshalerType) MarshalText() ([]byte, error) { 470 | panic("MarshalText called on type with MarshalYAML") 471 | } 472 | 473 | func (o marshalerType) MarshalYAML() (interface{}, error) { 474 | return o.value, nil 475 | } 476 | 477 | type marshalerValue struct { 478 | Field marshalerType "_" 479 | } 480 | 481 | func (s *S) TestMarshaler(c *C) { 482 | for _, item := range marshalerTests { 483 | obj := &marshalerValue{} 484 | obj.Field.value = item.value 485 | data, err := yaml.Marshal(obj) 486 | c.Assert(err, IsNil) 487 | c.Assert(string(data), Equals, string(item.data)) 488 | } 489 | } 490 | 491 | func (s *S) TestMarshalerWholeDocument(c *C) { 492 | obj := &marshalerType{} 493 | obj.value = map[string]string{"hello": "world!"} 494 | data, err := yaml.Marshal(obj) 495 | c.Assert(err, IsNil) 496 | c.Assert(string(data), Equals, "hello: world!\n") 497 | } 498 | 499 | type failingMarshaler struct{} 500 | 501 | func (ft *failingMarshaler) MarshalYAML() (interface{}, error) { 502 | return nil, failingErr 503 | } 504 | 505 | func (s *S) TestMarshalerError(c *C) { 506 | _, err := yaml.Marshal(&failingMarshaler{}) 507 | c.Assert(err, Equals, failingErr) 508 | } 509 | 510 | func (s *S) TestSortedOutput(c *C) { 511 | order := []interface{}{ 512 | false, 513 | true, 514 | 1, 515 | uint(1), 516 | 1.0, 517 | 1.1, 518 | 1.2, 519 | 2, 520 | uint(2), 521 | 2.0, 522 | 2.1, 523 | "", 524 | ".1", 525 | ".2", 526 | ".a", 527 | "1", 528 | "2", 529 | "a!10", 530 | "a/2", 531 | "a/10", 532 | "a~10", 533 | "ab/1", 534 | "b/1", 535 | "b/01", 536 | "b/2", 537 | "b/02", 538 | "b/3", 539 | "b/03", 540 | "b1", 541 | "b01", 542 | "b3", 543 | "c2.10", 544 | "c10.2", 545 | "d1", 546 | "d12", 547 | "d12a", 548 | } 549 | m := make(map[interface{}]int) 550 | for _, k := range order { 551 | m[k] = 1 552 | } 553 | data, err := yaml.Marshal(m) 554 | c.Assert(err, IsNil) 555 | out := "\n" + string(data) 556 | last := 0 557 | for i, k := range order { 558 | repr := fmt.Sprint(k) 559 | if s, ok := k.(string); ok { 560 | if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { 561 | repr = `"` + repr + `"` 562 | } 563 | } 564 | index := strings.Index(out, "\n"+repr+":") 565 | if index == -1 { 566 | c.Fatalf("%#v is not in the output: %#v", k, out) 567 | } 568 | if index < last { 569 | c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) 570 | } 571 | last = index 572 | } 573 | } 574 | 575 | func newTime(t time.Time) *time.Time { 576 | return &t 577 | } 578 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/example_embedded_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "gopkg.in/yaml.v2" 8 | ) 9 | 10 | // An example showing how to unmarshal embedded 11 | // structs from YAML. 12 | 13 | type StructA struct { 14 | A string `yaml:"a"` 15 | } 16 | 17 | type StructB struct { 18 | // Embedded structs are not treated as embedded in YAML by default. To do that, 19 | // add the ",inline" annotation below 20 | StructA `yaml:",inline"` 21 | B string `yaml:"b"` 22 | } 23 | 24 | var data = ` 25 | a: a string from struct A 26 | b: a string from struct B 27 | ` 28 | 29 | func ExampleUnmarshal_embedded() { 30 | var b StructB 31 | 32 | err := yaml.Unmarshal([]byte(data), &b) 33 | if err != nil { 34 | log.Fatalf("cannot unmarshal data: %v", err) 35 | } 36 | fmt.Println(b.A) 37 | fmt.Println(b.B) 38 | // Output: 39 | // a string from struct A 40 | // a string from struct B 41 | } 42 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/go.mod: -------------------------------------------------------------------------------- 1 | module "gopkg.in/yaml.v2" 2 | 3 | require ( 4 | "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 5 | ) 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/readerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // Set the reader error and return 0. 8 | func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { 9 | parser.error = yaml_READER_ERROR 10 | parser.problem = problem 11 | parser.problem_offset = offset 12 | parser.problem_value = value 13 | return false 14 | } 15 | 16 | // Byte order marks. 17 | const ( 18 | bom_UTF8 = "\xef\xbb\xbf" 19 | bom_UTF16LE = "\xff\xfe" 20 | bom_UTF16BE = "\xfe\xff" 21 | ) 22 | 23 | // Determine the input stream encoding by checking the BOM symbol. If no BOM is 24 | // found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. 25 | func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { 26 | // Ensure that we had enough bytes in the raw buffer. 27 | for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { 28 | if !yaml_parser_update_raw_buffer(parser) { 29 | return false 30 | } 31 | } 32 | 33 | // Determine the encoding. 34 | buf := parser.raw_buffer 35 | pos := parser.raw_buffer_pos 36 | avail := len(buf) - pos 37 | if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { 38 | parser.encoding = yaml_UTF16LE_ENCODING 39 | parser.raw_buffer_pos += 2 40 | parser.offset += 2 41 | } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { 42 | parser.encoding = yaml_UTF16BE_ENCODING 43 | parser.raw_buffer_pos += 2 44 | parser.offset += 2 45 | } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { 46 | parser.encoding = yaml_UTF8_ENCODING 47 | parser.raw_buffer_pos += 3 48 | parser.offset += 3 49 | } else { 50 | parser.encoding = yaml_UTF8_ENCODING 51 | } 52 | return true 53 | } 54 | 55 | // Update the raw buffer. 56 | func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { 57 | size_read := 0 58 | 59 | // Return if the raw buffer is full. 60 | if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { 61 | return true 62 | } 63 | 64 | // Return on EOF. 65 | if parser.eof { 66 | return true 67 | } 68 | 69 | // Move the remaining bytes in the raw buffer to the beginning. 70 | if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { 71 | copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) 72 | } 73 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] 74 | parser.raw_buffer_pos = 0 75 | 76 | // Call the read handler to fill the buffer. 77 | size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) 78 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] 79 | if err == io.EOF { 80 | parser.eof = true 81 | } else if err != nil { 82 | return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) 83 | } 84 | return true 85 | } 86 | 87 | // Ensure that the buffer contains at least `length` characters. 88 | // Return true on success, false on failure. 89 | // 90 | // The length is supposed to be significantly less that the buffer size. 91 | func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { 92 | if parser.read_handler == nil { 93 | panic("read handler must be set") 94 | } 95 | 96 | // If the EOF flag is set and the raw buffer is empty, do nothing. 97 | if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { 98 | return true 99 | } 100 | 101 | // Return if the buffer contains enough characters. 102 | if parser.unread >= length { 103 | return true 104 | } 105 | 106 | // Determine the input encoding if it is not known yet. 107 | if parser.encoding == yaml_ANY_ENCODING { 108 | if !yaml_parser_determine_encoding(parser) { 109 | return false 110 | } 111 | } 112 | 113 | // Move the unread characters to the beginning of the buffer. 114 | buffer_len := len(parser.buffer) 115 | if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { 116 | copy(parser.buffer, parser.buffer[parser.buffer_pos:]) 117 | buffer_len -= parser.buffer_pos 118 | parser.buffer_pos = 0 119 | } else if parser.buffer_pos == buffer_len { 120 | buffer_len = 0 121 | parser.buffer_pos = 0 122 | } 123 | 124 | // Open the whole buffer for writing, and cut it before returning. 125 | parser.buffer = parser.buffer[:cap(parser.buffer)] 126 | 127 | // Fill the buffer until it has enough characters. 128 | first := true 129 | for parser.unread < length { 130 | 131 | // Fill the raw buffer if necessary. 132 | if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { 133 | if !yaml_parser_update_raw_buffer(parser) { 134 | parser.buffer = parser.buffer[:buffer_len] 135 | return false 136 | } 137 | } 138 | first = false 139 | 140 | // Decode the raw buffer. 141 | inner: 142 | for parser.raw_buffer_pos != len(parser.raw_buffer) { 143 | var value rune 144 | var width int 145 | 146 | raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos 147 | 148 | // Decode the next character. 149 | switch parser.encoding { 150 | case yaml_UTF8_ENCODING: 151 | // Decode a UTF-8 character. Check RFC 3629 152 | // (http://www.ietf.org/rfc/rfc3629.txt) for more details. 153 | // 154 | // The following table (taken from the RFC) is used for 155 | // decoding. 156 | // 157 | // Char. number range | UTF-8 octet sequence 158 | // (hexadecimal) | (binary) 159 | // --------------------+------------------------------------ 160 | // 0000 0000-0000 007F | 0xxxxxxx 161 | // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 162 | // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 163 | // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 164 | // 165 | // Additionally, the characters in the range 0xD800-0xDFFF 166 | // are prohibited as they are reserved for use with UTF-16 167 | // surrogate pairs. 168 | 169 | // Determine the length of the UTF-8 sequence. 170 | octet := parser.raw_buffer[parser.raw_buffer_pos] 171 | switch { 172 | case octet&0x80 == 0x00: 173 | width = 1 174 | case octet&0xE0 == 0xC0: 175 | width = 2 176 | case octet&0xF0 == 0xE0: 177 | width = 3 178 | case octet&0xF8 == 0xF0: 179 | width = 4 180 | default: 181 | // The leading octet is invalid. 182 | return yaml_parser_set_reader_error(parser, 183 | "invalid leading UTF-8 octet", 184 | parser.offset, int(octet)) 185 | } 186 | 187 | // Check if the raw buffer contains an incomplete character. 188 | if width > raw_unread { 189 | if parser.eof { 190 | return yaml_parser_set_reader_error(parser, 191 | "incomplete UTF-8 octet sequence", 192 | parser.offset, -1) 193 | } 194 | break inner 195 | } 196 | 197 | // Decode the leading octet. 198 | switch { 199 | case octet&0x80 == 0x00: 200 | value = rune(octet & 0x7F) 201 | case octet&0xE0 == 0xC0: 202 | value = rune(octet & 0x1F) 203 | case octet&0xF0 == 0xE0: 204 | value = rune(octet & 0x0F) 205 | case octet&0xF8 == 0xF0: 206 | value = rune(octet & 0x07) 207 | default: 208 | value = 0 209 | } 210 | 211 | // Check and decode the trailing octets. 212 | for k := 1; k < width; k++ { 213 | octet = parser.raw_buffer[parser.raw_buffer_pos+k] 214 | 215 | // Check if the octet is valid. 216 | if (octet & 0xC0) != 0x80 { 217 | return yaml_parser_set_reader_error(parser, 218 | "invalid trailing UTF-8 octet", 219 | parser.offset+k, int(octet)) 220 | } 221 | 222 | // Decode the octet. 223 | value = (value << 6) + rune(octet&0x3F) 224 | } 225 | 226 | // Check the length of the sequence against the value. 227 | switch { 228 | case width == 1: 229 | case width == 2 && value >= 0x80: 230 | case width == 3 && value >= 0x800: 231 | case width == 4 && value >= 0x10000: 232 | default: 233 | return yaml_parser_set_reader_error(parser, 234 | "invalid length of a UTF-8 sequence", 235 | parser.offset, -1) 236 | } 237 | 238 | // Check the range of the value. 239 | if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { 240 | return yaml_parser_set_reader_error(parser, 241 | "invalid Unicode character", 242 | parser.offset, int(value)) 243 | } 244 | 245 | case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: 246 | var low, high int 247 | if parser.encoding == yaml_UTF16LE_ENCODING { 248 | low, high = 0, 1 249 | } else { 250 | low, high = 1, 0 251 | } 252 | 253 | // The UTF-16 encoding is not as simple as one might 254 | // naively think. Check RFC 2781 255 | // (http://www.ietf.org/rfc/rfc2781.txt). 256 | // 257 | // Normally, two subsequent bytes describe a Unicode 258 | // character. However a special technique (called a 259 | // surrogate pair) is used for specifying character 260 | // values larger than 0xFFFF. 261 | // 262 | // A surrogate pair consists of two pseudo-characters: 263 | // high surrogate area (0xD800-0xDBFF) 264 | // low surrogate area (0xDC00-0xDFFF) 265 | // 266 | // The following formulas are used for decoding 267 | // and encoding characters using surrogate pairs: 268 | // 269 | // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) 270 | // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) 271 | // W1 = 110110yyyyyyyyyy 272 | // W2 = 110111xxxxxxxxxx 273 | // 274 | // where U is the character value, W1 is the high surrogate 275 | // area, W2 is the low surrogate area. 276 | 277 | // Check for incomplete UTF-16 character. 278 | if raw_unread < 2 { 279 | if parser.eof { 280 | return yaml_parser_set_reader_error(parser, 281 | "incomplete UTF-16 character", 282 | parser.offset, -1) 283 | } 284 | break inner 285 | } 286 | 287 | // Get the character. 288 | value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + 289 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) 290 | 291 | // Check for unexpected low surrogate area. 292 | if value&0xFC00 == 0xDC00 { 293 | return yaml_parser_set_reader_error(parser, 294 | "unexpected low surrogate area", 295 | parser.offset, int(value)) 296 | } 297 | 298 | // Check for a high surrogate area. 299 | if value&0xFC00 == 0xD800 { 300 | width = 4 301 | 302 | // Check for incomplete surrogate pair. 303 | if raw_unread < 4 { 304 | if parser.eof { 305 | return yaml_parser_set_reader_error(parser, 306 | "incomplete UTF-16 surrogate pair", 307 | parser.offset, -1) 308 | } 309 | break inner 310 | } 311 | 312 | // Get the next character. 313 | value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + 314 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) 315 | 316 | // Check for a low surrogate area. 317 | if value2&0xFC00 != 0xDC00 { 318 | return yaml_parser_set_reader_error(parser, 319 | "expected low surrogate area", 320 | parser.offset+2, int(value2)) 321 | } 322 | 323 | // Generate the value of the surrogate pair. 324 | value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) 325 | } else { 326 | width = 2 327 | } 328 | 329 | default: 330 | panic("impossible") 331 | } 332 | 333 | // Check if the character is in the allowed range: 334 | // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) 335 | // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) 336 | // | [#x10000-#x10FFFF] (32 bit) 337 | switch { 338 | case value == 0x09: 339 | case value == 0x0A: 340 | case value == 0x0D: 341 | case value >= 0x20 && value <= 0x7E: 342 | case value == 0x85: 343 | case value >= 0xA0 && value <= 0xD7FF: 344 | case value >= 0xE000 && value <= 0xFFFD: 345 | case value >= 0x10000 && value <= 0x10FFFF: 346 | default: 347 | return yaml_parser_set_reader_error(parser, 348 | "control characters are not allowed", 349 | parser.offset, int(value)) 350 | } 351 | 352 | // Move the raw pointers. 353 | parser.raw_buffer_pos += width 354 | parser.offset += width 355 | 356 | // Finally put the character into the buffer. 357 | if value <= 0x7F { 358 | // 0000 0000-0000 007F . 0xxxxxxx 359 | parser.buffer[buffer_len+0] = byte(value) 360 | buffer_len += 1 361 | } else if value <= 0x7FF { 362 | // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx 363 | parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) 364 | parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) 365 | buffer_len += 2 366 | } else if value <= 0xFFFF { 367 | // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx 368 | parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) 369 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) 370 | parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) 371 | buffer_len += 3 372 | } else { 373 | // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 374 | parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) 375 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) 376 | parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) 377 | parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) 378 | buffer_len += 4 379 | } 380 | 381 | parser.unread++ 382 | } 383 | 384 | // On EOF, put NUL into the buffer and return. 385 | if parser.eof { 386 | parser.buffer[buffer_len] = 0 387 | buffer_len++ 388 | parser.unread++ 389 | break 390 | } 391 | } 392 | parser.buffer = parser.buffer[:buffer_len] 393 | return true 394 | } 395 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/resolve.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "math" 6 | "regexp" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | type resolveMapItem struct { 13 | value interface{} 14 | tag string 15 | } 16 | 17 | var resolveTable = make([]byte, 256) 18 | var resolveMap = make(map[string]resolveMapItem) 19 | 20 | func init() { 21 | t := resolveTable 22 | t[int('+')] = 'S' // Sign 23 | t[int('-')] = 'S' 24 | for _, c := range "0123456789" { 25 | t[int(c)] = 'D' // Digit 26 | } 27 | for _, c := range "yYnNtTfFoO~" { 28 | t[int(c)] = 'M' // In map 29 | } 30 | t[int('.')] = '.' // Float (potentially in map) 31 | 32 | var resolveMapList = []struct { 33 | v interface{} 34 | tag string 35 | l []string 36 | }{ 37 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, 38 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, 39 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, 40 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, 41 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, 42 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, 43 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, 44 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, 45 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, 46 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, 47 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, 48 | {"<<", yaml_MERGE_TAG, []string{"<<"}}, 49 | } 50 | 51 | m := resolveMap 52 | for _, item := range resolveMapList { 53 | for _, s := range item.l { 54 | m[s] = resolveMapItem{item.v, item.tag} 55 | } 56 | } 57 | } 58 | 59 | const longTagPrefix = "tag:yaml.org,2002:" 60 | 61 | func shortTag(tag string) string { 62 | // TODO This can easily be made faster and produce less garbage. 63 | if strings.HasPrefix(tag, longTagPrefix) { 64 | return "!!" + tag[len(longTagPrefix):] 65 | } 66 | return tag 67 | } 68 | 69 | func longTag(tag string) string { 70 | if strings.HasPrefix(tag, "!!") { 71 | return longTagPrefix + tag[2:] 72 | } 73 | return tag 74 | } 75 | 76 | func resolvableTag(tag string) bool { 77 | switch tag { 78 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG: 79 | return true 80 | } 81 | return false 82 | } 83 | 84 | var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`) 85 | 86 | func resolve(tag string, in string) (rtag string, out interface{}) { 87 | if !resolvableTag(tag) { 88 | return tag, in 89 | } 90 | 91 | defer func() { 92 | switch tag { 93 | case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: 94 | return 95 | } 96 | failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) 97 | }() 98 | 99 | // Any data is accepted as a !!str or !!binary. 100 | // Otherwise, the prefix is enough of a hint about what it might be. 101 | hint := byte('N') 102 | if in != "" { 103 | hint = resolveTable[in[0]] 104 | } 105 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { 106 | // Handle things we can lookup in a map. 107 | if item, ok := resolveMap[in]; ok { 108 | return item.tag, item.value 109 | } 110 | 111 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 112 | // are purposefully unsupported here. They're still quoted on 113 | // the way out for compatibility with other parser, though. 114 | 115 | switch hint { 116 | case 'M': 117 | // We've already checked the map above. 118 | 119 | case '.': 120 | // Not in the map, so maybe a normal float. 121 | floatv, err := strconv.ParseFloat(in, 64) 122 | if err == nil { 123 | return yaml_FLOAT_TAG, floatv 124 | } 125 | 126 | case 'D', 'S': 127 | // Int, float, or timestamp. 128 | // Only try values as a timestamp if the value is unquoted or there's an explicit 129 | // !!timestamp tag. 130 | if tag == "" || tag == yaml_TIMESTAMP_TAG { 131 | t, ok := parseTimestamp(in) 132 | if ok { 133 | return yaml_TIMESTAMP_TAG, t 134 | } 135 | } 136 | 137 | plain := strings.Replace(in, "_", "", -1) 138 | intv, err := strconv.ParseInt(plain, 0, 64) 139 | if err == nil { 140 | if intv == int64(int(intv)) { 141 | return yaml_INT_TAG, int(intv) 142 | } else { 143 | return yaml_INT_TAG, intv 144 | } 145 | } 146 | uintv, err := strconv.ParseUint(plain, 0, 64) 147 | if err == nil { 148 | return yaml_INT_TAG, uintv 149 | } 150 | if yamlStyleFloat.MatchString(plain) { 151 | floatv, err := strconv.ParseFloat(plain, 64) 152 | if err == nil { 153 | return yaml_FLOAT_TAG, floatv 154 | } 155 | } 156 | if strings.HasPrefix(plain, "0b") { 157 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 158 | if err == nil { 159 | if intv == int64(int(intv)) { 160 | return yaml_INT_TAG, int(intv) 161 | } else { 162 | return yaml_INT_TAG, intv 163 | } 164 | } 165 | uintv, err := strconv.ParseUint(plain[2:], 2, 64) 166 | if err == nil { 167 | return yaml_INT_TAG, uintv 168 | } 169 | } else if strings.HasPrefix(plain, "-0b") { 170 | intv, err := strconv.ParseInt(plain[3:], 2, 64) 171 | if err == nil { 172 | if intv == int64(int(intv)) { 173 | return yaml_INT_TAG, -int(intv) 174 | } else { 175 | return yaml_INT_TAG, -intv 176 | } 177 | } 178 | } 179 | default: 180 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 181 | } 182 | } 183 | return yaml_STR_TAG, in 184 | } 185 | 186 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 187 | // as appropriate for the resulting length. 188 | func encodeBase64(s string) string { 189 | const lineLen = 70 190 | encLen := base64.StdEncoding.EncodedLen(len(s)) 191 | lines := encLen/lineLen + 1 192 | buf := make([]byte, encLen*2+lines) 193 | in := buf[0:encLen] 194 | out := buf[encLen:] 195 | base64.StdEncoding.Encode(in, []byte(s)) 196 | k := 0 197 | for i := 0; i < len(in); i += lineLen { 198 | j := i + lineLen 199 | if j > len(in) { 200 | j = len(in) 201 | } 202 | k += copy(out[k:], in[i:j]) 203 | if lines > 1 { 204 | out[k] = '\n' 205 | k++ 206 | } 207 | } 208 | return string(out[:k]) 209 | } 210 | 211 | // This is a subset of the formats allowed by the regular expression 212 | // defined at http://yaml.org/type/timestamp.html. 213 | var allowedTimestampFormats = []string{ 214 | "2006-1-2T15:4:5Z07:00", 215 | "2006-1-2t15:4:5Z07:00", // RFC3339 with lower-case "t". 216 | "2006-1-2 15:4:5", // space separated with no time zone 217 | "2006-1-2", // date only 218 | // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" 219 | // from the set of examples. 220 | } 221 | 222 | // parseTimestamp parses s as a timestamp string and 223 | // returns the timestamp and reports whether it succeeded. 224 | // Timestamp formats are defined at http://yaml.org/type/timestamp.html 225 | func parseTimestamp(s string) (time.Time, bool) { 226 | // TODO write code to check all the formats supported by 227 | // http://yaml.org/type/timestamp.html instead of using time.Parse. 228 | 229 | // Quick check: all date formats start with YYYY-. 230 | i := 0 231 | for ; i < len(s); i++ { 232 | if c := s[i]; c < '0' || c > '9' { 233 | break 234 | } 235 | } 236 | if i != 4 || i == len(s) || s[i] != '-' { 237 | return time.Time{}, false 238 | } 239 | for _, format := range allowedTimestampFormats { 240 | if t, err := time.Parse(format, s); err == nil { 241 | return t, true 242 | } 243 | } 244 | return time.Time{}, false 245 | } 246 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/sorter.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "unicode" 6 | ) 7 | 8 | type keyList []reflect.Value 9 | 10 | func (l keyList) Len() int { return len(l) } 11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 12 | func (l keyList) Less(i, j int) bool { 13 | a := l[i] 14 | b := l[j] 15 | ak := a.Kind() 16 | bk := b.Kind() 17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 18 | a = a.Elem() 19 | ak = a.Kind() 20 | } 21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 22 | b = b.Elem() 23 | bk = b.Kind() 24 | } 25 | af, aok := keyFloat(a) 26 | bf, bok := keyFloat(b) 27 | if aok && bok { 28 | if af != bf { 29 | return af < bf 30 | } 31 | if ak != bk { 32 | return ak < bk 33 | } 34 | return numLess(a, b) 35 | } 36 | if ak != reflect.String || bk != reflect.String { 37 | return ak < bk 38 | } 39 | ar, br := []rune(a.String()), []rune(b.String()) 40 | for i := 0; i < len(ar) && i < len(br); i++ { 41 | if ar[i] == br[i] { 42 | continue 43 | } 44 | al := unicode.IsLetter(ar[i]) 45 | bl := unicode.IsLetter(br[i]) 46 | if al && bl { 47 | return ar[i] < br[i] 48 | } 49 | if al || bl { 50 | return bl 51 | } 52 | var ai, bi int 53 | var an, bn int64 54 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 55 | an = an*10 + int64(ar[ai]-'0') 56 | } 57 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 58 | bn = bn*10 + int64(br[bi]-'0') 59 | } 60 | if an != bn { 61 | return an < bn 62 | } 63 | if ai != bi { 64 | return ai < bi 65 | } 66 | return ar[i] < br[i] 67 | } 68 | return len(ar) < len(br) 69 | } 70 | 71 | // keyFloat returns a float value for v if it is a number/bool 72 | // and whether it is a number/bool or not. 73 | func keyFloat(v reflect.Value) (f float64, ok bool) { 74 | switch v.Kind() { 75 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 76 | return float64(v.Int()), true 77 | case reflect.Float32, reflect.Float64: 78 | return v.Float(), true 79 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 80 | return float64(v.Uint()), true 81 | case reflect.Bool: 82 | if v.Bool() { 83 | return 1, true 84 | } 85 | return 0, true 86 | } 87 | return 0, false 88 | } 89 | 90 | // numLess returns whether a < b. 91 | // a and b must necessarily have the same kind. 92 | func numLess(a, b reflect.Value) bool { 93 | switch a.Kind() { 94 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 95 | return a.Int() < b.Int() 96 | case reflect.Float32, reflect.Float64: 97 | return a.Float() < b.Float() 98 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 99 | return a.Uint() < b.Uint() 100 | case reflect.Bool: 101 | return !a.Bool() && b.Bool() 102 | } 103 | panic("not a number") 104 | } 105 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/suite_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | . "gopkg.in/check.v1" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { TestingT(t) } 9 | 10 | type S struct{} 11 | 12 | var _ = Suite(&S{}) 13 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/writerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | // Set the writer error and return false. 4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 5 | emitter.error = yaml_WRITER_ERROR 6 | emitter.problem = problem 7 | return false 8 | } 9 | 10 | // Flush the output buffer. 11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 12 | if emitter.write_handler == nil { 13 | panic("write handler not set") 14 | } 15 | 16 | // Check if the buffer is empty. 17 | if emitter.buffer_pos == 0 { 18 | return true 19 | } 20 | 21 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 22 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 23 | } 24 | emitter.buffer_pos = 0 25 | return true 26 | } 27 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/yaml.go: -------------------------------------------------------------------------------- 1 | // Package yaml implements YAML support for the Go language. 2 | // 3 | // Source code and other details for the project are available at GitHub: 4 | // 5 | // https://github.com/go-yaml/yaml 6 | // 7 | package yaml 8 | 9 | import ( 10 | "errors" 11 | "fmt" 12 | "io" 13 | "reflect" 14 | "strings" 15 | "sync" 16 | ) 17 | 18 | // MapSlice encodes and decodes as a YAML map. 19 | // The order of keys is preserved when encoding and decoding. 20 | type MapSlice []MapItem 21 | 22 | // MapItem is an item in a MapSlice. 23 | type MapItem struct { 24 | Key, Value interface{} 25 | } 26 | 27 | // The Unmarshaler interface may be implemented by types to customize their 28 | // behavior when being unmarshaled from a YAML document. The UnmarshalYAML 29 | // method receives a function that may be called to unmarshal the original 30 | // YAML value into a field or variable. It is safe to call the unmarshal 31 | // function parameter more than once if necessary. 32 | type Unmarshaler interface { 33 | UnmarshalYAML(unmarshal func(interface{}) error) error 34 | } 35 | 36 | // The Marshaler interface may be implemented by types to customize their 37 | // behavior when being marshaled into a YAML document. The returned value 38 | // is marshaled in place of the original value implementing Marshaler. 39 | // 40 | // If an error is returned by MarshalYAML, the marshaling procedure stops 41 | // and returns with the provided error. 42 | type Marshaler interface { 43 | MarshalYAML() (interface{}, error) 44 | } 45 | 46 | // Unmarshal decodes the first document found within the in byte slice 47 | // and assigns decoded values into the out value. 48 | // 49 | // Maps and pointers (to a struct, string, int, etc) are accepted as out 50 | // values. If an internal pointer within a struct is not initialized, 51 | // the yaml package will initialize it if necessary for unmarshalling 52 | // the provided data. The out parameter must not be nil. 53 | // 54 | // The type of the decoded values should be compatible with the respective 55 | // values in out. If one or more values cannot be decoded due to a type 56 | // mismatches, decoding continues partially until the end of the YAML 57 | // content, and a *yaml.TypeError is returned with details for all 58 | // missed values. 59 | // 60 | // Struct fields are only unmarshalled if they are exported (have an 61 | // upper case first letter), and are unmarshalled using the field name 62 | // lowercased as the default key. Custom keys may be defined via the 63 | // "yaml" name in the field tag: the content preceding the first comma 64 | // is used as the key, and the following comma-separated options are 65 | // used to tweak the marshalling process (see Marshal). 66 | // Conflicting names result in a runtime error. 67 | // 68 | // For example: 69 | // 70 | // type T struct { 71 | // F int `yaml:"a,omitempty"` 72 | // B int 73 | // } 74 | // var t T 75 | // yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) 76 | // 77 | // See the documentation of Marshal for the format of tags and a list of 78 | // supported tag options. 79 | // 80 | func Unmarshal(in []byte, out interface{}) (err error) { 81 | return unmarshal(in, out, false) 82 | } 83 | 84 | // UnmarshalStrict is like Unmarshal except that any fields that are found 85 | // in the data that do not have corresponding struct members, or mapping 86 | // keys that are duplicates, will result in 87 | // an error. 88 | func UnmarshalStrict(in []byte, out interface{}) (err error) { 89 | return unmarshal(in, out, true) 90 | } 91 | 92 | // A Decorder reads and decodes YAML values from an input stream. 93 | type Decoder struct { 94 | strict bool 95 | parser *parser 96 | } 97 | 98 | // NewDecoder returns a new decoder that reads from r. 99 | // 100 | // The decoder introduces its own buffering and may read 101 | // data from r beyond the YAML values requested. 102 | func NewDecoder(r io.Reader) *Decoder { 103 | return &Decoder{ 104 | parser: newParserFromReader(r), 105 | } 106 | } 107 | 108 | // SetStrict sets whether strict decoding behaviour is enabled when 109 | // decoding items in the data (see UnmarshalStrict). By default, decoding is not strict. 110 | func (dec *Decoder) SetStrict(strict bool) { 111 | dec.strict = strict 112 | } 113 | 114 | // Decode reads the next YAML-encoded value from its input 115 | // and stores it in the value pointed to by v. 116 | // 117 | // See the documentation for Unmarshal for details about the 118 | // conversion of YAML into a Go value. 119 | func (dec *Decoder) Decode(v interface{}) (err error) { 120 | d := newDecoder(dec.strict) 121 | defer handleErr(&err) 122 | node := dec.parser.parse() 123 | if node == nil { 124 | return io.EOF 125 | } 126 | out := reflect.ValueOf(v) 127 | if out.Kind() == reflect.Ptr && !out.IsNil() { 128 | out = out.Elem() 129 | } 130 | d.unmarshal(node, out) 131 | if len(d.terrors) > 0 { 132 | return &TypeError{d.terrors} 133 | } 134 | return nil 135 | } 136 | 137 | func unmarshal(in []byte, out interface{}, strict bool) (err error) { 138 | defer handleErr(&err) 139 | d := newDecoder(strict) 140 | p := newParser(in) 141 | defer p.destroy() 142 | node := p.parse() 143 | if node != nil { 144 | v := reflect.ValueOf(out) 145 | if v.Kind() == reflect.Ptr && !v.IsNil() { 146 | v = v.Elem() 147 | } 148 | d.unmarshal(node, v) 149 | } 150 | if len(d.terrors) > 0 { 151 | return &TypeError{d.terrors} 152 | } 153 | return nil 154 | } 155 | 156 | // Marshal serializes the value provided into a YAML document. The structure 157 | // of the generated document will reflect the structure of the value itself. 158 | // Maps and pointers (to struct, string, int, etc) are accepted as the in value. 159 | // 160 | // Struct fields are only unmarshalled if they are exported (have an upper case 161 | // first letter), and are unmarshalled using the field name lowercased as the 162 | // default key. Custom keys may be defined via the "yaml" name in the field 163 | // tag: the content preceding the first comma is used as the key, and the 164 | // following comma-separated options are used to tweak the marshalling process. 165 | // Conflicting names result in a runtime error. 166 | // 167 | // The field tag format accepted is: 168 | // 169 | // `(...) yaml:"[][,[,]]" (...)` 170 | // 171 | // The following flags are currently supported: 172 | // 173 | // omitempty Only include the field if it's not set to the zero 174 | // value for the type or to empty slices or maps. 175 | // Zero valued structs will be omitted if all their public 176 | // fields are zero, unless they implement an IsZero 177 | // method (see the IsZeroer interface type), in which 178 | // case the field will be included if that method returns true. 179 | // 180 | // flow Marshal using a flow style (useful for structs, 181 | // sequences and maps). 182 | // 183 | // inline Inline the field, which must be a struct or a map, 184 | // causing all of its fields or keys to be processed as if 185 | // they were part of the outer struct. For maps, keys must 186 | // not conflict with the yaml keys of other struct fields. 187 | // 188 | // In addition, if the key is "-", the field is ignored. 189 | // 190 | // For example: 191 | // 192 | // type T struct { 193 | // F int `yaml:"a,omitempty"` 194 | // B int 195 | // } 196 | // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" 197 | // yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" 198 | // 199 | func Marshal(in interface{}) (out []byte, err error) { 200 | defer handleErr(&err) 201 | e := newEncoder() 202 | defer e.destroy() 203 | e.marshalDoc("", reflect.ValueOf(in)) 204 | e.finish() 205 | out = e.out 206 | return 207 | } 208 | 209 | // An Encoder writes YAML values to an output stream. 210 | type Encoder struct { 211 | encoder *encoder 212 | } 213 | 214 | // NewEncoder returns a new encoder that writes to w. 215 | // The Encoder should be closed after use to flush all data 216 | // to w. 217 | func NewEncoder(w io.Writer) *Encoder { 218 | return &Encoder{ 219 | encoder: newEncoderWithWriter(w), 220 | } 221 | } 222 | 223 | // Encode writes the YAML encoding of v to the stream. 224 | // If multiple items are encoded to the stream, the 225 | // second and subsequent document will be preceded 226 | // with a "---" document separator, but the first will not. 227 | // 228 | // See the documentation for Marshal for details about the conversion of Go 229 | // values to YAML. 230 | func (e *Encoder) Encode(v interface{}) (err error) { 231 | defer handleErr(&err) 232 | e.encoder.marshalDoc("", reflect.ValueOf(v)) 233 | return nil 234 | } 235 | 236 | // Close closes the encoder by writing any remaining data. 237 | // It does not write a stream terminating string "...". 238 | func (e *Encoder) Close() (err error) { 239 | defer handleErr(&err) 240 | e.encoder.finish() 241 | return nil 242 | } 243 | 244 | func handleErr(err *error) { 245 | if v := recover(); v != nil { 246 | if e, ok := v.(yamlError); ok { 247 | *err = e.err 248 | } else { 249 | panic(v) 250 | } 251 | } 252 | } 253 | 254 | type yamlError struct { 255 | err error 256 | } 257 | 258 | func fail(err error) { 259 | panic(yamlError{err}) 260 | } 261 | 262 | func failf(format string, args ...interface{}) { 263 | panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) 264 | } 265 | 266 | // A TypeError is returned by Unmarshal when one or more fields in 267 | // the YAML document cannot be properly decoded into the requested 268 | // types. When this error is returned, the value is still 269 | // unmarshaled partially. 270 | type TypeError struct { 271 | Errors []string 272 | } 273 | 274 | func (e *TypeError) Error() string { 275 | return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) 276 | } 277 | 278 | // -------------------------------------------------------------------------- 279 | // Maintain a mapping of keys to structure field indexes 280 | 281 | // The code in this section was copied from mgo/bson. 282 | 283 | // structInfo holds details for the serialization of fields of 284 | // a given struct. 285 | type structInfo struct { 286 | FieldsMap map[string]fieldInfo 287 | FieldsList []fieldInfo 288 | 289 | // InlineMap is the number of the field in the struct that 290 | // contains an ,inline map, or -1 if there's none. 291 | InlineMap int 292 | } 293 | 294 | type fieldInfo struct { 295 | Key string 296 | Num int 297 | OmitEmpty bool 298 | Flow bool 299 | // Id holds the unique field identifier, so we can cheaply 300 | // check for field duplicates without maintaining an extra map. 301 | Id int 302 | 303 | // Inline holds the field index if the field is part of an inlined struct. 304 | Inline []int 305 | } 306 | 307 | var structMap = make(map[reflect.Type]*structInfo) 308 | var fieldMapMutex sync.RWMutex 309 | 310 | func getStructInfo(st reflect.Type) (*structInfo, error) { 311 | fieldMapMutex.RLock() 312 | sinfo, found := structMap[st] 313 | fieldMapMutex.RUnlock() 314 | if found { 315 | return sinfo, nil 316 | } 317 | 318 | n := st.NumField() 319 | fieldsMap := make(map[string]fieldInfo) 320 | fieldsList := make([]fieldInfo, 0, n) 321 | inlineMap := -1 322 | for i := 0; i != n; i++ { 323 | field := st.Field(i) 324 | if field.PkgPath != "" && !field.Anonymous { 325 | continue // Private field 326 | } 327 | 328 | info := fieldInfo{Num: i} 329 | 330 | tag := field.Tag.Get("yaml") 331 | if tag == "" && strings.Index(string(field.Tag), ":") < 0 { 332 | tag = string(field.Tag) 333 | } 334 | if tag == "-" { 335 | continue 336 | } 337 | 338 | inline := false 339 | fields := strings.Split(tag, ",") 340 | if len(fields) > 1 { 341 | for _, flag := range fields[1:] { 342 | switch flag { 343 | case "omitempty": 344 | info.OmitEmpty = true 345 | case "flow": 346 | info.Flow = true 347 | case "inline": 348 | inline = true 349 | default: 350 | return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) 351 | } 352 | } 353 | tag = fields[0] 354 | } 355 | 356 | if inline { 357 | switch field.Type.Kind() { 358 | case reflect.Map: 359 | if inlineMap >= 0 { 360 | return nil, errors.New("Multiple ,inline maps in struct " + st.String()) 361 | } 362 | if field.Type.Key() != reflect.TypeOf("") { 363 | return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) 364 | } 365 | inlineMap = info.Num 366 | case reflect.Struct: 367 | sinfo, err := getStructInfo(field.Type) 368 | if err != nil { 369 | return nil, err 370 | } 371 | for _, finfo := range sinfo.FieldsList { 372 | if _, found := fieldsMap[finfo.Key]; found { 373 | msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() 374 | return nil, errors.New(msg) 375 | } 376 | if finfo.Inline == nil { 377 | finfo.Inline = []int{i, finfo.Num} 378 | } else { 379 | finfo.Inline = append([]int{i}, finfo.Inline...) 380 | } 381 | finfo.Id = len(fieldsList) 382 | fieldsMap[finfo.Key] = finfo 383 | fieldsList = append(fieldsList, finfo) 384 | } 385 | default: 386 | //return nil, errors.New("Option ,inline needs a struct value or map field") 387 | return nil, errors.New("Option ,inline needs a struct value field") 388 | } 389 | continue 390 | } 391 | 392 | if tag != "" { 393 | info.Key = tag 394 | } else { 395 | info.Key = strings.ToLower(field.Name) 396 | } 397 | 398 | if _, found = fieldsMap[info.Key]; found { 399 | msg := "Duplicated key '" + info.Key + "' in struct " + st.String() 400 | return nil, errors.New(msg) 401 | } 402 | 403 | info.Id = len(fieldsList) 404 | fieldsList = append(fieldsList, info) 405 | fieldsMap[info.Key] = info 406 | } 407 | 408 | sinfo = &structInfo{ 409 | FieldsMap: fieldsMap, 410 | FieldsList: fieldsList, 411 | InlineMap: inlineMap, 412 | } 413 | 414 | fieldMapMutex.Lock() 415 | structMap[st] = sinfo 416 | fieldMapMutex.Unlock() 417 | return sinfo, nil 418 | } 419 | 420 | // IsZeroer is used to check whether an object is zero to 421 | // determine whether it should be omitted when marshaling 422 | // with the omitempty flag. One notable implementation 423 | // is time.Time. 424 | type IsZeroer interface { 425 | IsZero() bool 426 | } 427 | 428 | func isZero(v reflect.Value) bool { 429 | kind := v.Kind() 430 | if z, ok := v.Interface().(IsZeroer); ok { 431 | if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { 432 | return true 433 | } 434 | return z.IsZero() 435 | } 436 | switch kind { 437 | case reflect.String: 438 | return len(v.String()) == 0 439 | case reflect.Interface, reflect.Ptr: 440 | return v.IsNil() 441 | case reflect.Slice: 442 | return v.Len() == 0 443 | case reflect.Map: 444 | return v.Len() == 0 445 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 446 | return v.Int() == 0 447 | case reflect.Float32, reflect.Float64: 448 | return v.Float() == 0 449 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 450 | return v.Uint() == 0 451 | case reflect.Bool: 452 | return !v.Bool() 453 | case reflect.Struct: 454 | vt := v.Type() 455 | for i := v.NumField() - 1; i >= 0; i-- { 456 | if vt.Field(i).PkgPath != "" { 457 | continue // Private field 458 | } 459 | if !isZero(v.Field(i)) { 460 | return false 461 | } 462 | } 463 | return true 464 | } 465 | return false 466 | } 467 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/yamlh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | ) 7 | 8 | // The version directive data. 9 | type yaml_version_directive_t struct { 10 | major int8 // The major version number. 11 | minor int8 // The minor version number. 12 | } 13 | 14 | // The tag directive data. 15 | type yaml_tag_directive_t struct { 16 | handle []byte // The tag handle. 17 | prefix []byte // The tag prefix. 18 | } 19 | 20 | type yaml_encoding_t int 21 | 22 | // The stream encoding. 23 | const ( 24 | // Let the parser choose the encoding. 25 | yaml_ANY_ENCODING yaml_encoding_t = iota 26 | 27 | yaml_UTF8_ENCODING // The default UTF-8 encoding. 28 | yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. 29 | yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. 30 | ) 31 | 32 | type yaml_break_t int 33 | 34 | // Line break types. 35 | const ( 36 | // Let the parser choose the break type. 37 | yaml_ANY_BREAK yaml_break_t = iota 38 | 39 | yaml_CR_BREAK // Use CR for line breaks (Mac style). 40 | yaml_LN_BREAK // Use LN for line breaks (Unix style). 41 | yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). 42 | ) 43 | 44 | type yaml_error_type_t int 45 | 46 | // Many bad things could happen with the parser and emitter. 47 | const ( 48 | // No error is produced. 49 | yaml_NO_ERROR yaml_error_type_t = iota 50 | 51 | yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. 52 | yaml_READER_ERROR // Cannot read or decode the input stream. 53 | yaml_SCANNER_ERROR // Cannot scan the input stream. 54 | yaml_PARSER_ERROR // Cannot parse the input stream. 55 | yaml_COMPOSER_ERROR // Cannot compose a YAML document. 56 | yaml_WRITER_ERROR // Cannot write to the output stream. 57 | yaml_EMITTER_ERROR // Cannot emit a YAML stream. 58 | ) 59 | 60 | // The pointer position. 61 | type yaml_mark_t struct { 62 | index int // The position index. 63 | line int // The position line. 64 | column int // The position column. 65 | } 66 | 67 | // Node Styles 68 | 69 | type yaml_style_t int8 70 | 71 | type yaml_scalar_style_t yaml_style_t 72 | 73 | // Scalar styles. 74 | const ( 75 | // Let the emitter choose the style. 76 | yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota 77 | 78 | yaml_PLAIN_SCALAR_STYLE // The plain scalar style. 79 | yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. 80 | yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. 81 | yaml_LITERAL_SCALAR_STYLE // The literal scalar style. 82 | yaml_FOLDED_SCALAR_STYLE // The folded scalar style. 83 | ) 84 | 85 | type yaml_sequence_style_t yaml_style_t 86 | 87 | // Sequence styles. 88 | const ( 89 | // Let the emitter choose the style. 90 | yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota 91 | 92 | yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. 93 | yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. 94 | ) 95 | 96 | type yaml_mapping_style_t yaml_style_t 97 | 98 | // Mapping styles. 99 | const ( 100 | // Let the emitter choose the style. 101 | yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota 102 | 103 | yaml_BLOCK_MAPPING_STYLE // The block mapping style. 104 | yaml_FLOW_MAPPING_STYLE // The flow mapping style. 105 | ) 106 | 107 | // Tokens 108 | 109 | type yaml_token_type_t int 110 | 111 | // Token types. 112 | const ( 113 | // An empty token. 114 | yaml_NO_TOKEN yaml_token_type_t = iota 115 | 116 | yaml_STREAM_START_TOKEN // A STREAM-START token. 117 | yaml_STREAM_END_TOKEN // A STREAM-END token. 118 | 119 | yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. 120 | yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. 121 | yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. 122 | yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. 123 | 124 | yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. 125 | yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. 126 | yaml_BLOCK_END_TOKEN // A BLOCK-END token. 127 | 128 | yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. 129 | yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. 130 | yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. 131 | yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. 132 | 133 | yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. 134 | yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. 135 | yaml_KEY_TOKEN // A KEY token. 136 | yaml_VALUE_TOKEN // A VALUE token. 137 | 138 | yaml_ALIAS_TOKEN // An ALIAS token. 139 | yaml_ANCHOR_TOKEN // An ANCHOR token. 140 | yaml_TAG_TOKEN // A TAG token. 141 | yaml_SCALAR_TOKEN // A SCALAR token. 142 | ) 143 | 144 | func (tt yaml_token_type_t) String() string { 145 | switch tt { 146 | case yaml_NO_TOKEN: 147 | return "yaml_NO_TOKEN" 148 | case yaml_STREAM_START_TOKEN: 149 | return "yaml_STREAM_START_TOKEN" 150 | case yaml_STREAM_END_TOKEN: 151 | return "yaml_STREAM_END_TOKEN" 152 | case yaml_VERSION_DIRECTIVE_TOKEN: 153 | return "yaml_VERSION_DIRECTIVE_TOKEN" 154 | case yaml_TAG_DIRECTIVE_TOKEN: 155 | return "yaml_TAG_DIRECTIVE_TOKEN" 156 | case yaml_DOCUMENT_START_TOKEN: 157 | return "yaml_DOCUMENT_START_TOKEN" 158 | case yaml_DOCUMENT_END_TOKEN: 159 | return "yaml_DOCUMENT_END_TOKEN" 160 | case yaml_BLOCK_SEQUENCE_START_TOKEN: 161 | return "yaml_BLOCK_SEQUENCE_START_TOKEN" 162 | case yaml_BLOCK_MAPPING_START_TOKEN: 163 | return "yaml_BLOCK_MAPPING_START_TOKEN" 164 | case yaml_BLOCK_END_TOKEN: 165 | return "yaml_BLOCK_END_TOKEN" 166 | case yaml_FLOW_SEQUENCE_START_TOKEN: 167 | return "yaml_FLOW_SEQUENCE_START_TOKEN" 168 | case yaml_FLOW_SEQUENCE_END_TOKEN: 169 | return "yaml_FLOW_SEQUENCE_END_TOKEN" 170 | case yaml_FLOW_MAPPING_START_TOKEN: 171 | return "yaml_FLOW_MAPPING_START_TOKEN" 172 | case yaml_FLOW_MAPPING_END_TOKEN: 173 | return "yaml_FLOW_MAPPING_END_TOKEN" 174 | case yaml_BLOCK_ENTRY_TOKEN: 175 | return "yaml_BLOCK_ENTRY_TOKEN" 176 | case yaml_FLOW_ENTRY_TOKEN: 177 | return "yaml_FLOW_ENTRY_TOKEN" 178 | case yaml_KEY_TOKEN: 179 | return "yaml_KEY_TOKEN" 180 | case yaml_VALUE_TOKEN: 181 | return "yaml_VALUE_TOKEN" 182 | case yaml_ALIAS_TOKEN: 183 | return "yaml_ALIAS_TOKEN" 184 | case yaml_ANCHOR_TOKEN: 185 | return "yaml_ANCHOR_TOKEN" 186 | case yaml_TAG_TOKEN: 187 | return "yaml_TAG_TOKEN" 188 | case yaml_SCALAR_TOKEN: 189 | return "yaml_SCALAR_TOKEN" 190 | } 191 | return "" 192 | } 193 | 194 | // The token structure. 195 | type yaml_token_t struct { 196 | // The token type. 197 | typ yaml_token_type_t 198 | 199 | // The start/end of the token. 200 | start_mark, end_mark yaml_mark_t 201 | 202 | // The stream encoding (for yaml_STREAM_START_TOKEN). 203 | encoding yaml_encoding_t 204 | 205 | // The alias/anchor/scalar value or tag/tag directive handle 206 | // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). 207 | value []byte 208 | 209 | // The tag suffix (for yaml_TAG_TOKEN). 210 | suffix []byte 211 | 212 | // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). 213 | prefix []byte 214 | 215 | // The scalar style (for yaml_SCALAR_TOKEN). 216 | style yaml_scalar_style_t 217 | 218 | // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). 219 | major, minor int8 220 | } 221 | 222 | // Events 223 | 224 | type yaml_event_type_t int8 225 | 226 | // Event types. 227 | const ( 228 | // An empty event. 229 | yaml_NO_EVENT yaml_event_type_t = iota 230 | 231 | yaml_STREAM_START_EVENT // A STREAM-START event. 232 | yaml_STREAM_END_EVENT // A STREAM-END event. 233 | yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. 234 | yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. 235 | yaml_ALIAS_EVENT // An ALIAS event. 236 | yaml_SCALAR_EVENT // A SCALAR event. 237 | yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. 238 | yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. 239 | yaml_MAPPING_START_EVENT // A MAPPING-START event. 240 | yaml_MAPPING_END_EVENT // A MAPPING-END event. 241 | ) 242 | 243 | var eventStrings = []string{ 244 | yaml_NO_EVENT: "none", 245 | yaml_STREAM_START_EVENT: "stream start", 246 | yaml_STREAM_END_EVENT: "stream end", 247 | yaml_DOCUMENT_START_EVENT: "document start", 248 | yaml_DOCUMENT_END_EVENT: "document end", 249 | yaml_ALIAS_EVENT: "alias", 250 | yaml_SCALAR_EVENT: "scalar", 251 | yaml_SEQUENCE_START_EVENT: "sequence start", 252 | yaml_SEQUENCE_END_EVENT: "sequence end", 253 | yaml_MAPPING_START_EVENT: "mapping start", 254 | yaml_MAPPING_END_EVENT: "mapping end", 255 | } 256 | 257 | func (e yaml_event_type_t) String() string { 258 | if e < 0 || int(e) >= len(eventStrings) { 259 | return fmt.Sprintf("unknown event %d", e) 260 | } 261 | return eventStrings[e] 262 | } 263 | 264 | // The event structure. 265 | type yaml_event_t struct { 266 | 267 | // The event type. 268 | typ yaml_event_type_t 269 | 270 | // The start and end of the event. 271 | start_mark, end_mark yaml_mark_t 272 | 273 | // The document encoding (for yaml_STREAM_START_EVENT). 274 | encoding yaml_encoding_t 275 | 276 | // The version directive (for yaml_DOCUMENT_START_EVENT). 277 | version_directive *yaml_version_directive_t 278 | 279 | // The list of tag directives (for yaml_DOCUMENT_START_EVENT). 280 | tag_directives []yaml_tag_directive_t 281 | 282 | // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). 283 | anchor []byte 284 | 285 | // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). 286 | tag []byte 287 | 288 | // The scalar value (for yaml_SCALAR_EVENT). 289 | value []byte 290 | 291 | // Is the document start/end indicator implicit, or the tag optional? 292 | // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). 293 | implicit bool 294 | 295 | // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). 296 | quoted_implicit bool 297 | 298 | // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). 299 | style yaml_style_t 300 | } 301 | 302 | func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } 303 | func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } 304 | func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } 305 | 306 | // Nodes 307 | 308 | const ( 309 | yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. 310 | yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. 311 | yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. 312 | yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. 313 | yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. 314 | yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. 315 | 316 | yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. 317 | yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. 318 | 319 | // Not in original libyaml. 320 | yaml_BINARY_TAG = "tag:yaml.org,2002:binary" 321 | yaml_MERGE_TAG = "tag:yaml.org,2002:merge" 322 | 323 | yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. 324 | yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. 325 | yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. 326 | ) 327 | 328 | type yaml_node_type_t int 329 | 330 | // Node types. 331 | const ( 332 | // An empty node. 333 | yaml_NO_NODE yaml_node_type_t = iota 334 | 335 | yaml_SCALAR_NODE // A scalar node. 336 | yaml_SEQUENCE_NODE // A sequence node. 337 | yaml_MAPPING_NODE // A mapping node. 338 | ) 339 | 340 | // An element of a sequence node. 341 | type yaml_node_item_t int 342 | 343 | // An element of a mapping node. 344 | type yaml_node_pair_t struct { 345 | key int // The key of the element. 346 | value int // The value of the element. 347 | } 348 | 349 | // The node structure. 350 | type yaml_node_t struct { 351 | typ yaml_node_type_t // The node type. 352 | tag []byte // The node tag. 353 | 354 | // The node data. 355 | 356 | // The scalar parameters (for yaml_SCALAR_NODE). 357 | scalar struct { 358 | value []byte // The scalar value. 359 | length int // The length of the scalar value. 360 | style yaml_scalar_style_t // The scalar style. 361 | } 362 | 363 | // The sequence parameters (for YAML_SEQUENCE_NODE). 364 | sequence struct { 365 | items_data []yaml_node_item_t // The stack of sequence items. 366 | style yaml_sequence_style_t // The sequence style. 367 | } 368 | 369 | // The mapping parameters (for yaml_MAPPING_NODE). 370 | mapping struct { 371 | pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). 372 | pairs_start *yaml_node_pair_t // The beginning of the stack. 373 | pairs_end *yaml_node_pair_t // The end of the stack. 374 | pairs_top *yaml_node_pair_t // The top of the stack. 375 | style yaml_mapping_style_t // The mapping style. 376 | } 377 | 378 | start_mark yaml_mark_t // The beginning of the node. 379 | end_mark yaml_mark_t // The end of the node. 380 | 381 | } 382 | 383 | // The document structure. 384 | type yaml_document_t struct { 385 | 386 | // The document nodes. 387 | nodes []yaml_node_t 388 | 389 | // The version directive. 390 | version_directive *yaml_version_directive_t 391 | 392 | // The list of tag directives. 393 | tag_directives_data []yaml_tag_directive_t 394 | tag_directives_start int // The beginning of the tag directives list. 395 | tag_directives_end int // The end of the tag directives list. 396 | 397 | start_implicit int // Is the document start indicator implicit? 398 | end_implicit int // Is the document end indicator implicit? 399 | 400 | // The start/end of the document. 401 | start_mark, end_mark yaml_mark_t 402 | } 403 | 404 | // The prototype of a read handler. 405 | // 406 | // The read handler is called when the parser needs to read more bytes from the 407 | // source. The handler should write not more than size bytes to the buffer. 408 | // The number of written bytes should be set to the size_read variable. 409 | // 410 | // [in,out] data A pointer to an application data specified by 411 | // yaml_parser_set_input(). 412 | // [out] buffer The buffer to write the data from the source. 413 | // [in] size The size of the buffer. 414 | // [out] size_read The actual number of bytes read from the source. 415 | // 416 | // On success, the handler should return 1. If the handler failed, 417 | // the returned value should be 0. On EOF, the handler should set the 418 | // size_read to 0 and return 1. 419 | type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) 420 | 421 | // This structure holds information about a potential simple key. 422 | type yaml_simple_key_t struct { 423 | possible bool // Is a simple key possible? 424 | required bool // Is a simple key required? 425 | token_number int // The number of the token. 426 | mark yaml_mark_t // The position mark. 427 | } 428 | 429 | // The states of the parser. 430 | type yaml_parser_state_t int 431 | 432 | const ( 433 | yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota 434 | 435 | yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. 436 | yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. 437 | yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. 438 | yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. 439 | yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. 440 | yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. 441 | yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. 442 | yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. 443 | yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. 444 | yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. 445 | yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. 446 | yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. 447 | yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. 448 | yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. 449 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. 450 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. 451 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. 452 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. 453 | yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. 454 | yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. 455 | yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. 456 | yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. 457 | yaml_PARSE_END_STATE // Expect nothing. 458 | ) 459 | 460 | func (ps yaml_parser_state_t) String() string { 461 | switch ps { 462 | case yaml_PARSE_STREAM_START_STATE: 463 | return "yaml_PARSE_STREAM_START_STATE" 464 | case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: 465 | return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" 466 | case yaml_PARSE_DOCUMENT_START_STATE: 467 | return "yaml_PARSE_DOCUMENT_START_STATE" 468 | case yaml_PARSE_DOCUMENT_CONTENT_STATE: 469 | return "yaml_PARSE_DOCUMENT_CONTENT_STATE" 470 | case yaml_PARSE_DOCUMENT_END_STATE: 471 | return "yaml_PARSE_DOCUMENT_END_STATE" 472 | case yaml_PARSE_BLOCK_NODE_STATE: 473 | return "yaml_PARSE_BLOCK_NODE_STATE" 474 | case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: 475 | return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" 476 | case yaml_PARSE_FLOW_NODE_STATE: 477 | return "yaml_PARSE_FLOW_NODE_STATE" 478 | case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: 479 | return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" 480 | case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: 481 | return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" 482 | case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: 483 | return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" 484 | case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: 485 | return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" 486 | case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: 487 | return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" 488 | case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: 489 | return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" 490 | case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: 491 | return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" 492 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: 493 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" 494 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: 495 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" 496 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: 497 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" 498 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: 499 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" 500 | case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: 501 | return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" 502 | case yaml_PARSE_FLOW_MAPPING_KEY_STATE: 503 | return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" 504 | case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: 505 | return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" 506 | case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: 507 | return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" 508 | case yaml_PARSE_END_STATE: 509 | return "yaml_PARSE_END_STATE" 510 | } 511 | return "" 512 | } 513 | 514 | // This structure holds aliases data. 515 | type yaml_alias_data_t struct { 516 | anchor []byte // The anchor. 517 | index int // The node id. 518 | mark yaml_mark_t // The anchor mark. 519 | } 520 | 521 | // The parser structure. 522 | // 523 | // All members are internal. Manage the structure using the 524 | // yaml_parser_ family of functions. 525 | type yaml_parser_t struct { 526 | 527 | // Error handling 528 | 529 | error yaml_error_type_t // Error type. 530 | 531 | problem string // Error description. 532 | 533 | // The byte about which the problem occurred. 534 | problem_offset int 535 | problem_value int 536 | problem_mark yaml_mark_t 537 | 538 | // The error context. 539 | context string 540 | context_mark yaml_mark_t 541 | 542 | // Reader stuff 543 | 544 | read_handler yaml_read_handler_t // Read handler. 545 | 546 | input_reader io.Reader // File input data. 547 | input []byte // String input data. 548 | input_pos int 549 | 550 | eof bool // EOF flag 551 | 552 | buffer []byte // The working buffer. 553 | buffer_pos int // The current position of the buffer. 554 | 555 | unread int // The number of unread characters in the buffer. 556 | 557 | raw_buffer []byte // The raw buffer. 558 | raw_buffer_pos int // The current position of the buffer. 559 | 560 | encoding yaml_encoding_t // The input encoding. 561 | 562 | offset int // The offset of the current position (in bytes). 563 | mark yaml_mark_t // The mark of the current position. 564 | 565 | // Scanner stuff 566 | 567 | stream_start_produced bool // Have we started to scan the input stream? 568 | stream_end_produced bool // Have we reached the end of the input stream? 569 | 570 | flow_level int // The number of unclosed '[' and '{' indicators. 571 | 572 | tokens []yaml_token_t // The tokens queue. 573 | tokens_head int // The head of the tokens queue. 574 | tokens_parsed int // The number of tokens fetched from the queue. 575 | token_available bool // Does the tokens queue contain a token ready for dequeueing. 576 | 577 | indent int // The current indentation level. 578 | indents []int // The indentation levels stack. 579 | 580 | simple_key_allowed bool // May a simple key occur at the current position? 581 | simple_keys []yaml_simple_key_t // The stack of simple keys. 582 | 583 | // Parser stuff 584 | 585 | state yaml_parser_state_t // The current parser state. 586 | states []yaml_parser_state_t // The parser states stack. 587 | marks []yaml_mark_t // The stack of marks. 588 | tag_directives []yaml_tag_directive_t // The list of TAG directives. 589 | 590 | // Dumper stuff 591 | 592 | aliases []yaml_alias_data_t // The alias data. 593 | 594 | document *yaml_document_t // The currently parsed document. 595 | } 596 | 597 | // Emitter Definitions 598 | 599 | // The prototype of a write handler. 600 | // 601 | // The write handler is called when the emitter needs to flush the accumulated 602 | // characters to the output. The handler should write @a size bytes of the 603 | // @a buffer to the output. 604 | // 605 | // @param[in,out] data A pointer to an application data specified by 606 | // yaml_emitter_set_output(). 607 | // @param[in] buffer The buffer with bytes to be written. 608 | // @param[in] size The size of the buffer. 609 | // 610 | // @returns On success, the handler should return @c 1. If the handler failed, 611 | // the returned value should be @c 0. 612 | // 613 | type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error 614 | 615 | type yaml_emitter_state_t int 616 | 617 | // The emitter states. 618 | const ( 619 | // Expect STREAM-START. 620 | yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota 621 | 622 | yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. 623 | yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. 624 | yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. 625 | yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. 626 | yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. 627 | yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. 628 | yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. 629 | yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. 630 | yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. 631 | yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. 632 | yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. 633 | yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. 634 | yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. 635 | yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. 636 | yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. 637 | yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. 638 | yaml_EMIT_END_STATE // Expect nothing. 639 | ) 640 | 641 | // The emitter structure. 642 | // 643 | // All members are internal. Manage the structure using the @c yaml_emitter_ 644 | // family of functions. 645 | type yaml_emitter_t struct { 646 | 647 | // Error handling 648 | 649 | error yaml_error_type_t // Error type. 650 | problem string // Error description. 651 | 652 | // Writer stuff 653 | 654 | write_handler yaml_write_handler_t // Write handler. 655 | 656 | output_buffer *[]byte // String output data. 657 | output_writer io.Writer // File output data. 658 | 659 | buffer []byte // The working buffer. 660 | buffer_pos int // The current position of the buffer. 661 | 662 | raw_buffer []byte // The raw buffer. 663 | raw_buffer_pos int // The current position of the buffer. 664 | 665 | encoding yaml_encoding_t // The stream encoding. 666 | 667 | // Emitter stuff 668 | 669 | canonical bool // If the output is in the canonical style? 670 | best_indent int // The number of indentation spaces. 671 | best_width int // The preferred width of the output lines. 672 | unicode bool // Allow unescaped non-ASCII characters? 673 | line_break yaml_break_t // The preferred line break. 674 | 675 | state yaml_emitter_state_t // The current emitter state. 676 | states []yaml_emitter_state_t // The stack of states. 677 | 678 | events []yaml_event_t // The event queue. 679 | events_head int // The head of the event queue. 680 | 681 | indents []int // The stack of indentation levels. 682 | 683 | tag_directives []yaml_tag_directive_t // The list of tag directives. 684 | 685 | indent int // The current indentation level. 686 | 687 | flow_level int // The current flow level. 688 | 689 | root_context bool // Is it the document root context? 690 | sequence_context bool // Is it a sequence context? 691 | mapping_context bool // Is it a mapping context? 692 | simple_key_context bool // Is it a simple mapping key context? 693 | 694 | line int // The current line. 695 | column int // The current column. 696 | whitespace bool // If the last character was a whitespace? 697 | indention bool // If the last character was an indentation character (' ', '-', '?', ':')? 698 | open_ended bool // If an explicit document end is required? 699 | 700 | // Anchor analysis. 701 | anchor_data struct { 702 | anchor []byte // The anchor value. 703 | alias bool // Is it an alias? 704 | } 705 | 706 | // Tag analysis. 707 | tag_data struct { 708 | handle []byte // The tag handle. 709 | suffix []byte // The tag suffix. 710 | } 711 | 712 | // Scalar analysis. 713 | scalar_data struct { 714 | value []byte // The scalar value. 715 | multiline bool // Does the scalar contain line breaks? 716 | flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? 717 | block_plain_allowed bool // Can the scalar be expressed in the block plain style? 718 | single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? 719 | block_allowed bool // Can the scalar be expressed in the literal or folded styles? 720 | style yaml_scalar_style_t // The output style. 721 | } 722 | 723 | // Dumper stuff 724 | 725 | opened bool // If the stream was already opened? 726 | closed bool // If the stream was already closed? 727 | 728 | // The information associated with the document nodes. 729 | anchors *struct { 730 | references int // The number of references. 731 | anchor int // The anchor id. 732 | serialized bool // If the node has been emitted? 733 | } 734 | 735 | last_anchor_id int // The last assigned anchor id. 736 | 737 | document *yaml_document_t // The currently emitted document. 738 | } 739 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/yamlprivateh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | const ( 4 | // The size of the input raw buffer. 5 | input_raw_buffer_size = 512 6 | 7 | // The size of the input buffer. 8 | // It should be possible to decode the whole raw buffer. 9 | input_buffer_size = input_raw_buffer_size * 3 10 | 11 | // The size of the output buffer. 12 | output_buffer_size = 128 13 | 14 | // The size of the output raw buffer. 15 | // It should be possible to encode the whole output buffer. 16 | output_raw_buffer_size = (output_buffer_size*2 + 2) 17 | 18 | // The size of other stacks and queues. 19 | initial_stack_size = 16 20 | initial_queue_size = 16 21 | initial_string_size = 16 22 | ) 23 | 24 | // Check if the character at the specified position is an alphabetical 25 | // character, a digit, '_', or '-'. 26 | func is_alpha(b []byte, i int) bool { 27 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' 28 | } 29 | 30 | // Check if the character at the specified position is a digit. 31 | func is_digit(b []byte, i int) bool { 32 | return b[i] >= '0' && b[i] <= '9' 33 | } 34 | 35 | // Get the value of a digit. 36 | func as_digit(b []byte, i int) int { 37 | return int(b[i]) - '0' 38 | } 39 | 40 | // Check if the character at the specified position is a hex-digit. 41 | func is_hex(b []byte, i int) bool { 42 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' 43 | } 44 | 45 | // Get the value of a hex-digit. 46 | func as_hex(b []byte, i int) int { 47 | bi := b[i] 48 | if bi >= 'A' && bi <= 'F' { 49 | return int(bi) - 'A' + 10 50 | } 51 | if bi >= 'a' && bi <= 'f' { 52 | return int(bi) - 'a' + 10 53 | } 54 | return int(bi) - '0' 55 | } 56 | 57 | // Check if the character is ASCII. 58 | func is_ascii(b []byte, i int) bool { 59 | return b[i] <= 0x7F 60 | } 61 | 62 | // Check if the character at the start of the buffer can be printed unescaped. 63 | func is_printable(b []byte, i int) bool { 64 | return ((b[i] == 0x0A) || // . == #x0A 65 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E 66 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF 67 | (b[i] > 0xC2 && b[i] < 0xED) || 68 | (b[i] == 0xED && b[i+1] < 0xA0) || 69 | (b[i] == 0xEE) || 70 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD 71 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF 72 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) 73 | } 74 | 75 | // Check if the character at the specified position is NUL. 76 | func is_z(b []byte, i int) bool { 77 | return b[i] == 0x00 78 | } 79 | 80 | // Check if the beginning of the buffer is a BOM. 81 | func is_bom(b []byte, i int) bool { 82 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF 83 | } 84 | 85 | // Check if the character at the specified position is space. 86 | func is_space(b []byte, i int) bool { 87 | return b[i] == ' ' 88 | } 89 | 90 | // Check if the character at the specified position is tab. 91 | func is_tab(b []byte, i int) bool { 92 | return b[i] == '\t' 93 | } 94 | 95 | // Check if the character at the specified position is blank (space or tab). 96 | func is_blank(b []byte, i int) bool { 97 | //return is_space(b, i) || is_tab(b, i) 98 | return b[i] == ' ' || b[i] == '\t' 99 | } 100 | 101 | // Check if the character at the specified position is a line break. 102 | func is_break(b []byte, i int) bool { 103 | return (b[i] == '\r' || // CR (#xD) 104 | b[i] == '\n' || // LF (#xA) 105 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 106 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 107 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) 108 | } 109 | 110 | func is_crlf(b []byte, i int) bool { 111 | return b[i] == '\r' && b[i+1] == '\n' 112 | } 113 | 114 | // Check if the character is a line break or NUL. 115 | func is_breakz(b []byte, i int) bool { 116 | //return is_break(b, i) || is_z(b, i) 117 | return ( // is_break: 118 | b[i] == '\r' || // CR (#xD) 119 | b[i] == '\n' || // LF (#xA) 120 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 121 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 122 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 123 | // is_z: 124 | b[i] == 0) 125 | } 126 | 127 | // Check if the character is a line break, space, or NUL. 128 | func is_spacez(b []byte, i int) bool { 129 | //return is_space(b, i) || is_breakz(b, i) 130 | return ( // is_space: 131 | b[i] == ' ' || 132 | // is_breakz: 133 | b[i] == '\r' || // CR (#xD) 134 | b[i] == '\n' || // LF (#xA) 135 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 136 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 137 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 138 | b[i] == 0) 139 | } 140 | 141 | // Check if the character is a line break, space, tab, or NUL. 142 | func is_blankz(b []byte, i int) bool { 143 | //return is_blank(b, i) || is_breakz(b, i) 144 | return ( // is_blank: 145 | b[i] == ' ' || b[i] == '\t' || 146 | // is_breakz: 147 | b[i] == '\r' || // CR (#xD) 148 | b[i] == '\n' || // LF (#xA) 149 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 150 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 151 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 152 | b[i] == 0) 153 | } 154 | 155 | // Determine the width of the character. 156 | func width(b byte) int { 157 | // Don't replace these by a switch without first 158 | // confirming that it is being inlined. 159 | if b&0x80 == 0x00 { 160 | return 1 161 | } 162 | if b&0xE0 == 0xC0 { 163 | return 2 164 | } 165 | if b&0xF0 == 0xE0 { 166 | return 3 167 | } 168 | if b&0xF8 == 0xF0 { 169 | return 4 170 | } 171 | return 0 172 | 173 | } 174 | -------------------------------------------------------------------------------- /wercker.yml: -------------------------------------------------------------------------------- 1 | # This references the default golang container from 2 | # the Docker Hub: https://registry.hub.docker.com/u/library/golang/ 3 | # If you want Google's container you would reference google/golang 4 | # Read more about containers on our dev center 5 | # http://devcenter.wercker.com/docs/containers/index.html 6 | box: golang 7 | build: 8 | # The steps that will be executed on build 9 | # Steps make up the actions in your pipeline 10 | # Read more about steps on our dev center: 11 | # http://devcenter.wercker.com/docs/steps/index.html 12 | steps: 13 | # Sets the go workspace and places you package 14 | # at the right place in the workspace tree 15 | - setup-go-workspace 16 | # Test the project 17 | - script: 18 | name: go test 19 | code: | 20 | go test ./... 21 | --------------------------------------------------------------------------------