├── LICENSE ├── README.md ├── examples ├── crud.yaml └── thing.json ├── experiment ├── create.go └── yaml.go ├── go.mod ├── go.sum ├── hypothesis ├── jsonschema.go ├── response.go └── runner.go ├── main.go ├── main_test.go └── vendor ├── github.com └── xeipuuv │ ├── gojsonpointer │ ├── LICENSE-APACHE-2.0.txt │ ├── README.md │ └── pointer.go │ ├── gojsonreference │ ├── LICENSE-APACHE-2.0.txt │ ├── README.md │ └── reference.go │ └── gojsonschema │ ├── .gitignore │ ├── .travis.yml │ ├── LICENSE-APACHE-2.0.txt │ ├── README.md │ ├── draft.go │ ├── errors.go │ ├── format_checkers.go │ ├── glide.yaml │ ├── go.mod │ ├── go.sum │ ├── internalLog.go │ ├── jsonContext.go │ ├── jsonLoader.go │ ├── locales.go │ ├── result.go │ ├── schema.go │ ├── schemaLoader.go │ ├── schemaPool.go │ ├── schemaReferencePool.go │ ├── schemaType.go │ ├── subSchema.go │ ├── types.go │ ├── utils.go │ └── validation.go ├── gopkg.in └── yaml.v2 │ ├── .travis.yml │ ├── LICENSE │ ├── LICENSE.libyaml │ ├── NOTICE │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── emitterc.go │ ├── encode.go │ ├── go.mod │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── modules.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 David Gage (whytheplatypus) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # reagent [![GoDoc](https://godoc.org/github.com/whytheplatypus/reagent?status.svg)](http://godoc.org/github.com/whytheplatypus/reagent) [![Report card](https://goreportcard.com/badge/github.com/whytheplatypus/reagent)](https://goreportcard.com/report/github.com/whytheplatypus/reagent) 2 | 3 | A cli and library for declaring what how an API is expected to behave and checking that hypothesis. 4 | 5 | ## Installation 6 | `go install github.com/whytheplatypus/reagent` 7 | 8 | ## Usage 9 | 10 | Describe how you expect an API to behave (currently in YAML) 11 | 12 | Variables can be set from the command-line with `-var` e.g. `-var host=
`. 13 | This can be done multiple times `-var host=
-var token=` 14 | [examples/crud.yaml](/example/crud.yaml) 15 | 16 | ``` 17 | create_a_thing: 18 | name: "Create a thing" 19 | url: "{{ .host }}/things/" 20 | method: "POST" 21 | body: | 22 | { 23 | "hello": "world", 24 | "works": false 25 | } 26 | headers: 27 | Authorization: ["Bearer sample_bearer_token"] 28 | ``` 29 | State what you expect the API to do with this input. 30 | ``` 31 | assert: 32 | response: 33 | code: 200 34 | body: '{"id": 0}' 35 | headers: 36 | Content-Type: ["application/json"] 37 | ``` 38 | 39 | Steps from the same file are run in order and results from previous steps can be used 40 | e.g. `json .create_a_thing "id"` returns the value from the `id` key of the json response from the `create_a_thing` step. 41 | ``` 42 | read_a_thing: 43 | name: "Read a thing" 44 | url: "{{ .host }}/things/${ json .create_a_thing `id` }" 45 | method: "GET" 46 | headers: 47 | Authorization: ["Bearer sample_bearer_token"] 48 | assert: 49 | response: 50 | code: 200 51 | jsonschema: 52 | ref: "examples/thing.json" 53 | ``` 54 | 55 | For a full example run you can pull down the repository and use the server used for tests to experiment. 56 | ``` 57 | git clone github.com/whytheplatypus/reagent 58 | cd reagent 59 | ``` 60 | Start the test server 61 | ``` 62 | go test -live -v . 63 | ``` 64 | This will output the port the test server is running on. 65 | 66 | In another terminal run the example hypothesis. 67 | ``` 68 | go run . -v -var host=
examples/crud.yaml 69 | ``` 70 | Try modifying [examples/crud.yaml](/examples/crud.yaml) to make the run fail. 71 | 72 | -------------------------------------------------------------------------------- /examples/crud.yaml: -------------------------------------------------------------------------------- 1 | create_a_thing: 2 | name: "Create a thing" 3 | url: "{{ .host }}/things/" 4 | method: "POST" 5 | body: | 6 | { 7 | "hello": "world", 8 | "works": false 9 | } 10 | headers: 11 | Authorization: ["Bearer sample_bearer_token"] 12 | assert: 13 | response: 14 | code: 200 15 | body: '{"id": 0}' 16 | headers: 17 | Content-Type: ["application/json"] 18 | 19 | read_a_thing: 20 | name: "Read a thing" 21 | url: "{{ .host }}/things/${ json .create_a_thing `id` }" 22 | method: "GET" 23 | headers: 24 | Authorization: ["Bearer sample_bearer_token"] 25 | assert: 26 | response: 27 | code: 200 28 | jsonschema: 29 | ref: "examples/thing.json" 30 | 31 | delete_a_thing: 32 | name: "Delete a thing" 33 | url: "{{ .host }}/things/${ json .create_a_thing `id` }" 34 | method: "DELETE" 35 | headers: 36 | Authorization: ["Bearer sample_bearer_token"] 37 | assert: 38 | response: 39 | code: 201 40 | 41 | read_a_missing_thing: 42 | name: "Read a missing thing" 43 | url: "{{ .host }}/things/${ json .create_a_thing `id` }" 44 | method: "GET" 45 | headers: 46 | Authorization: ["Bearer sample_bearer_token"] 47 | assert: 48 | response: 49 | code: 404 50 | -------------------------------------------------------------------------------- /examples/thing.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "hello": { 4 | "type": "string" 5 | }, 6 | "works": { 7 | "type": "boolean" 8 | } 9 | }, 10 | "required": ["hello", "works"] 11 | } 12 | -------------------------------------------------------------------------------- /experiment/create.go: -------------------------------------------------------------------------------- 1 | package experiment 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "net/http" 7 | "text/template" 8 | 9 | "github.com/whytheplatypus/reagent/hypothesis" 10 | ) 11 | 12 | type steps map[string]*step 13 | 14 | type step struct { 15 | Name string 16 | URL string 17 | Assert map[string]map[string]interface{} 18 | Headers http.Header 19 | Method string 20 | Body string 21 | } 22 | 23 | func (s *step) Assertions() map[string]map[string]interface{} { 24 | return s.Assert 25 | } 26 | 27 | func (s *step) Do() (*http.Response, error) { 28 | req, err := http.NewRequest(s.Method, s.URL, bytes.NewBuffer([]byte(s.Body))) 29 | if err != nil { 30 | return nil, err 31 | } 32 | req.Header = s.Headers 33 | return http.DefaultClient.Do(req) 34 | } 35 | 36 | var funcMap = template.FuncMap{ 37 | // The name "title" is what the function will be called in the template text. 38 | "json": parseJSON, 39 | } 40 | 41 | func parseJSON(b []byte, key string) interface{} { 42 | var result map[string]interface{} 43 | if err := json.Unmarshal(b, &result); err != nil { 44 | return nil 45 | } 46 | return result[key] 47 | } 48 | 49 | // NewTrial creates a new trial from the toml file and variables provided. 50 | func NewTrial(name string, vars map[string]string, path string) (*Trial, error) { 51 | t := &Trial{ 52 | Variables: vars, 53 | Name: name, 54 | } 55 | if err := t.ParseFile(path); err != nil { 56 | return t, err 57 | } 58 | return t, nil 59 | } 60 | 61 | // Trial describes a set of behaviors an API is expected to exibit 62 | // and the results of testing those behaviors. 63 | type Trial struct { 64 | Variables map[string]string 65 | Name string 66 | steps map[string]*step 67 | keys []string 68 | results map[string]interface{} 69 | } 70 | 71 | // ParseFile parses a TOML file with this trials variables. 72 | func (t *Trial) ParseFile(path string) error { 73 | tmp, err := template.ParseFiles(path) 74 | if err != nil { 75 | return err 76 | } 77 | b := bytes.NewBuffer([]byte{}) 78 | if err := tmp.Execute(b, t.Variables); err != nil { 79 | return err 80 | } 81 | steps, keys, err := decodeYAML(b.Bytes()) 82 | if err != nil { 83 | return err 84 | } 85 | t.steps = steps 86 | t.keys = keys 87 | return nil 88 | } 89 | 90 | // Run executes the trial, recording the results and returning an error 91 | // if the hypothesis in the trial are disproven. 92 | func (t *Trial) Run() error { 93 | t.results = map[string]interface{}{} 94 | for _, name := range t.keys { 95 | step := t.steps[name] 96 | 97 | //template URL, Body 98 | 99 | b := bytes.NewBuffer([]byte{}) 100 | if err := template.Must(template.New(name).Delims("${", "}").Funcs(funcMap).Parse(step.URL)).Execute(b, t.results); err != nil { 101 | return err 102 | } 103 | step.URL = b.String() 104 | 105 | result, err := hypothesis.Check(step) 106 | if err != nil { 107 | return err 108 | } 109 | t.results[name] = result 110 | } 111 | return nil 112 | } 113 | -------------------------------------------------------------------------------- /experiment/yaml.go: -------------------------------------------------------------------------------- 1 | package experiment 2 | 3 | import ( 4 | "gopkg.in/yaml.v2" 5 | ) 6 | 7 | func decodeYAML(b []byte) (steps, []string, error) { 8 | var s steps 9 | if err := yaml.Unmarshal(b, &s); err != nil { 10 | return nil, nil, err 11 | } 12 | 13 | var ts yaml.MapSlice 14 | if err := yaml.Unmarshal(b, &ts); err != nil { 15 | return nil, nil, err 16 | } 17 | 18 | keys := make([]string, len(ts)) 19 | for i, item := range ts { 20 | keys[i] = item.Key.(string) 21 | } 22 | 23 | return s, keys, nil 24 | } 25 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/whytheplatypus/reagent 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/xeipuuv/gojsonschema v1.2.0 7 | gopkg.in/yaml.v2 v2.3.0 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 6 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 7 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 8 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= 9 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 10 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= 11 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= 12 | github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= 13 | github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= 14 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 15 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 16 | gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= 17 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 18 | -------------------------------------------------------------------------------- /hypothesis/jsonschema.go: -------------------------------------------------------------------------------- 1 | package hypothesis 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | "github.com/xeipuuv/gojsonschema" 10 | ) 11 | 12 | func init() { 13 | asserters["jsonschema"] = assertJSONSchema 14 | } 15 | 16 | func assertJSONSchema(r *http.Response, args map[string]interface{}) error { 17 | ref, ok := args["ref"].(string) 18 | if !ok { 19 | return fmt.Errorf("ref must be a string %T", ref) 20 | } 21 | schema, err := ioutil.ReadFile(ref) 22 | if err != nil { 23 | return err 24 | } 25 | schemaLoader := gojsonschema.NewStringLoader(string(schema)) 26 | 27 | content, err := ioutil.ReadAll(r.Body) 28 | if err != nil { 29 | return err 30 | } 31 | r.Body = ioutil.NopCloser(bytes.NewReader(content)) 32 | 33 | documentLoader := gojsonschema.NewStringLoader(string(content)) 34 | 35 | result, err := gojsonschema.Validate(schemaLoader, documentLoader) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | if !result.Valid() { 41 | var s string 42 | for _, desc := range result.Errors() { 43 | s = fmt.Sprintf("%s\n%s", s, desc) 44 | } 45 | return fmt.Errorf(s) 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /hypothesis/response.go: -------------------------------------------------------------------------------- 1 | package hypothesis 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | ) 9 | 10 | func init() { 11 | asserters["response"] = assertResponse 12 | } 13 | 14 | var checks = map[string]func(*http.Response, interface{}) error{ 15 | "code": checkCode, 16 | "protomajor": checkProtoMajor, 17 | "protominor": checkProtoMinor, 18 | "headers": checkHeader, 19 | "body": checkBody, 20 | } 21 | 22 | func assertResponse(r *http.Response, args map[string]interface{}) error { 23 | for key, check := range checks { 24 | c, ok := args[key] 25 | if ok { 26 | if err := check(r, c); err != nil { 27 | return err 28 | } 29 | } 30 | } 31 | return nil 32 | } 33 | 34 | func checkCode(r *http.Response, c interface{}) error { 35 | code, ok := c.(int) 36 | if !ok { 37 | return fmt.Errorf("Code must be an int %T", c) 38 | } 39 | if r.StatusCode != code { 40 | return fmt.Errorf("code not equal") 41 | } 42 | return nil 43 | } 44 | 45 | func checkProtoMajor(r *http.Response, c interface{}) error { 46 | proto, ok := c.(int64) 47 | if !ok { 48 | return fmt.Errorf("proto major must be an int %T", c) 49 | } 50 | if int64(r.ProtoMajor) != proto { 51 | return fmt.Errorf("proto major not equal") 52 | } 53 | return nil 54 | } 55 | 56 | func checkProtoMinor(r *http.Response, c interface{}) error { 57 | proto, ok := c.(int64) 58 | if !ok { 59 | return fmt.Errorf("proto minor must be an int %T", c) 60 | } 61 | if int64(r.ProtoMinor) != proto { 62 | return fmt.Errorf("proto minor not equal") 63 | } 64 | return nil 65 | } 66 | 67 | func checkHeader(r *http.Response, c interface{}) error { 68 | h, ok := c.(map[interface{}]interface{}) 69 | if !ok { 70 | return fmt.Errorf("Headers must be of the form Header = [value] %T", c) 71 | } 72 | headers := http.Header{} 73 | for k, v := range h { 74 | for _, vv := range v.([]interface{}) { 75 | headers.Add(k.(string), vv.(string)) 76 | } 77 | } 78 | for key := range headers { 79 | if headers.Get(key) != r.Header.Get(key) { 80 | return fmt.Errorf("%s header did not match; %s, %s", key, headers.Get(key), r.Header.Get(key)) 81 | } 82 | } 83 | return nil 84 | } 85 | 86 | func checkBody(r *http.Response, c interface{}) error { 87 | b, ok := c.(string) 88 | if !ok { 89 | return fmt.Errorf("Expected body value could not be parsed %T", c) 90 | } 91 | content, err := ioutil.ReadAll(r.Body) 92 | if err != nil { 93 | return err 94 | } 95 | r.Body = ioutil.NopCloser(bytes.NewReader(content)) 96 | if string(content) != b { 97 | return fmt.Errorf("Response body did not match") 98 | } 99 | return nil 100 | } 101 | -------------------------------------------------------------------------------- /hypothesis/runner.go: -------------------------------------------------------------------------------- 1 | package hypothesis 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "net/http/httputil" 9 | ) 10 | 11 | type assertable func(*http.Response, map[string]interface{}) error 12 | 13 | var asserters = map[string]assertable{} 14 | 15 | type testable interface { 16 | Do() (*http.Response, error) 17 | Assertions() map[string]map[string]interface{} 18 | } 19 | 20 | var ( 21 | // ErrUnregisteredAsserter is thrown if the type of assertion is not recognized. 22 | // currentlly supported assertions are `jsonschema` and `code` 23 | ErrUnregisteredAsserter = errors.New("asserter is not registered") 24 | ) 25 | 26 | // Check a hypothesis. Returns the content of the body of the API response and, if the hypothesis is disproven, an error. 27 | func Check(t testable) (result []byte, err error) { 28 | 29 | res, err := t.Do() 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | for asrt, args := range t.Assertions() { 35 | asserter, ok := asserters[asrt] 36 | if !ok { 37 | return nil, ErrUnregisteredAsserter 38 | } 39 | if err := asserter(res, args); err != nil { 40 | resp, _ := httputil.DumpResponse(res, true) 41 | req, _ := httputil.DumpRequest(res.Request, true) 42 | return nil, fmt.Errorf("%s :\n %s\n : %s", err, string(req), string(resp)) 43 | } 44 | } 45 | result, err = ioutil.ReadAll(res.Body) 46 | if err != nil { 47 | return nil, err 48 | } 49 | defer res.Body.Close() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "strings" 11 | "sync" 12 | 13 | "github.com/whytheplatypus/reagent/experiment" 14 | ) 15 | 16 | var exitCode = 0 17 | 18 | var errBadStringMapVar = errors.New("Variables must be of the form key=value") 19 | 20 | type stringMapVar map[string]string 21 | 22 | func (av stringMapVar) String() string { 23 | return "" 24 | } 25 | 26 | func (av stringMapVar) Set(s string) error { 27 | args := strings.SplitN(s, "=", 2) 28 | if len(args) != 2 { 29 | return errBadStringMapVar 30 | } 31 | av[args[0]] = args[1] 32 | return nil 33 | } 34 | 35 | func main() { 36 | flags := flag.NewFlagSet(os.Args[0], flag.ExitOnError) 37 | flags.Usage = func() { 38 | fmt.Fprintf(flags.Output(), "Usage of %s:\n %s [flags] [files]\nFlags:\n", os.Args[0], os.Args[0]) 39 | flags.PrintDefaults() 40 | } 41 | vars := stringMapVar{} 42 | var verbose bool 43 | flags.BoolVar(&verbose, "v", false, "Enable for verbose logging") 44 | flags.Var(&vars, "var", "Variables to use in the rendering of test files. Must be of the form key=value") 45 | flags.Parse(os.Args[1:]) 46 | tf := flags.Args() 47 | if verbose { 48 | log.SetFlags(log.LstdFlags) 49 | } else { 50 | log.SetOutput(ioutil.Discard) 51 | } 52 | var wg sync.WaitGroup 53 | for _, f := range tf { 54 | wg.Add(1) 55 | go func(f string) { 56 | defer wg.Done() 57 | t, err := experiment.NewTrial(f, vars, f) 58 | if err != nil { 59 | exitCode = 1 60 | fmt.Println(t.Name, err) 61 | return 62 | } 63 | if err := t.Run(); err != nil { 64 | exitCode = 1 65 | log.Println(t.Name, err) 66 | return 67 | } 68 | log.Println("PASS:", f) 69 | }(f) 70 | } 71 | wg.Wait() 72 | os.Exit(exitCode) 73 | } 74 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main_test 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "net/http" 8 | "net/http/httptest" 9 | "os" 10 | "os/signal" 11 | "strconv" 12 | "strings" 13 | "syscall" 14 | "testing" 15 | 16 | "github.com/whytheplatypus/reagent/experiment" 17 | ) 18 | 19 | var ( 20 | things = []map[string]interface{}{} 21 | ts *httptest.Server 22 | ) 23 | 24 | func TestCRUD(t *testing.T) { 25 | vars := map[string]string{ 26 | "host": ts.URL, 27 | } 28 | trial, err := experiment.NewTrial("crud", vars, "examples/crud.yaml") 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | 33 | if err := trial.Run(); err != nil { 34 | t.Fatal(err) 35 | } 36 | } 37 | 38 | func TestMain(m *testing.M) { 39 | ts = configureServer() 40 | defer ts.Close() 41 | // call flag.Parse() here if TestMain uses flags 42 | live := flag.Bool("live", false, "keep the test server alive") 43 | flag.Parse() 44 | if *live { 45 | fmt.Println(ts.URL) 46 | waitFor(syscall.SIGINT, syscall.SIGTERM) 47 | } 48 | os.Exit(m.Run()) 49 | } 50 | 51 | func waitFor(calls ...os.Signal) { 52 | sigs := make(chan os.Signal, 1) 53 | signal.Notify(sigs, calls...) 54 | <-sigs 55 | } 56 | 57 | func handleThings(rw http.ResponseWriter, r *http.Request) { 58 | switch r.Method { 59 | case http.MethodPost: 60 | d := json.NewDecoder(r.Body) 61 | defer r.Body.Close() 62 | var t map[string]interface{} 63 | if err := d.Decode(&t); err != nil { 64 | http.Error(rw, err.Error(), http.StatusInternalServerError) 65 | return 66 | } 67 | things = append(things, t) 68 | rw.Header().Set("Content-Type", "application/json") 69 | fmt.Fprintf(rw, "{\"id\": %d}", len(things)-1) 70 | default: 71 | http.Error(rw, "unsupported", http.StatusMethodNotAllowed) 72 | } 73 | } 74 | 75 | func handleThing(rw http.ResponseWriter, r *http.Request) { 76 | id, err := strconv.Atoi(strings.Split(r.URL.Path, "/")[2]) 77 | if err != nil { 78 | http.Error(rw, err.Error(), http.StatusInternalServerError) 79 | return 80 | } 81 | 82 | if len(things) < id+1 { 83 | http.NotFound(rw, r) 84 | return 85 | } 86 | 87 | t := things[id] 88 | switch r.Method { 89 | case http.MethodGet: 90 | res, err := json.Marshal(t) 91 | if err != nil { 92 | http.Error(rw, err.Error(), http.StatusInternalServerError) 93 | return 94 | } 95 | fmt.Fprintf(rw, "%s", string(res)) 96 | case http.MethodDelete: 97 | things = append(things[:id], things[id+1:]...) 98 | rw.WriteHeader(http.StatusCreated) 99 | default: 100 | http.Error(rw, "unsupported", http.StatusMethodNotAllowed) 101 | } 102 | } 103 | 104 | func configureServer() *httptest.Server { 105 | r := http.NewServeMux() 106 | r.HandleFunc("/things/", func(rw http.ResponseWriter, r *http.Request) { 107 | switch idPart := strings.Split(r.URL.Path, "/")[2]; idPart { 108 | case "": 109 | handleThings(rw, r) 110 | default: 111 | handleThing(rw, r) 112 | } 113 | }) 114 | ts := httptest.NewServer(r) 115 | return ts 116 | } 117 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonpointer/LICENSE-APACHE-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2015 xeipuuv 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonpointer/README.md: -------------------------------------------------------------------------------- 1 | # gojsonpointer 2 | An implementation of JSON Pointer - Go language 3 | 4 | ## Usage 5 | jsonText := `{ 6 | "name": "Bobby B", 7 | "occupation": { 8 | "title" : "King", 9 | "years" : 15, 10 | "heir" : "Joffrey B" 11 | } 12 | }` 13 | 14 | var jsonDocument map[string]interface{} 15 | json.Unmarshal([]byte(jsonText), &jsonDocument) 16 | 17 | //create a JSON pointer 18 | pointerString := "/occupation/title" 19 | pointer, _ := NewJsonPointer(pointerString) 20 | 21 | //SET a new value for the "title" in the document 22 | pointer.Set(jsonDocument, "Supreme Leader of Westeros") 23 | 24 | //GET the new "title" from the document 25 | title, _, _ := pointer.Get(jsonDocument) 26 | fmt.Println(title) //outputs "Supreme Leader of Westeros" 27 | 28 | //DELETE the "heir" from the document 29 | deletePointer := NewJsonPointer("/occupation/heir") 30 | deletePointer.Delete(jsonDocument) 31 | 32 | b, _ := json.Marshal(jsonDocument) 33 | fmt.Println(string(b)) 34 | //outputs `{"name":"Bobby B","occupation":{"title":"Supreme Leader of Westeros","years":15}}` 35 | 36 | 37 | ## References 38 | http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07 39 | 40 | ### Note 41 | The 4.Evaluation part of the previous reference, starting with 'If the currently referenced value is a JSON array, the reference token MUST contain either...' is not implemented. 42 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonpointer/pointer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonpointer 20 | // repository-desc An implementation of JSON Pointer - Go language 21 | // 22 | // description Main and unique file. 23 | // 24 | // created 25-02-2013 25 | 26 | package gojsonpointer 27 | 28 | import ( 29 | "errors" 30 | "fmt" 31 | "reflect" 32 | "strconv" 33 | "strings" 34 | ) 35 | 36 | const ( 37 | const_empty_pointer = `` 38 | const_pointer_separator = `/` 39 | 40 | const_invalid_start = `JSON pointer must be empty or start with a "` + const_pointer_separator + `"` 41 | ) 42 | 43 | type implStruct struct { 44 | mode string // "SET" or "GET" 45 | 46 | inDocument interface{} 47 | 48 | setInValue interface{} 49 | 50 | getOutNode interface{} 51 | getOutKind reflect.Kind 52 | outError error 53 | } 54 | 55 | type JsonPointer struct { 56 | referenceTokens []string 57 | } 58 | 59 | // NewJsonPointer parses the given string JSON pointer and returns an object 60 | func NewJsonPointer(jsonPointerString string) (p JsonPointer, err error) { 61 | 62 | // Pointer to the root of the document 63 | if len(jsonPointerString) == 0 { 64 | // Keep referenceTokens nil 65 | return 66 | } 67 | if jsonPointerString[0] != '/' { 68 | return p, errors.New(const_invalid_start) 69 | } 70 | 71 | p.referenceTokens = strings.Split(jsonPointerString[1:], const_pointer_separator) 72 | return 73 | } 74 | 75 | // Uses the pointer to retrieve a value from a JSON document 76 | func (p *JsonPointer) Get(document interface{}) (interface{}, reflect.Kind, error) { 77 | 78 | is := &implStruct{mode: "GET", inDocument: document} 79 | p.implementation(is) 80 | return is.getOutNode, is.getOutKind, is.outError 81 | 82 | } 83 | 84 | // Uses the pointer to update a value from a JSON document 85 | func (p *JsonPointer) Set(document interface{}, value interface{}) (interface{}, error) { 86 | 87 | is := &implStruct{mode: "SET", inDocument: document, setInValue: value} 88 | p.implementation(is) 89 | return document, is.outError 90 | 91 | } 92 | 93 | // Uses the pointer to delete a value from a JSON document 94 | func (p *JsonPointer) Delete(document interface{}) (interface{}, error) { 95 | is := &implStruct{mode: "DEL", inDocument: document} 96 | p.implementation(is) 97 | return document, is.outError 98 | } 99 | 100 | // Both Get and Set functions use the same implementation to avoid code duplication 101 | func (p *JsonPointer) implementation(i *implStruct) { 102 | 103 | kind := reflect.Invalid 104 | 105 | // Full document when empty 106 | if len(p.referenceTokens) == 0 { 107 | i.getOutNode = i.inDocument 108 | i.outError = nil 109 | i.getOutKind = kind 110 | i.outError = nil 111 | return 112 | } 113 | 114 | node := i.inDocument 115 | 116 | previousNodes := make([]interface{}, len(p.referenceTokens)) 117 | previousTokens := make([]string, len(p.referenceTokens)) 118 | 119 | for ti, token := range p.referenceTokens { 120 | 121 | isLastToken := ti == len(p.referenceTokens)-1 122 | previousNodes[ti] = node 123 | previousTokens[ti] = token 124 | 125 | switch v := node.(type) { 126 | 127 | case map[string]interface{}: 128 | decodedToken := decodeReferenceToken(token) 129 | if _, ok := v[decodedToken]; ok { 130 | node = v[decodedToken] 131 | if isLastToken && i.mode == "SET" { 132 | v[decodedToken] = i.setInValue 133 | } else if isLastToken && i.mode =="DEL" { 134 | delete(v,decodedToken) 135 | } 136 | } else if (isLastToken && i.mode == "SET") { 137 | v[decodedToken] = i.setInValue 138 | } else { 139 | i.outError = fmt.Errorf("Object has no key '%s'", decodedToken) 140 | i.getOutKind = reflect.Map 141 | i.getOutNode = nil 142 | return 143 | } 144 | 145 | case []interface{}: 146 | tokenIndex, err := strconv.Atoi(token) 147 | if err != nil { 148 | i.outError = fmt.Errorf("Invalid array index '%s'", token) 149 | i.getOutKind = reflect.Slice 150 | i.getOutNode = nil 151 | return 152 | } 153 | if tokenIndex < 0 || tokenIndex >= len(v) { 154 | i.outError = fmt.Errorf("Out of bound array[0,%d] index '%d'", len(v), tokenIndex) 155 | i.getOutKind = reflect.Slice 156 | i.getOutNode = nil 157 | return 158 | } 159 | 160 | node = v[tokenIndex] 161 | if isLastToken && i.mode == "SET" { 162 | v[tokenIndex] = i.setInValue 163 | } else if isLastToken && i.mode =="DEL" { 164 | v[tokenIndex] = v[len(v)-1] 165 | v[len(v)-1] = nil 166 | v = v[:len(v)-1] 167 | previousNodes[ti-1].(map[string]interface{})[previousTokens[ti-1]] = v 168 | } 169 | 170 | default: 171 | i.outError = fmt.Errorf("Invalid token reference '%s'", token) 172 | i.getOutKind = reflect.ValueOf(node).Kind() 173 | i.getOutNode = nil 174 | return 175 | } 176 | 177 | } 178 | 179 | i.getOutNode = node 180 | i.getOutKind = reflect.ValueOf(node).Kind() 181 | i.outError = nil 182 | } 183 | 184 | // Pointer to string representation function 185 | func (p *JsonPointer) String() string { 186 | 187 | if len(p.referenceTokens) == 0 { 188 | return const_empty_pointer 189 | } 190 | 191 | pointerString := const_pointer_separator + strings.Join(p.referenceTokens, const_pointer_separator) 192 | 193 | return pointerString 194 | } 195 | 196 | // Specific JSON pointer encoding here 197 | // ~0 => ~ 198 | // ~1 => / 199 | // ... and vice versa 200 | 201 | func decodeReferenceToken(token string) string { 202 | step1 := strings.Replace(token, `~1`, `/`, -1) 203 | step2 := strings.Replace(step1, `~0`, `~`, -1) 204 | return step2 205 | } 206 | 207 | func encodeReferenceToken(token string) string { 208 | step1 := strings.Replace(token, `~`, `~0`, -1) 209 | step2 := strings.Replace(step1, `/`, `~1`, -1) 210 | return step2 211 | } 212 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonreference/LICENSE-APACHE-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2015 xeipuuv 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonreference/README.md: -------------------------------------------------------------------------------- 1 | # gojsonreference 2 | An implementation of JSON Reference - Go language 3 | 4 | ## Dependencies 5 | https://github.com/xeipuuv/gojsonpointer 6 | 7 | ## References 8 | http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07 9 | 10 | http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 11 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonreference/reference.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonreference 20 | // repository-desc An implementation of JSON Reference - Go language 21 | // 22 | // description Main and unique file. 23 | // 24 | // created 26-02-2013 25 | 26 | package gojsonreference 27 | 28 | import ( 29 | "errors" 30 | "net/url" 31 | "path/filepath" 32 | "runtime" 33 | "strings" 34 | 35 | "github.com/xeipuuv/gojsonpointer" 36 | ) 37 | 38 | const ( 39 | const_fragment_char = `#` 40 | ) 41 | 42 | func NewJsonReference(jsonReferenceString string) (JsonReference, error) { 43 | 44 | var r JsonReference 45 | err := r.parse(jsonReferenceString) 46 | return r, err 47 | 48 | } 49 | 50 | type JsonReference struct { 51 | referenceUrl *url.URL 52 | referencePointer gojsonpointer.JsonPointer 53 | 54 | HasFullUrl bool 55 | HasUrlPathOnly bool 56 | HasFragmentOnly bool 57 | HasFileScheme bool 58 | HasFullFilePath bool 59 | } 60 | 61 | func (r *JsonReference) GetUrl() *url.URL { 62 | return r.referenceUrl 63 | } 64 | 65 | func (r *JsonReference) GetPointer() *gojsonpointer.JsonPointer { 66 | return &r.referencePointer 67 | } 68 | 69 | func (r *JsonReference) String() string { 70 | 71 | if r.referenceUrl != nil { 72 | return r.referenceUrl.String() 73 | } 74 | 75 | if r.HasFragmentOnly { 76 | return const_fragment_char + r.referencePointer.String() 77 | } 78 | 79 | return r.referencePointer.String() 80 | } 81 | 82 | func (r *JsonReference) IsCanonical() bool { 83 | return (r.HasFileScheme && r.HasFullFilePath) || (!r.HasFileScheme && r.HasFullUrl) 84 | } 85 | 86 | // "Constructor", parses the given string JSON reference 87 | func (r *JsonReference) parse(jsonReferenceString string) (err error) { 88 | 89 | r.referenceUrl, err = url.Parse(jsonReferenceString) 90 | if err != nil { 91 | return 92 | } 93 | refUrl := r.referenceUrl 94 | 95 | if refUrl.Scheme != "" && refUrl.Host != "" { 96 | r.HasFullUrl = true 97 | } else { 98 | if refUrl.Path != "" { 99 | r.HasUrlPathOnly = true 100 | } else if refUrl.RawQuery == "" && refUrl.Fragment != "" { 101 | r.HasFragmentOnly = true 102 | } 103 | } 104 | 105 | r.HasFileScheme = refUrl.Scheme == "file" 106 | if runtime.GOOS == "windows" { 107 | // on Windows, a file URL may have an extra leading slash, and if it 108 | // doesn't then its first component will be treated as the host by the 109 | // Go runtime 110 | if refUrl.Host == "" && strings.HasPrefix(refUrl.Path, "/") { 111 | r.HasFullFilePath = filepath.IsAbs(refUrl.Path[1:]) 112 | } else { 113 | r.HasFullFilePath = filepath.IsAbs(refUrl.Host + refUrl.Path) 114 | } 115 | } else { 116 | r.HasFullFilePath = filepath.IsAbs(refUrl.Path) 117 | } 118 | 119 | // invalid json-pointer error means url has no json-pointer fragment. simply ignore error 120 | r.referencePointer, _ = gojsonpointer.NewJsonPointer(refUrl.Fragment) 121 | 122 | return 123 | } 124 | 125 | // Creates a new reference from a parent and a child 126 | // If the child cannot inherit from the parent, an error is returned 127 | func (r *JsonReference) Inherits(child JsonReference) (*JsonReference, error) { 128 | if child.GetUrl() == nil { 129 | return nil, errors.New("childUrl is nil!") 130 | } 131 | 132 | if r.GetUrl() == nil { 133 | return nil, errors.New("parentUrl is nil!") 134 | } 135 | 136 | // Get a copy of the parent url to make sure we do not modify the original. 137 | // URL reference resolving fails if the fragment of the child is empty, but the parent's is not. 138 | // The fragment of the child must be used, so the fragment of the parent is manually removed. 139 | parentUrl := *r.GetUrl() 140 | parentUrl.Fragment = "" 141 | 142 | ref, err := NewJsonReference(parentUrl.ResolveReference(child.GetUrl()).String()) 143 | if err != nil { 144 | return nil, err 145 | } 146 | return &ref, err 147 | } 148 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/.gitignore: -------------------------------------------------------------------------------- 1 | *.sw[nop] 2 | *.iml 3 | .vscode/ 4 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - "1.11" 4 | - "1.12" 5 | - "1.13" 6 | before_install: 7 | - go get github.com/xeipuuv/gojsonreference 8 | - go get github.com/xeipuuv/gojsonpointer 9 | - go get github.com/stretchr/testify/assert 10 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/LICENSE-APACHE-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2015 xeipuuv 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/draft.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 johandorland ( https://github.com/johandorland ) 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 | 15 | package gojsonschema 16 | 17 | import ( 18 | "errors" 19 | "math" 20 | "reflect" 21 | 22 | "github.com/xeipuuv/gojsonreference" 23 | ) 24 | 25 | // Draft is a JSON-schema draft version 26 | type Draft int 27 | 28 | // Supported Draft versions 29 | const ( 30 | Draft4 Draft = 4 31 | Draft6 Draft = 6 32 | Draft7 Draft = 7 33 | Hybrid Draft = math.MaxInt32 34 | ) 35 | 36 | type draftConfig struct { 37 | Version Draft 38 | MetaSchemaURL string 39 | MetaSchema string 40 | } 41 | type draftConfigs []draftConfig 42 | 43 | var drafts draftConfigs 44 | 45 | func init() { 46 | drafts = []draftConfig{ 47 | { 48 | Version: Draft4, 49 | MetaSchemaURL: "http://json-schema.org/draft-04/schema", 50 | MetaSchema: `{"id":"http://json-schema.org/draft-04/schema#","$schema":"http://json-schema.org/draft-04/schema#","description":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"positiveInteger":{"type":"integer","minimum":0},"positiveIntegerDefault0":{"allOf":[{"$ref":"#/definitions/positiveInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true}},"type":"object","properties":{"id":{"type":"string"},"$schema":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"multipleOf":{"type":"number","minimum":0,"exclusiveMinimum":true},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"boolean","default":false},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"boolean","default":false},"maxLength":{"$ref":"#/definitions/positiveInteger"},"minLength":{"$ref":"#/definitions/positiveIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/positiveInteger"},"minItems":{"$ref":"#/definitions/positiveIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxProperties":{"$ref":"#/definitions/positiveInteger"},"minProperties":{"$ref":"#/definitions/positiveIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"dependencies":{"exclusiveMaximum":["maximum"],"exclusiveMinimum":["minimum"]},"default":{}}`, 51 | }, 52 | { 53 | Version: Draft6, 54 | MetaSchemaURL: "http://json-schema.org/draft-06/schema", 55 | MetaSchema: `{"$schema":"http://json-schema.org/draft-06/schema#","$id":"http://json-schema.org/draft-06/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"examples":{"type":"array","items":{}},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":{},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":{}}`, 56 | }, 57 | { 58 | Version: Draft7, 59 | MetaSchemaURL: "http://json-schema.org/draft-07/schema", 60 | MetaSchema: `{"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}`, 61 | }, 62 | } 63 | } 64 | 65 | func (dc draftConfigs) GetMetaSchema(url string) string { 66 | for _, config := range dc { 67 | if config.MetaSchemaURL == url { 68 | return config.MetaSchema 69 | } 70 | } 71 | return "" 72 | } 73 | func (dc draftConfigs) GetDraftVersion(url string) *Draft { 74 | for _, config := range dc { 75 | if config.MetaSchemaURL == url { 76 | return &config.Version 77 | } 78 | } 79 | return nil 80 | } 81 | func (dc draftConfigs) GetSchemaURL(draft Draft) string { 82 | for _, config := range dc { 83 | if config.Version == draft { 84 | return config.MetaSchemaURL 85 | } 86 | } 87 | return "" 88 | } 89 | 90 | func parseSchemaURL(documentNode interface{}) (string, *Draft, error) { 91 | 92 | if isKind(documentNode, reflect.Bool) { 93 | return "", nil, nil 94 | } 95 | 96 | if !isKind(documentNode, reflect.Map) { 97 | return "", nil, errors.New("schema is invalid") 98 | } 99 | 100 | m := documentNode.(map[string]interface{}) 101 | 102 | if existsMapKey(m, KEY_SCHEMA) { 103 | if !isKind(m[KEY_SCHEMA], reflect.String) { 104 | return "", nil, errors.New(formatErrorDescription( 105 | Locale.MustBeOfType(), 106 | ErrorDetails{ 107 | "key": KEY_SCHEMA, 108 | "type": TYPE_STRING, 109 | }, 110 | )) 111 | } 112 | 113 | schemaReference, err := gojsonreference.NewJsonReference(m[KEY_SCHEMA].(string)) 114 | 115 | if err != nil { 116 | return "", nil, err 117 | } 118 | 119 | schema := schemaReference.String() 120 | 121 | return schema, drafts.GetDraftVersion(schema), nil 122 | } 123 | 124 | return "", nil, nil 125 | } 126 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/errors.go: -------------------------------------------------------------------------------- 1 | package gojsonschema 2 | 3 | import ( 4 | "bytes" 5 | "sync" 6 | "text/template" 7 | ) 8 | 9 | var errorTemplates = errorTemplate{template.New("errors-new"), sync.RWMutex{}} 10 | 11 | // template.Template is not thread-safe for writing, so some locking is done 12 | // sync.RWMutex is used for efficiently locking when new templates are created 13 | type errorTemplate struct { 14 | *template.Template 15 | sync.RWMutex 16 | } 17 | 18 | type ( 19 | 20 | // FalseError. ErrorDetails: - 21 | FalseError struct { 22 | ResultErrorFields 23 | } 24 | 25 | // RequiredError indicates that a required field is missing 26 | // ErrorDetails: property string 27 | RequiredError struct { 28 | ResultErrorFields 29 | } 30 | 31 | // InvalidTypeError indicates that a field has the incorrect type 32 | // ErrorDetails: expected, given 33 | InvalidTypeError struct { 34 | ResultErrorFields 35 | } 36 | 37 | // NumberAnyOfError is produced in case of a failing "anyOf" validation 38 | // ErrorDetails: - 39 | NumberAnyOfError struct { 40 | ResultErrorFields 41 | } 42 | 43 | // NumberOneOfError is produced in case of a failing "oneOf" validation 44 | // ErrorDetails: - 45 | NumberOneOfError struct { 46 | ResultErrorFields 47 | } 48 | 49 | // NumberAllOfError is produced in case of a failing "allOf" validation 50 | // ErrorDetails: - 51 | NumberAllOfError struct { 52 | ResultErrorFields 53 | } 54 | 55 | // NumberNotError is produced if a "not" validation failed 56 | // ErrorDetails: - 57 | NumberNotError struct { 58 | ResultErrorFields 59 | } 60 | 61 | // MissingDependencyError is produced in case of a "missing dependency" problem 62 | // ErrorDetails: dependency 63 | MissingDependencyError struct { 64 | ResultErrorFields 65 | } 66 | 67 | // InternalError indicates an internal error 68 | // ErrorDetails: error 69 | InternalError struct { 70 | ResultErrorFields 71 | } 72 | 73 | // ConstError indicates a const error 74 | // ErrorDetails: allowed 75 | ConstError struct { 76 | ResultErrorFields 77 | } 78 | 79 | // EnumError indicates an enum error 80 | // ErrorDetails: allowed 81 | EnumError struct { 82 | ResultErrorFields 83 | } 84 | 85 | // ArrayNoAdditionalItemsError is produced if additional items were found, but not allowed 86 | // ErrorDetails: - 87 | ArrayNoAdditionalItemsError struct { 88 | ResultErrorFields 89 | } 90 | 91 | // ArrayMinItemsError is produced if an array contains less items than the allowed minimum 92 | // ErrorDetails: min 93 | ArrayMinItemsError struct { 94 | ResultErrorFields 95 | } 96 | 97 | // ArrayMaxItemsError is produced if an array contains more items than the allowed maximum 98 | // ErrorDetails: max 99 | ArrayMaxItemsError struct { 100 | ResultErrorFields 101 | } 102 | 103 | // ItemsMustBeUniqueError is produced if an array requires unique items, but contains non-unique items 104 | // ErrorDetails: type, i, j 105 | ItemsMustBeUniqueError struct { 106 | ResultErrorFields 107 | } 108 | 109 | // ArrayContainsError is produced if an array contains invalid items 110 | // ErrorDetails: 111 | ArrayContainsError struct { 112 | ResultErrorFields 113 | } 114 | 115 | // ArrayMinPropertiesError is produced if an object contains less properties than the allowed minimum 116 | // ErrorDetails: min 117 | ArrayMinPropertiesError struct { 118 | ResultErrorFields 119 | } 120 | 121 | // ArrayMaxPropertiesError is produced if an object contains more properties than the allowed maximum 122 | // ErrorDetails: max 123 | ArrayMaxPropertiesError struct { 124 | ResultErrorFields 125 | } 126 | 127 | // AdditionalPropertyNotAllowedError is produced if an object has additional properties, but not allowed 128 | // ErrorDetails: property 129 | AdditionalPropertyNotAllowedError struct { 130 | ResultErrorFields 131 | } 132 | 133 | // InvalidPropertyPatternError is produced if an pattern was found 134 | // ErrorDetails: property, pattern 135 | InvalidPropertyPatternError struct { 136 | ResultErrorFields 137 | } 138 | 139 | // InvalidPropertyNameError is produced if an invalid-named property was found 140 | // ErrorDetails: property 141 | InvalidPropertyNameError struct { 142 | ResultErrorFields 143 | } 144 | 145 | // StringLengthGTEError is produced if a string is shorter than the minimum required length 146 | // ErrorDetails: min 147 | StringLengthGTEError struct { 148 | ResultErrorFields 149 | } 150 | 151 | // StringLengthLTEError is produced if a string is longer than the maximum allowed length 152 | // ErrorDetails: max 153 | StringLengthLTEError struct { 154 | ResultErrorFields 155 | } 156 | 157 | // DoesNotMatchPatternError is produced if a string does not match the defined pattern 158 | // ErrorDetails: pattern 159 | DoesNotMatchPatternError struct { 160 | ResultErrorFields 161 | } 162 | 163 | // DoesNotMatchFormatError is produced if a string does not match the defined format 164 | // ErrorDetails: format 165 | DoesNotMatchFormatError struct { 166 | ResultErrorFields 167 | } 168 | 169 | // MultipleOfError is produced if a number is not a multiple of the defined multipleOf 170 | // ErrorDetails: multiple 171 | MultipleOfError struct { 172 | ResultErrorFields 173 | } 174 | 175 | // NumberGTEError is produced if a number is lower than the allowed minimum 176 | // ErrorDetails: min 177 | NumberGTEError struct { 178 | ResultErrorFields 179 | } 180 | 181 | // NumberGTError is produced if a number is lower than, or equal to the specified minimum, and exclusiveMinimum is set 182 | // ErrorDetails: min 183 | NumberGTError struct { 184 | ResultErrorFields 185 | } 186 | 187 | // NumberLTEError is produced if a number is higher than the allowed maximum 188 | // ErrorDetails: max 189 | NumberLTEError struct { 190 | ResultErrorFields 191 | } 192 | 193 | // NumberLTError is produced if a number is higher than, or equal to the specified maximum, and exclusiveMaximum is set 194 | // ErrorDetails: max 195 | NumberLTError struct { 196 | ResultErrorFields 197 | } 198 | 199 | // ConditionThenError is produced if a condition's "then" validation is invalid 200 | // ErrorDetails: - 201 | ConditionThenError struct { 202 | ResultErrorFields 203 | } 204 | 205 | // ConditionElseError is produced if a condition's "else" condition is invalid 206 | // ErrorDetails: - 207 | ConditionElseError struct { 208 | ResultErrorFields 209 | } 210 | ) 211 | 212 | // newError takes a ResultError type and sets the type, context, description, details, value, and field 213 | func newError(err ResultError, context *JsonContext, value interface{}, locale locale, details ErrorDetails) { 214 | var t string 215 | var d string 216 | switch err.(type) { 217 | case *FalseError: 218 | t = "false" 219 | d = locale.False() 220 | case *RequiredError: 221 | t = "required" 222 | d = locale.Required() 223 | case *InvalidTypeError: 224 | t = "invalid_type" 225 | d = locale.InvalidType() 226 | case *NumberAnyOfError: 227 | t = "number_any_of" 228 | d = locale.NumberAnyOf() 229 | case *NumberOneOfError: 230 | t = "number_one_of" 231 | d = locale.NumberOneOf() 232 | case *NumberAllOfError: 233 | t = "number_all_of" 234 | d = locale.NumberAllOf() 235 | case *NumberNotError: 236 | t = "number_not" 237 | d = locale.NumberNot() 238 | case *MissingDependencyError: 239 | t = "missing_dependency" 240 | d = locale.MissingDependency() 241 | case *InternalError: 242 | t = "internal" 243 | d = locale.Internal() 244 | case *ConstError: 245 | t = "const" 246 | d = locale.Const() 247 | case *EnumError: 248 | t = "enum" 249 | d = locale.Enum() 250 | case *ArrayNoAdditionalItemsError: 251 | t = "array_no_additional_items" 252 | d = locale.ArrayNoAdditionalItems() 253 | case *ArrayMinItemsError: 254 | t = "array_min_items" 255 | d = locale.ArrayMinItems() 256 | case *ArrayMaxItemsError: 257 | t = "array_max_items" 258 | d = locale.ArrayMaxItems() 259 | case *ItemsMustBeUniqueError: 260 | t = "unique" 261 | d = locale.Unique() 262 | case *ArrayContainsError: 263 | t = "contains" 264 | d = locale.ArrayContains() 265 | case *ArrayMinPropertiesError: 266 | t = "array_min_properties" 267 | d = locale.ArrayMinProperties() 268 | case *ArrayMaxPropertiesError: 269 | t = "array_max_properties" 270 | d = locale.ArrayMaxProperties() 271 | case *AdditionalPropertyNotAllowedError: 272 | t = "additional_property_not_allowed" 273 | d = locale.AdditionalPropertyNotAllowed() 274 | case *InvalidPropertyPatternError: 275 | t = "invalid_property_pattern" 276 | d = locale.InvalidPropertyPattern() 277 | case *InvalidPropertyNameError: 278 | t = "invalid_property_name" 279 | d = locale.InvalidPropertyName() 280 | case *StringLengthGTEError: 281 | t = "string_gte" 282 | d = locale.StringGTE() 283 | case *StringLengthLTEError: 284 | t = "string_lte" 285 | d = locale.StringLTE() 286 | case *DoesNotMatchPatternError: 287 | t = "pattern" 288 | d = locale.DoesNotMatchPattern() 289 | case *DoesNotMatchFormatError: 290 | t = "format" 291 | d = locale.DoesNotMatchFormat() 292 | case *MultipleOfError: 293 | t = "multiple_of" 294 | d = locale.MultipleOf() 295 | case *NumberGTEError: 296 | t = "number_gte" 297 | d = locale.NumberGTE() 298 | case *NumberGTError: 299 | t = "number_gt" 300 | d = locale.NumberGT() 301 | case *NumberLTEError: 302 | t = "number_lte" 303 | d = locale.NumberLTE() 304 | case *NumberLTError: 305 | t = "number_lt" 306 | d = locale.NumberLT() 307 | case *ConditionThenError: 308 | t = "condition_then" 309 | d = locale.ConditionThen() 310 | case *ConditionElseError: 311 | t = "condition_else" 312 | d = locale.ConditionElse() 313 | } 314 | 315 | err.SetType(t) 316 | err.SetContext(context) 317 | err.SetValue(value) 318 | err.SetDetails(details) 319 | err.SetDescriptionFormat(d) 320 | details["field"] = err.Field() 321 | 322 | if _, exists := details["context"]; !exists && context != nil { 323 | details["context"] = context.String() 324 | } 325 | 326 | err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details)) 327 | } 328 | 329 | // formatErrorDescription takes a string in the default text/template 330 | // format and converts it to a string with replacements. The fields come 331 | // from the ErrorDetails struct and vary for each type of error. 332 | func formatErrorDescription(s string, details ErrorDetails) string { 333 | 334 | var tpl *template.Template 335 | var descrAsBuffer bytes.Buffer 336 | var err error 337 | 338 | errorTemplates.RLock() 339 | tpl = errorTemplates.Lookup(s) 340 | errorTemplates.RUnlock() 341 | 342 | if tpl == nil { 343 | errorTemplates.Lock() 344 | tpl = errorTemplates.New(s) 345 | 346 | if ErrorTemplateFuncs != nil { 347 | tpl.Funcs(ErrorTemplateFuncs) 348 | } 349 | 350 | tpl, err = tpl.Parse(s) 351 | errorTemplates.Unlock() 352 | 353 | if err != nil { 354 | return err.Error() 355 | } 356 | } 357 | 358 | err = tpl.Execute(&descrAsBuffer, details) 359 | if err != nil { 360 | return err.Error() 361 | } 362 | 363 | return descrAsBuffer.String() 364 | } 365 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/format_checkers.go: -------------------------------------------------------------------------------- 1 | package gojsonschema 2 | 3 | import ( 4 | "net" 5 | "net/mail" 6 | "net/url" 7 | "regexp" 8 | "strings" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | type ( 14 | // FormatChecker is the interface all formatters added to FormatCheckerChain must implement 15 | FormatChecker interface { 16 | // IsFormat checks if input has the correct format and type 17 | IsFormat(input interface{}) bool 18 | } 19 | 20 | // FormatCheckerChain holds the formatters 21 | FormatCheckerChain struct { 22 | formatters map[string]FormatChecker 23 | } 24 | 25 | // EmailFormatChecker verifies email address formats 26 | EmailFormatChecker struct{} 27 | 28 | // IPV4FormatChecker verifies IP addresses in the IPv4 format 29 | IPV4FormatChecker struct{} 30 | 31 | // IPV6FormatChecker verifies IP addresses in the IPv6 format 32 | IPV6FormatChecker struct{} 33 | 34 | // DateTimeFormatChecker verifies date/time formats per RFC3339 5.6 35 | // 36 | // Valid formats: 37 | // Partial Time: HH:MM:SS 38 | // Full Date: YYYY-MM-DD 39 | // Full Time: HH:MM:SSZ-07:00 40 | // Date Time: YYYY-MM-DDTHH:MM:SSZ-0700 41 | // 42 | // Where 43 | // YYYY = 4DIGIT year 44 | // MM = 2DIGIT month ; 01-12 45 | // DD = 2DIGIT day-month ; 01-28, 01-29, 01-30, 01-31 based on month/year 46 | // HH = 2DIGIT hour ; 00-23 47 | // MM = 2DIGIT ; 00-59 48 | // SS = 2DIGIT ; 00-58, 00-60 based on leap second rules 49 | // T = Literal 50 | // Z = Literal 51 | // 52 | // Note: Nanoseconds are also suported in all formats 53 | // 54 | // http://tools.ietf.org/html/rfc3339#section-5.6 55 | DateTimeFormatChecker struct{} 56 | 57 | // DateFormatChecker verifies date formats 58 | // 59 | // Valid format: 60 | // Full Date: YYYY-MM-DD 61 | // 62 | // Where 63 | // YYYY = 4DIGIT year 64 | // MM = 2DIGIT month ; 01-12 65 | // DD = 2DIGIT day-month ; 01-28, 01-29, 01-30, 01-31 based on month/year 66 | DateFormatChecker struct{} 67 | 68 | // TimeFormatChecker verifies time formats 69 | // 70 | // Valid formats: 71 | // Partial Time: HH:MM:SS 72 | // Full Time: HH:MM:SSZ-07:00 73 | // 74 | // Where 75 | // HH = 2DIGIT hour ; 00-23 76 | // MM = 2DIGIT ; 00-59 77 | // SS = 2DIGIT ; 00-58, 00-60 based on leap second rules 78 | // T = Literal 79 | // Z = Literal 80 | TimeFormatChecker struct{} 81 | 82 | // URIFormatChecker validates a URI with a valid Scheme per RFC3986 83 | URIFormatChecker struct{} 84 | 85 | // URIReferenceFormatChecker validates a URI or relative-reference per RFC3986 86 | URIReferenceFormatChecker struct{} 87 | 88 | // URITemplateFormatChecker validates a URI template per RFC6570 89 | URITemplateFormatChecker struct{} 90 | 91 | // HostnameFormatChecker validates a hostname is in the correct format 92 | HostnameFormatChecker struct{} 93 | 94 | // UUIDFormatChecker validates a UUID is in the correct format 95 | UUIDFormatChecker struct{} 96 | 97 | // RegexFormatChecker validates a regex is in the correct format 98 | RegexFormatChecker struct{} 99 | 100 | // JSONPointerFormatChecker validates a JSON Pointer per RFC6901 101 | JSONPointerFormatChecker struct{} 102 | 103 | // RelativeJSONPointerFormatChecker validates a relative JSON Pointer is in the correct format 104 | RelativeJSONPointerFormatChecker struct{} 105 | ) 106 | 107 | var ( 108 | // FormatCheckers holds the valid formatters, and is a public variable 109 | // so library users can add custom formatters 110 | FormatCheckers = FormatCheckerChain{ 111 | formatters: map[string]FormatChecker{ 112 | "date": DateFormatChecker{}, 113 | "time": TimeFormatChecker{}, 114 | "date-time": DateTimeFormatChecker{}, 115 | "hostname": HostnameFormatChecker{}, 116 | "email": EmailFormatChecker{}, 117 | "idn-email": EmailFormatChecker{}, 118 | "ipv4": IPV4FormatChecker{}, 119 | "ipv6": IPV6FormatChecker{}, 120 | "uri": URIFormatChecker{}, 121 | "uri-reference": URIReferenceFormatChecker{}, 122 | "iri": URIFormatChecker{}, 123 | "iri-reference": URIReferenceFormatChecker{}, 124 | "uri-template": URITemplateFormatChecker{}, 125 | "uuid": UUIDFormatChecker{}, 126 | "regex": RegexFormatChecker{}, 127 | "json-pointer": JSONPointerFormatChecker{}, 128 | "relative-json-pointer": RelativeJSONPointerFormatChecker{}, 129 | }, 130 | } 131 | 132 | // Regex credit: https://www.socketloop.com/tutorials/golang-validate-hostname 133 | rxHostname = regexp.MustCompile(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`) 134 | 135 | // Use a regex to make sure curly brackets are balanced properly after validating it as a AURI 136 | rxURITemplate = regexp.MustCompile("^([^{]*({[^}]*})?)*$") 137 | 138 | rxUUID = regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$") 139 | 140 | rxJSONPointer = regexp.MustCompile("^(?:/(?:[^~/]|~0|~1)*)*$") 141 | 142 | rxRelJSONPointer = regexp.MustCompile("^(?:0|[1-9][0-9]*)(?:#|(?:/(?:[^~/]|~0|~1)*)*)$") 143 | 144 | lock = new(sync.RWMutex) 145 | ) 146 | 147 | // Add adds a FormatChecker to the FormatCheckerChain 148 | // The name used will be the value used for the format key in your json schema 149 | func (c *FormatCheckerChain) Add(name string, f FormatChecker) *FormatCheckerChain { 150 | lock.Lock() 151 | c.formatters[name] = f 152 | lock.Unlock() 153 | 154 | return c 155 | } 156 | 157 | // Remove deletes a FormatChecker from the FormatCheckerChain (if it exists) 158 | func (c *FormatCheckerChain) Remove(name string) *FormatCheckerChain { 159 | lock.Lock() 160 | delete(c.formatters, name) 161 | lock.Unlock() 162 | 163 | return c 164 | } 165 | 166 | // Has checks to see if the FormatCheckerChain holds a FormatChecker with the given name 167 | func (c *FormatCheckerChain) Has(name string) bool { 168 | lock.RLock() 169 | _, ok := c.formatters[name] 170 | lock.RUnlock() 171 | 172 | return ok 173 | } 174 | 175 | // IsFormat will check an input against a FormatChecker with the given name 176 | // to see if it is the correct format 177 | func (c *FormatCheckerChain) IsFormat(name string, input interface{}) bool { 178 | lock.RLock() 179 | f, ok := c.formatters[name] 180 | lock.RUnlock() 181 | 182 | // If a format is unrecognized it should always pass validation 183 | if !ok { 184 | return true 185 | } 186 | 187 | return f.IsFormat(input) 188 | } 189 | 190 | // IsFormat checks if input is a correctly formatted e-mail address 191 | func (f EmailFormatChecker) IsFormat(input interface{}) bool { 192 | asString, ok := input.(string) 193 | if !ok { 194 | return false 195 | } 196 | 197 | _, err := mail.ParseAddress(asString) 198 | return err == nil 199 | } 200 | 201 | // IsFormat checks if input is a correctly formatted IPv4-address 202 | func (f IPV4FormatChecker) IsFormat(input interface{}) bool { 203 | asString, ok := input.(string) 204 | if !ok { 205 | return false 206 | } 207 | 208 | // Credit: https://github.com/asaskevich/govalidator 209 | ip := net.ParseIP(asString) 210 | return ip != nil && strings.Contains(asString, ".") 211 | } 212 | 213 | // IsFormat checks if input is a correctly formatted IPv6=address 214 | func (f IPV6FormatChecker) IsFormat(input interface{}) bool { 215 | asString, ok := input.(string) 216 | if !ok { 217 | return false 218 | } 219 | 220 | // Credit: https://github.com/asaskevich/govalidator 221 | ip := net.ParseIP(asString) 222 | return ip != nil && strings.Contains(asString, ":") 223 | } 224 | 225 | // IsFormat checks if input is a correctly formatted date/time per RFC3339 5.6 226 | func (f DateTimeFormatChecker) IsFormat(input interface{}) bool { 227 | asString, ok := input.(string) 228 | if !ok { 229 | return false 230 | } 231 | 232 | formats := []string{ 233 | "15:04:05", 234 | "15:04:05Z07:00", 235 | "2006-01-02", 236 | time.RFC3339, 237 | time.RFC3339Nano, 238 | } 239 | 240 | for _, format := range formats { 241 | if _, err := time.Parse(format, asString); err == nil { 242 | return true 243 | } 244 | } 245 | 246 | return false 247 | } 248 | 249 | // IsFormat checks if input is a correctly formatted date (YYYY-MM-DD) 250 | func (f DateFormatChecker) IsFormat(input interface{}) bool { 251 | asString, ok := input.(string) 252 | if !ok { 253 | return false 254 | } 255 | _, err := time.Parse("2006-01-02", asString) 256 | return err == nil 257 | } 258 | 259 | // IsFormat checks if input correctly formatted time (HH:MM:SS or HH:MM:SSZ-07:00) 260 | func (f TimeFormatChecker) IsFormat(input interface{}) bool { 261 | asString, ok := input.(string) 262 | if !ok { 263 | return false 264 | } 265 | 266 | if _, err := time.Parse("15:04:05Z07:00", asString); err == nil { 267 | return true 268 | } 269 | 270 | _, err := time.Parse("15:04:05", asString) 271 | return err == nil 272 | } 273 | 274 | // IsFormat checks if input is correctly formatted URI with a valid Scheme per RFC3986 275 | func (f URIFormatChecker) IsFormat(input interface{}) bool { 276 | asString, ok := input.(string) 277 | if !ok { 278 | return false 279 | } 280 | 281 | u, err := url.Parse(asString) 282 | 283 | if err != nil || u.Scheme == "" { 284 | return false 285 | } 286 | 287 | return !strings.Contains(asString, `\`) 288 | } 289 | 290 | // IsFormat checks if input is a correctly formatted URI or relative-reference per RFC3986 291 | func (f URIReferenceFormatChecker) IsFormat(input interface{}) bool { 292 | asString, ok := input.(string) 293 | if !ok { 294 | return false 295 | } 296 | 297 | _, err := url.Parse(asString) 298 | return err == nil && !strings.Contains(asString, `\`) 299 | } 300 | 301 | // IsFormat checks if input is a correctly formatted URI template per RFC6570 302 | func (f URITemplateFormatChecker) IsFormat(input interface{}) bool { 303 | asString, ok := input.(string) 304 | if !ok { 305 | return false 306 | } 307 | 308 | u, err := url.Parse(asString) 309 | if err != nil || strings.Contains(asString, `\`) { 310 | return false 311 | } 312 | 313 | return rxURITemplate.MatchString(u.Path) 314 | } 315 | 316 | // IsFormat checks if input is a correctly formatted hostname 317 | func (f HostnameFormatChecker) IsFormat(input interface{}) bool { 318 | asString, ok := input.(string) 319 | if !ok { 320 | return false 321 | } 322 | 323 | return rxHostname.MatchString(asString) && len(asString) < 256 324 | } 325 | 326 | // IsFormat checks if input is a correctly formatted UUID 327 | func (f UUIDFormatChecker) IsFormat(input interface{}) bool { 328 | asString, ok := input.(string) 329 | if !ok { 330 | return false 331 | } 332 | 333 | return rxUUID.MatchString(asString) 334 | } 335 | 336 | // IsFormat checks if input is a correctly formatted regular expression 337 | func (f RegexFormatChecker) IsFormat(input interface{}) bool { 338 | asString, ok := input.(string) 339 | if !ok { 340 | return false 341 | } 342 | 343 | if asString == "" { 344 | return true 345 | } 346 | _, err := regexp.Compile(asString) 347 | return err == nil 348 | } 349 | 350 | // IsFormat checks if input is a correctly formatted JSON Pointer per RFC6901 351 | func (f JSONPointerFormatChecker) IsFormat(input interface{}) bool { 352 | asString, ok := input.(string) 353 | if !ok { 354 | return false 355 | } 356 | 357 | return rxJSONPointer.MatchString(asString) 358 | } 359 | 360 | // IsFormat checks if input is a correctly formatted relative JSON Pointer 361 | func (f RelativeJSONPointerFormatChecker) IsFormat(input interface{}) bool { 362 | asString, ok := input.(string) 363 | if !ok { 364 | return false 365 | } 366 | 367 | return rxRelJSONPointer.MatchString(asString) 368 | } 369 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/glide.yaml: -------------------------------------------------------------------------------- 1 | package: github.com/xeipuuv/gojsonschema 2 | license: Apache 2.0 3 | import: 4 | - package: github.com/xeipuuv/gojsonschema 5 | 6 | - package: github.com/xeipuuv/gojsonpointer 7 | 8 | - package: github.com/xeipuuv/gojsonreference 9 | 10 | testImport: 11 | - package: github.com/stretchr/testify 12 | subpackages: 13 | - assert 14 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/xeipuuv/gojsonschema 2 | 3 | require ( 4 | github.com/stretchr/testify v1.3.0 5 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect 6 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 7 | ) 8 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 6 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 7 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 8 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= 9 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 10 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= 11 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= 12 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/internalLog.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Very simple log wrapper. 23 | // Used for debugging/testing purposes. 24 | // 25 | // created 01-01-2015 26 | 27 | package gojsonschema 28 | 29 | import ( 30 | "log" 31 | ) 32 | 33 | const internalLogEnabled = false 34 | 35 | func internalLog(format string, v ...interface{}) { 36 | log.Printf(format, v...) 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/jsonContext.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 MongoDB, Inc. 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 | 15 | // author tolsen 16 | // author-github https://github.com/tolsen 17 | // 18 | // repository-name gojsonschema 19 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 20 | // 21 | // description Implements a persistent (immutable w/ shared structure) singly-linked list of strings for the purpose of storing a json context 22 | // 23 | // created 04-09-2013 24 | 25 | package gojsonschema 26 | 27 | import "bytes" 28 | 29 | // JsonContext implements a persistent linked-list of strings 30 | type JsonContext struct { 31 | head string 32 | tail *JsonContext 33 | } 34 | 35 | // NewJsonContext creates a new JsonContext 36 | func NewJsonContext(head string, tail *JsonContext) *JsonContext { 37 | return &JsonContext{head, tail} 38 | } 39 | 40 | // String displays the context in reverse. 41 | // This plays well with the data structure's persistent nature with 42 | // Cons and a json document's tree structure. 43 | func (c *JsonContext) String(del ...string) string { 44 | byteArr := make([]byte, 0, c.stringLen()) 45 | buf := bytes.NewBuffer(byteArr) 46 | c.writeStringToBuffer(buf, del) 47 | 48 | return buf.String() 49 | } 50 | 51 | func (c *JsonContext) stringLen() int { 52 | length := 0 53 | if c.tail != nil { 54 | length = c.tail.stringLen() + 1 // add 1 for "." 55 | } 56 | 57 | length += len(c.head) 58 | return length 59 | } 60 | 61 | func (c *JsonContext) writeStringToBuffer(buf *bytes.Buffer, del []string) { 62 | if c.tail != nil { 63 | c.tail.writeStringToBuffer(buf, del) 64 | 65 | if len(del) > 0 { 66 | buf.WriteString(del[0]) 67 | } else { 68 | buf.WriteString(".") 69 | } 70 | } 71 | 72 | buf.WriteString(c.head) 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Different strategies to load JSON files. 23 | // Includes References (file and HTTP), JSON strings and Go types. 24 | // 25 | // created 01-02-2015 26 | 27 | package gojsonschema 28 | 29 | import ( 30 | "bytes" 31 | "encoding/json" 32 | "errors" 33 | "io" 34 | "io/ioutil" 35 | "net/http" 36 | "net/url" 37 | "os" 38 | "path/filepath" 39 | "runtime" 40 | "strings" 41 | 42 | "github.com/xeipuuv/gojsonreference" 43 | ) 44 | 45 | var osFS = osFileSystem(os.Open) 46 | 47 | // JSONLoader defines the JSON loader interface 48 | type JSONLoader interface { 49 | JsonSource() interface{} 50 | LoadJSON() (interface{}, error) 51 | JsonReference() (gojsonreference.JsonReference, error) 52 | LoaderFactory() JSONLoaderFactory 53 | } 54 | 55 | // JSONLoaderFactory defines the JSON loader factory interface 56 | type JSONLoaderFactory interface { 57 | // New creates a new JSON loader for the given source 58 | New(source string) JSONLoader 59 | } 60 | 61 | // DefaultJSONLoaderFactory is the default JSON loader factory 62 | type DefaultJSONLoaderFactory struct { 63 | } 64 | 65 | // FileSystemJSONLoaderFactory is a JSON loader factory that uses http.FileSystem 66 | type FileSystemJSONLoaderFactory struct { 67 | fs http.FileSystem 68 | } 69 | 70 | // New creates a new JSON loader for the given source 71 | func (d DefaultJSONLoaderFactory) New(source string) JSONLoader { 72 | return &jsonReferenceLoader{ 73 | fs: osFS, 74 | source: source, 75 | } 76 | } 77 | 78 | // New creates a new JSON loader for the given source 79 | func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader { 80 | return &jsonReferenceLoader{ 81 | fs: f.fs, 82 | source: source, 83 | } 84 | } 85 | 86 | // osFileSystem is a functional wrapper for os.Open that implements http.FileSystem. 87 | type osFileSystem func(string) (*os.File, error) 88 | 89 | // Opens a file with the given name 90 | func (o osFileSystem) Open(name string) (http.File, error) { 91 | return o(name) 92 | } 93 | 94 | // JSON Reference loader 95 | // references are used to load JSONs from files and HTTP 96 | 97 | type jsonReferenceLoader struct { 98 | fs http.FileSystem 99 | source string 100 | } 101 | 102 | func (l *jsonReferenceLoader) JsonSource() interface{} { 103 | return l.source 104 | } 105 | 106 | func (l *jsonReferenceLoader) JsonReference() (gojsonreference.JsonReference, error) { 107 | return gojsonreference.NewJsonReference(l.JsonSource().(string)) 108 | } 109 | 110 | func (l *jsonReferenceLoader) LoaderFactory() JSONLoaderFactory { 111 | return &FileSystemJSONLoaderFactory{ 112 | fs: l.fs, 113 | } 114 | } 115 | 116 | // NewReferenceLoader returns a JSON reference loader using the given source and the local OS file system. 117 | func NewReferenceLoader(source string) JSONLoader { 118 | return &jsonReferenceLoader{ 119 | fs: osFS, 120 | source: source, 121 | } 122 | } 123 | 124 | // NewReferenceLoaderFileSystem returns a JSON reference loader using the given source and file system. 125 | func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) JSONLoader { 126 | return &jsonReferenceLoader{ 127 | fs: fs, 128 | source: source, 129 | } 130 | } 131 | 132 | func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) { 133 | 134 | var err error 135 | 136 | reference, err := gojsonreference.NewJsonReference(l.JsonSource().(string)) 137 | if err != nil { 138 | return nil, err 139 | } 140 | 141 | refToURL := reference 142 | refToURL.GetUrl().Fragment = "" 143 | 144 | var document interface{} 145 | 146 | if reference.HasFileScheme { 147 | 148 | filename := strings.TrimPrefix(refToURL.String(), "file://") 149 | filename, err = url.QueryUnescape(filename) 150 | 151 | if err != nil { 152 | return nil, err 153 | } 154 | 155 | if runtime.GOOS == "windows" { 156 | // on Windows, a file URL may have an extra leading slash, use slashes 157 | // instead of backslashes, and have spaces escaped 158 | filename = strings.TrimPrefix(filename, "/") 159 | filename = filepath.FromSlash(filename) 160 | } 161 | 162 | document, err = l.loadFromFile(filename) 163 | if err != nil { 164 | return nil, err 165 | } 166 | 167 | } else { 168 | 169 | document, err = l.loadFromHTTP(refToURL.String()) 170 | if err != nil { 171 | return nil, err 172 | } 173 | 174 | } 175 | 176 | return document, nil 177 | 178 | } 179 | 180 | func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) { 181 | 182 | // returned cached versions for metaschemas for drafts 4, 6 and 7 183 | // for performance and allow for easier offline use 184 | if metaSchema := drafts.GetMetaSchema(address); metaSchema != "" { 185 | return decodeJSONUsingNumber(strings.NewReader(metaSchema)) 186 | } 187 | 188 | resp, err := http.Get(address) 189 | if err != nil { 190 | return nil, err 191 | } 192 | 193 | // must return HTTP Status 200 OK 194 | if resp.StatusCode != http.StatusOK { 195 | return nil, errors.New(formatErrorDescription(Locale.HttpBadStatus(), ErrorDetails{"status": resp.Status})) 196 | } 197 | 198 | bodyBuff, err := ioutil.ReadAll(resp.Body) 199 | if err != nil { 200 | return nil, err 201 | } 202 | 203 | return decodeJSONUsingNumber(bytes.NewReader(bodyBuff)) 204 | } 205 | 206 | func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) { 207 | f, err := l.fs.Open(path) 208 | if err != nil { 209 | return nil, err 210 | } 211 | defer f.Close() 212 | 213 | bodyBuff, err := ioutil.ReadAll(f) 214 | if err != nil { 215 | return nil, err 216 | } 217 | 218 | return decodeJSONUsingNumber(bytes.NewReader(bodyBuff)) 219 | 220 | } 221 | 222 | // JSON string loader 223 | 224 | type jsonStringLoader struct { 225 | source string 226 | } 227 | 228 | func (l *jsonStringLoader) JsonSource() interface{} { 229 | return l.source 230 | } 231 | 232 | func (l *jsonStringLoader) JsonReference() (gojsonreference.JsonReference, error) { 233 | return gojsonreference.NewJsonReference("#") 234 | } 235 | 236 | func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory { 237 | return &DefaultJSONLoaderFactory{} 238 | } 239 | 240 | // NewStringLoader creates a new JSONLoader, taking a string as source 241 | func NewStringLoader(source string) JSONLoader { 242 | return &jsonStringLoader{source: source} 243 | } 244 | 245 | func (l *jsonStringLoader) LoadJSON() (interface{}, error) { 246 | 247 | return decodeJSONUsingNumber(strings.NewReader(l.JsonSource().(string))) 248 | 249 | } 250 | 251 | // JSON bytes loader 252 | 253 | type jsonBytesLoader struct { 254 | source []byte 255 | } 256 | 257 | func (l *jsonBytesLoader) JsonSource() interface{} { 258 | return l.source 259 | } 260 | 261 | func (l *jsonBytesLoader) JsonReference() (gojsonreference.JsonReference, error) { 262 | return gojsonreference.NewJsonReference("#") 263 | } 264 | 265 | func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory { 266 | return &DefaultJSONLoaderFactory{} 267 | } 268 | 269 | // NewBytesLoader creates a new JSONLoader, taking a `[]byte` as source 270 | func NewBytesLoader(source []byte) JSONLoader { 271 | return &jsonBytesLoader{source: source} 272 | } 273 | 274 | func (l *jsonBytesLoader) LoadJSON() (interface{}, error) { 275 | return decodeJSONUsingNumber(bytes.NewReader(l.JsonSource().([]byte))) 276 | } 277 | 278 | // JSON Go (types) loader 279 | // used to load JSONs from the code as maps, interface{}, structs ... 280 | 281 | type jsonGoLoader struct { 282 | source interface{} 283 | } 284 | 285 | func (l *jsonGoLoader) JsonSource() interface{} { 286 | return l.source 287 | } 288 | 289 | func (l *jsonGoLoader) JsonReference() (gojsonreference.JsonReference, error) { 290 | return gojsonreference.NewJsonReference("#") 291 | } 292 | 293 | func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory { 294 | return &DefaultJSONLoaderFactory{} 295 | } 296 | 297 | // NewGoLoader creates a new JSONLoader from a given Go struct 298 | func NewGoLoader(source interface{}) JSONLoader { 299 | return &jsonGoLoader{source: source} 300 | } 301 | 302 | func (l *jsonGoLoader) LoadJSON() (interface{}, error) { 303 | 304 | // convert it to a compliant JSON first to avoid types "mismatches" 305 | 306 | jsonBytes, err := json.Marshal(l.JsonSource()) 307 | if err != nil { 308 | return nil, err 309 | } 310 | 311 | return decodeJSONUsingNumber(bytes.NewReader(jsonBytes)) 312 | 313 | } 314 | 315 | type jsonIOLoader struct { 316 | buf *bytes.Buffer 317 | } 318 | 319 | // NewReaderLoader creates a new JSON loader using the provided io.Reader 320 | func NewReaderLoader(source io.Reader) (JSONLoader, io.Reader) { 321 | buf := &bytes.Buffer{} 322 | return &jsonIOLoader{buf: buf}, io.TeeReader(source, buf) 323 | } 324 | 325 | // NewWriterLoader creates a new JSON loader using the provided io.Writer 326 | func NewWriterLoader(source io.Writer) (JSONLoader, io.Writer) { 327 | buf := &bytes.Buffer{} 328 | return &jsonIOLoader{buf: buf}, io.MultiWriter(source, buf) 329 | } 330 | 331 | func (l *jsonIOLoader) JsonSource() interface{} { 332 | return l.buf.String() 333 | } 334 | 335 | func (l *jsonIOLoader) LoadJSON() (interface{}, error) { 336 | return decodeJSONUsingNumber(l.buf) 337 | } 338 | 339 | func (l *jsonIOLoader) JsonReference() (gojsonreference.JsonReference, error) { 340 | return gojsonreference.NewJsonReference("#") 341 | } 342 | 343 | func (l *jsonIOLoader) LoaderFactory() JSONLoaderFactory { 344 | return &DefaultJSONLoaderFactory{} 345 | } 346 | 347 | // JSON raw loader 348 | // In case the JSON is already marshalled to interface{} use this loader 349 | // This is used for testing as otherwise there is no guarantee the JSON is marshalled 350 | // "properly" by using https://golang.org/pkg/encoding/json/#Decoder.UseNumber 351 | type jsonRawLoader struct { 352 | source interface{} 353 | } 354 | 355 | // NewRawLoader creates a new JSON raw loader for the given source 356 | func NewRawLoader(source interface{}) JSONLoader { 357 | return &jsonRawLoader{source: source} 358 | } 359 | func (l *jsonRawLoader) JsonSource() interface{} { 360 | return l.source 361 | } 362 | func (l *jsonRawLoader) LoadJSON() (interface{}, error) { 363 | return l.source, nil 364 | } 365 | func (l *jsonRawLoader) JsonReference() (gojsonreference.JsonReference, error) { 366 | return gojsonreference.NewJsonReference("#") 367 | } 368 | func (l *jsonRawLoader) LoaderFactory() JSONLoaderFactory { 369 | return &DefaultJSONLoaderFactory{} 370 | } 371 | 372 | func decodeJSONUsingNumber(r io.Reader) (interface{}, error) { 373 | 374 | var document interface{} 375 | 376 | decoder := json.NewDecoder(r) 377 | decoder.UseNumber() 378 | 379 | err := decoder.Decode(&document) 380 | if err != nil { 381 | return nil, err 382 | } 383 | 384 | return document, nil 385 | 386 | } 387 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/result.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Result and ResultError implementations. 23 | // 24 | // created 01-01-2015 25 | 26 | package gojsonschema 27 | 28 | import ( 29 | "fmt" 30 | "strings" 31 | ) 32 | 33 | type ( 34 | // ErrorDetails is a map of details specific to each error. 35 | // While the values will vary, every error will contain a "field" value 36 | ErrorDetails map[string]interface{} 37 | 38 | // ResultError is the interface that library errors must implement 39 | ResultError interface { 40 | // Field returns the field name without the root context 41 | // i.e. firstName or person.firstName instead of (root).firstName or (root).person.firstName 42 | Field() string 43 | // SetType sets the error-type 44 | SetType(string) 45 | // Type returns the error-type 46 | Type() string 47 | // SetContext sets the JSON-context for the error 48 | SetContext(*JsonContext) 49 | // Context returns the JSON-context of the error 50 | Context() *JsonContext 51 | // SetDescription sets a description for the error 52 | SetDescription(string) 53 | // Description returns the description of the error 54 | Description() string 55 | // SetDescriptionFormat sets the format for the description in the default text/template format 56 | SetDescriptionFormat(string) 57 | // DescriptionFormat returns the format for the description in the default text/template format 58 | DescriptionFormat() string 59 | // SetValue sets the value related to the error 60 | SetValue(interface{}) 61 | // Value returns the value related to the error 62 | Value() interface{} 63 | // SetDetails sets the details specific to the error 64 | SetDetails(ErrorDetails) 65 | // Details returns details about the error 66 | Details() ErrorDetails 67 | // String returns a string representation of the error 68 | String() string 69 | } 70 | 71 | // ResultErrorFields holds the fields for each ResultError implementation. 72 | // ResultErrorFields implements the ResultError interface, so custom errors 73 | // can be defined by just embedding this type 74 | ResultErrorFields struct { 75 | errorType string // A string with the type of error (i.e. invalid_type) 76 | context *JsonContext // Tree like notation of the part that failed the validation. ex (root).a.b ... 77 | description string // A human readable error message 78 | descriptionFormat string // A format for human readable error message 79 | value interface{} // Value given by the JSON file that is the source of the error 80 | details ErrorDetails 81 | } 82 | 83 | // Result holds the result of a validation 84 | Result struct { 85 | errors []ResultError 86 | // Scores how well the validation matched. Useful in generating 87 | // better error messages for anyOf and oneOf. 88 | score int 89 | } 90 | ) 91 | 92 | // Field returns the field name without the root context 93 | // i.e. firstName or person.firstName instead of (root).firstName or (root).person.firstName 94 | func (v *ResultErrorFields) Field() string { 95 | return strings.TrimPrefix(v.context.String(), STRING_ROOT_SCHEMA_PROPERTY+".") 96 | } 97 | 98 | // SetType sets the error-type 99 | func (v *ResultErrorFields) SetType(errorType string) { 100 | v.errorType = errorType 101 | } 102 | 103 | // Type returns the error-type 104 | func (v *ResultErrorFields) Type() string { 105 | return v.errorType 106 | } 107 | 108 | // SetContext sets the JSON-context for the error 109 | func (v *ResultErrorFields) SetContext(context *JsonContext) { 110 | v.context = context 111 | } 112 | 113 | // Context returns the JSON-context of the error 114 | func (v *ResultErrorFields) Context() *JsonContext { 115 | return v.context 116 | } 117 | 118 | // SetDescription sets a description for the error 119 | func (v *ResultErrorFields) SetDescription(description string) { 120 | v.description = description 121 | } 122 | 123 | // Description returns the description of the error 124 | func (v *ResultErrorFields) Description() string { 125 | return v.description 126 | } 127 | 128 | // SetDescriptionFormat sets the format for the description in the default text/template format 129 | func (v *ResultErrorFields) SetDescriptionFormat(descriptionFormat string) { 130 | v.descriptionFormat = descriptionFormat 131 | } 132 | 133 | // DescriptionFormat returns the format for the description in the default text/template format 134 | func (v *ResultErrorFields) DescriptionFormat() string { 135 | return v.descriptionFormat 136 | } 137 | 138 | // SetValue sets the value related to the error 139 | func (v *ResultErrorFields) SetValue(value interface{}) { 140 | v.value = value 141 | } 142 | 143 | // Value returns the value related to the error 144 | func (v *ResultErrorFields) Value() interface{} { 145 | return v.value 146 | } 147 | 148 | // SetDetails sets the details specific to the error 149 | func (v *ResultErrorFields) SetDetails(details ErrorDetails) { 150 | v.details = details 151 | } 152 | 153 | // Details returns details about the error 154 | func (v *ResultErrorFields) Details() ErrorDetails { 155 | return v.details 156 | } 157 | 158 | // String returns a string representation of the error 159 | func (v ResultErrorFields) String() string { 160 | // as a fallback, the value is displayed go style 161 | valueString := fmt.Sprintf("%v", v.value) 162 | 163 | // marshal the go value value to json 164 | if v.value == nil { 165 | valueString = TYPE_NULL 166 | } else { 167 | if vs, err := marshalToJSONString(v.value); err == nil { 168 | if vs == nil { 169 | valueString = TYPE_NULL 170 | } else { 171 | valueString = *vs 172 | } 173 | } 174 | } 175 | 176 | return formatErrorDescription(Locale.ErrorFormat(), ErrorDetails{ 177 | "context": v.context.String(), 178 | "description": v.description, 179 | "value": valueString, 180 | "field": v.Field(), 181 | }) 182 | } 183 | 184 | // Valid indicates if no errors were found 185 | func (v *Result) Valid() bool { 186 | return len(v.errors) == 0 187 | } 188 | 189 | // Errors returns the errors that were found 190 | func (v *Result) Errors() []ResultError { 191 | return v.errors 192 | } 193 | 194 | // AddError appends a fully filled error to the error set 195 | // SetDescription() will be called with the result of the parsed err.DescriptionFormat() 196 | func (v *Result) AddError(err ResultError, details ErrorDetails) { 197 | if _, exists := details["context"]; !exists && err.Context() != nil { 198 | details["context"] = err.Context().String() 199 | } 200 | 201 | err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details)) 202 | 203 | v.errors = append(v.errors, err) 204 | } 205 | 206 | func (v *Result) addInternalError(err ResultError, context *JsonContext, value interface{}, details ErrorDetails) { 207 | newError(err, context, value, Locale, details) 208 | v.errors = append(v.errors, err) 209 | v.score -= 2 // results in a net -1 when added to the +1 we get at the end of the validation function 210 | } 211 | 212 | // Used to copy errors from a sub-schema to the main one 213 | func (v *Result) mergeErrors(otherResult *Result) { 214 | v.errors = append(v.errors, otherResult.Errors()...) 215 | v.score += otherResult.score 216 | } 217 | 218 | func (v *Result) incrementScore() { 219 | v.score++ 220 | } 221 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 johandorland ( https://github.com/johandorland ) 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 | 15 | package gojsonschema 16 | 17 | import ( 18 | "bytes" 19 | "errors" 20 | 21 | "github.com/xeipuuv/gojsonreference" 22 | ) 23 | 24 | // SchemaLoader is used to load schemas 25 | type SchemaLoader struct { 26 | pool *schemaPool 27 | AutoDetect bool 28 | Validate bool 29 | Draft Draft 30 | } 31 | 32 | // NewSchemaLoader creates a new NewSchemaLoader 33 | func NewSchemaLoader() *SchemaLoader { 34 | 35 | ps := &SchemaLoader{ 36 | pool: &schemaPool{ 37 | schemaPoolDocuments: make(map[string]*schemaPoolDocument), 38 | }, 39 | AutoDetect: true, 40 | Validate: false, 41 | Draft: Hybrid, 42 | } 43 | ps.pool.autoDetect = &ps.AutoDetect 44 | 45 | return ps 46 | } 47 | 48 | func (sl *SchemaLoader) validateMetaschema(documentNode interface{}) error { 49 | 50 | var ( 51 | schema string 52 | err error 53 | ) 54 | if sl.AutoDetect { 55 | schema, _, err = parseSchemaURL(documentNode) 56 | if err != nil { 57 | return err 58 | } 59 | } 60 | 61 | // If no explicit "$schema" is used, use the default metaschema associated with the draft used 62 | if schema == "" { 63 | if sl.Draft == Hybrid { 64 | return nil 65 | } 66 | schema = drafts.GetSchemaURL(sl.Draft) 67 | } 68 | 69 | //Disable validation when loading the metaschema to prevent an infinite recursive loop 70 | sl.Validate = false 71 | 72 | metaSchema, err := sl.Compile(NewReferenceLoader(schema)) 73 | 74 | if err != nil { 75 | return err 76 | } 77 | 78 | sl.Validate = true 79 | 80 | result := metaSchema.validateDocument(documentNode) 81 | 82 | if !result.Valid() { 83 | var res bytes.Buffer 84 | for _, err := range result.Errors() { 85 | res.WriteString(err.String()) 86 | res.WriteString("\n") 87 | } 88 | return errors.New(res.String()) 89 | } 90 | 91 | return nil 92 | } 93 | 94 | // AddSchemas adds an arbritrary amount of schemas to the schema cache. As this function does not require 95 | // an explicit URL, every schema should contain an $id, so that it can be referenced by the main schema 96 | func (sl *SchemaLoader) AddSchemas(loaders ...JSONLoader) error { 97 | emptyRef, _ := gojsonreference.NewJsonReference("") 98 | 99 | for _, loader := range loaders { 100 | doc, err := loader.LoadJSON() 101 | 102 | if err != nil { 103 | return err 104 | } 105 | 106 | if sl.Validate { 107 | if err := sl.validateMetaschema(doc); err != nil { 108 | return err 109 | } 110 | } 111 | 112 | // Directly use the Recursive function, so that it get only added to the schema pool by $id 113 | // and not by the ref of the document as it's empty 114 | if err = sl.pool.parseReferences(doc, emptyRef, false); err != nil { 115 | return err 116 | } 117 | } 118 | 119 | return nil 120 | } 121 | 122 | //AddSchema adds a schema under the provided URL to the schema cache 123 | func (sl *SchemaLoader) AddSchema(url string, loader JSONLoader) error { 124 | 125 | ref, err := gojsonreference.NewJsonReference(url) 126 | 127 | if err != nil { 128 | return err 129 | } 130 | 131 | doc, err := loader.LoadJSON() 132 | 133 | if err != nil { 134 | return err 135 | } 136 | 137 | if sl.Validate { 138 | if err := sl.validateMetaschema(doc); err != nil { 139 | return err 140 | } 141 | } 142 | 143 | return sl.pool.parseReferences(doc, ref, true) 144 | } 145 | 146 | // Compile loads and compiles a schema 147 | func (sl *SchemaLoader) Compile(rootSchema JSONLoader) (*Schema, error) { 148 | 149 | ref, err := rootSchema.JsonReference() 150 | 151 | if err != nil { 152 | return nil, err 153 | } 154 | 155 | d := Schema{} 156 | d.pool = sl.pool 157 | d.pool.jsonLoaderFactory = rootSchema.LoaderFactory() 158 | d.documentReference = ref 159 | d.referencePool = newSchemaReferencePool() 160 | 161 | var doc interface{} 162 | if ref.String() != "" { 163 | // Get document from schema pool 164 | spd, err := d.pool.GetDocument(d.documentReference) 165 | if err != nil { 166 | return nil, err 167 | } 168 | doc = spd.Document 169 | } else { 170 | // Load JSON directly 171 | doc, err = rootSchema.LoadJSON() 172 | if err != nil { 173 | return nil, err 174 | } 175 | // References need only be parsed if loading JSON directly 176 | // as pool.GetDocument already does this for us if loading by reference 177 | err = sl.pool.parseReferences(doc, ref, true) 178 | if err != nil { 179 | return nil, err 180 | } 181 | } 182 | 183 | if sl.Validate { 184 | if err := sl.validateMetaschema(doc); err != nil { 185 | return nil, err 186 | } 187 | } 188 | 189 | draft := sl.Draft 190 | if sl.AutoDetect { 191 | _, detectedDraft, err := parseSchemaURL(doc) 192 | if err != nil { 193 | return nil, err 194 | } 195 | if detectedDraft != nil { 196 | draft = *detectedDraft 197 | } 198 | } 199 | 200 | err = d.parse(doc, draft) 201 | if err != nil { 202 | return nil, err 203 | } 204 | 205 | return &d, nil 206 | } 207 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/schemaPool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Defines resources pooling. 23 | // Eases referencing and avoids downloading the same resource twice. 24 | // 25 | // created 26-02-2013 26 | 27 | package gojsonschema 28 | 29 | import ( 30 | "errors" 31 | "fmt" 32 | "reflect" 33 | 34 | "github.com/xeipuuv/gojsonreference" 35 | ) 36 | 37 | type schemaPoolDocument struct { 38 | Document interface{} 39 | Draft *Draft 40 | } 41 | 42 | type schemaPool struct { 43 | schemaPoolDocuments map[string]*schemaPoolDocument 44 | jsonLoaderFactory JSONLoaderFactory 45 | autoDetect *bool 46 | } 47 | 48 | func (p *schemaPool) parseReferences(document interface{}, ref gojsonreference.JsonReference, pooled bool) error { 49 | 50 | var ( 51 | draft *Draft 52 | err error 53 | reference = ref.String() 54 | ) 55 | // Only the root document should be added to the schema pool if pooled is true 56 | if _, ok := p.schemaPoolDocuments[reference]; pooled && ok { 57 | return fmt.Errorf("Reference already exists: \"%s\"", reference) 58 | } 59 | 60 | if *p.autoDetect { 61 | _, draft, err = parseSchemaURL(document) 62 | if err != nil { 63 | return err 64 | } 65 | } 66 | 67 | err = p.parseReferencesRecursive(document, ref, draft) 68 | 69 | if pooled { 70 | p.schemaPoolDocuments[reference] = &schemaPoolDocument{Document: document, Draft: draft} 71 | } 72 | 73 | return err 74 | } 75 | 76 | func (p *schemaPool) parseReferencesRecursive(document interface{}, ref gojsonreference.JsonReference, draft *Draft) error { 77 | // parseReferencesRecursive parses a JSON document and resolves all $id and $ref references. 78 | // For $ref references it takes into account the $id scope it is in and replaces 79 | // the reference by the absolute resolved reference 80 | 81 | // When encountering errors it fails silently. Error handling is done when the schema 82 | // is syntactically parsed and any error encountered here should also come up there. 83 | switch m := document.(type) { 84 | case []interface{}: 85 | for _, v := range m { 86 | p.parseReferencesRecursive(v, ref, draft) 87 | } 88 | case map[string]interface{}: 89 | localRef := &ref 90 | 91 | keyID := KEY_ID_NEW 92 | if existsMapKey(m, KEY_ID) { 93 | keyID = KEY_ID 94 | } 95 | if existsMapKey(m, keyID) && isKind(m[keyID], reflect.String) { 96 | jsonReference, err := gojsonreference.NewJsonReference(m[keyID].(string)) 97 | if err == nil { 98 | localRef, err = ref.Inherits(jsonReference) 99 | if err == nil { 100 | if _, ok := p.schemaPoolDocuments[localRef.String()]; ok { 101 | return fmt.Errorf("Reference already exists: \"%s\"", localRef.String()) 102 | } 103 | p.schemaPoolDocuments[localRef.String()] = &schemaPoolDocument{Document: document, Draft: draft} 104 | } 105 | } 106 | } 107 | 108 | if existsMapKey(m, KEY_REF) && isKind(m[KEY_REF], reflect.String) { 109 | jsonReference, err := gojsonreference.NewJsonReference(m[KEY_REF].(string)) 110 | if err == nil { 111 | absoluteRef, err := localRef.Inherits(jsonReference) 112 | if err == nil { 113 | m[KEY_REF] = absoluteRef.String() 114 | } 115 | } 116 | } 117 | 118 | for k, v := range m { 119 | // const and enums should be interpreted literally, so ignore them 120 | if k == KEY_CONST || k == KEY_ENUM { 121 | continue 122 | } 123 | // Something like a property or a dependency is not a valid schema, as it might describe properties named "$ref", "$id" or "const", etc 124 | // Therefore don't treat it like a schema. 125 | if k == KEY_PROPERTIES || k == KEY_DEPENDENCIES || k == KEY_PATTERN_PROPERTIES { 126 | if child, ok := v.(map[string]interface{}); ok { 127 | for _, v := range child { 128 | p.parseReferencesRecursive(v, *localRef, draft) 129 | } 130 | } 131 | } else { 132 | p.parseReferencesRecursive(v, *localRef, draft) 133 | } 134 | } 135 | } 136 | return nil 137 | } 138 | 139 | func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*schemaPoolDocument, error) { 140 | 141 | var ( 142 | spd *schemaPoolDocument 143 | draft *Draft 144 | ok bool 145 | err error 146 | ) 147 | 148 | if internalLogEnabled { 149 | internalLog("Get Document ( %s )", reference.String()) 150 | } 151 | 152 | // Create a deep copy, so we can remove the fragment part later on without altering the original 153 | refToURL, _ := gojsonreference.NewJsonReference(reference.String()) 154 | 155 | // First check if the given fragment is a location independent identifier 156 | // http://json-schema.org/latest/json-schema-core.html#rfc.section.8.2.3 157 | 158 | if spd, ok = p.schemaPoolDocuments[refToURL.String()]; ok { 159 | if internalLogEnabled { 160 | internalLog(" From pool") 161 | } 162 | return spd, nil 163 | } 164 | 165 | // If the given reference is not a location independent identifier, 166 | // strip the fragment and look for a document with it's base URI 167 | 168 | refToURL.GetUrl().Fragment = "" 169 | 170 | if cachedSpd, ok := p.schemaPoolDocuments[refToURL.String()]; ok { 171 | document, _, err := reference.GetPointer().Get(cachedSpd.Document) 172 | 173 | if err != nil { 174 | return nil, err 175 | } 176 | 177 | if internalLogEnabled { 178 | internalLog(" From pool") 179 | } 180 | 181 | spd = &schemaPoolDocument{Document: document, Draft: cachedSpd.Draft} 182 | p.schemaPoolDocuments[reference.String()] = spd 183 | 184 | return spd, nil 185 | } 186 | 187 | // It is not possible to load anything remotely that is not canonical... 188 | if !reference.IsCanonical() { 189 | return nil, errors.New(formatErrorDescription( 190 | Locale.ReferenceMustBeCanonical(), 191 | ErrorDetails{"reference": reference.String()}, 192 | )) 193 | } 194 | 195 | jsonReferenceLoader := p.jsonLoaderFactory.New(reference.String()) 196 | document, err := jsonReferenceLoader.LoadJSON() 197 | 198 | if err != nil { 199 | return nil, err 200 | } 201 | 202 | // add the whole document to the pool for potential re-use 203 | p.parseReferences(document, refToURL, true) 204 | 205 | _, draft, _ = parseSchemaURL(document) 206 | 207 | // resolve the potential fragment and also cache it 208 | document, _, err = reference.GetPointer().Get(document) 209 | 210 | if err != nil { 211 | return nil, err 212 | } 213 | 214 | return &schemaPoolDocument{Document: document, Draft: draft}, nil 215 | } 216 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/schemaReferencePool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Pool of referenced schemas. 23 | // 24 | // created 25-06-2013 25 | 26 | package gojsonschema 27 | 28 | import ( 29 | "fmt" 30 | ) 31 | 32 | type schemaReferencePool struct { 33 | documents map[string]*subSchema 34 | } 35 | 36 | func newSchemaReferencePool() *schemaReferencePool { 37 | 38 | p := &schemaReferencePool{} 39 | p.documents = make(map[string]*subSchema) 40 | 41 | return p 42 | } 43 | 44 | func (p *schemaReferencePool) Get(ref string) (r *subSchema, o bool) { 45 | 46 | if internalLogEnabled { 47 | internalLog(fmt.Sprintf("Schema Reference ( %s )", ref)) 48 | } 49 | 50 | if sch, ok := p.documents[ref]; ok { 51 | if internalLogEnabled { 52 | internalLog(fmt.Sprintf(" From pool")) 53 | } 54 | return sch, true 55 | } 56 | 57 | return nil, false 58 | } 59 | 60 | func (p *schemaReferencePool) Add(ref string, sch *subSchema) { 61 | 62 | if internalLogEnabled { 63 | internalLog(fmt.Sprintf("Add Schema Reference %s to pool", ref)) 64 | } 65 | if _, ok := p.documents[ref]; !ok { 66 | p.documents[ref] = sch 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/schemaType.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Helper structure to handle schema types, and the combination of them. 23 | // 24 | // created 28-02-2013 25 | 26 | package gojsonschema 27 | 28 | import ( 29 | "errors" 30 | "fmt" 31 | "strings" 32 | ) 33 | 34 | type jsonSchemaType struct { 35 | types []string 36 | } 37 | 38 | // Is the schema typed ? that is containing at least one type 39 | // When not typed, the schema does not need any type validation 40 | func (t *jsonSchemaType) IsTyped() bool { 41 | return len(t.types) > 0 42 | } 43 | 44 | func (t *jsonSchemaType) Add(etype string) error { 45 | 46 | if !isStringInSlice(JSON_TYPES, etype) { 47 | return errors.New(formatErrorDescription(Locale.NotAValidType(), ErrorDetails{"given": "/" + etype + "/", "expected": JSON_TYPES})) 48 | } 49 | 50 | if t.Contains(etype) { 51 | return errors.New(formatErrorDescription(Locale.Duplicated(), ErrorDetails{"type": etype})) 52 | } 53 | 54 | t.types = append(t.types, etype) 55 | 56 | return nil 57 | } 58 | 59 | func (t *jsonSchemaType) Contains(etype string) bool { 60 | 61 | for _, v := range t.types { 62 | if v == etype { 63 | return true 64 | } 65 | } 66 | 67 | return false 68 | } 69 | 70 | func (t *jsonSchemaType) String() string { 71 | 72 | if len(t.types) == 0 { 73 | return STRING_UNDEFINED // should never happen 74 | } 75 | 76 | // Displayed as a list [type1,type2,...] 77 | if len(t.types) > 1 { 78 | return fmt.Sprintf("[%s]", strings.Join(t.types, ",")) 79 | } 80 | 81 | // Only one type: name only 82 | return t.types[0] 83 | } 84 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/subSchema.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Defines the structure of a sub-subSchema. 23 | // A sub-subSchema can contain other sub-schemas. 24 | // 25 | // created 27-02-2013 26 | 27 | package gojsonschema 28 | 29 | import ( 30 | "github.com/xeipuuv/gojsonreference" 31 | "math/big" 32 | "regexp" 33 | ) 34 | 35 | // Constants 36 | const ( 37 | KEY_SCHEMA = "$schema" 38 | KEY_ID = "id" 39 | KEY_ID_NEW = "$id" 40 | KEY_REF = "$ref" 41 | KEY_TITLE = "title" 42 | KEY_DESCRIPTION = "description" 43 | KEY_TYPE = "type" 44 | KEY_ITEMS = "items" 45 | KEY_ADDITIONAL_ITEMS = "additionalItems" 46 | KEY_PROPERTIES = "properties" 47 | KEY_PATTERN_PROPERTIES = "patternProperties" 48 | KEY_ADDITIONAL_PROPERTIES = "additionalProperties" 49 | KEY_PROPERTY_NAMES = "propertyNames" 50 | KEY_DEFINITIONS = "definitions" 51 | KEY_MULTIPLE_OF = "multipleOf" 52 | KEY_MINIMUM = "minimum" 53 | KEY_MAXIMUM = "maximum" 54 | KEY_EXCLUSIVE_MINIMUM = "exclusiveMinimum" 55 | KEY_EXCLUSIVE_MAXIMUM = "exclusiveMaximum" 56 | KEY_MIN_LENGTH = "minLength" 57 | KEY_MAX_LENGTH = "maxLength" 58 | KEY_PATTERN = "pattern" 59 | KEY_FORMAT = "format" 60 | KEY_MIN_PROPERTIES = "minProperties" 61 | KEY_MAX_PROPERTIES = "maxProperties" 62 | KEY_DEPENDENCIES = "dependencies" 63 | KEY_REQUIRED = "required" 64 | KEY_MIN_ITEMS = "minItems" 65 | KEY_MAX_ITEMS = "maxItems" 66 | KEY_UNIQUE_ITEMS = "uniqueItems" 67 | KEY_CONTAINS = "contains" 68 | KEY_CONST = "const" 69 | KEY_ENUM = "enum" 70 | KEY_ONE_OF = "oneOf" 71 | KEY_ANY_OF = "anyOf" 72 | KEY_ALL_OF = "allOf" 73 | KEY_NOT = "not" 74 | KEY_IF = "if" 75 | KEY_THEN = "then" 76 | KEY_ELSE = "else" 77 | ) 78 | 79 | type subSchema struct { 80 | draft *Draft 81 | 82 | // basic subSchema meta properties 83 | id *gojsonreference.JsonReference 84 | title *string 85 | description *string 86 | 87 | property string 88 | 89 | // Quick pass/fail for boolean schemas 90 | pass *bool 91 | 92 | // Types associated with the subSchema 93 | types jsonSchemaType 94 | 95 | // Reference url 96 | ref *gojsonreference.JsonReference 97 | // Schema referenced 98 | refSchema *subSchema 99 | 100 | // hierarchy 101 | parent *subSchema 102 | itemsChildren []*subSchema 103 | itemsChildrenIsSingleSchema bool 104 | propertiesChildren []*subSchema 105 | 106 | // validation : number / integer 107 | multipleOf *big.Rat 108 | maximum *big.Rat 109 | exclusiveMaximum *big.Rat 110 | minimum *big.Rat 111 | exclusiveMinimum *big.Rat 112 | 113 | // validation : string 114 | minLength *int 115 | maxLength *int 116 | pattern *regexp.Regexp 117 | format string 118 | 119 | // validation : object 120 | minProperties *int 121 | maxProperties *int 122 | required []string 123 | 124 | dependencies map[string]interface{} 125 | additionalProperties interface{} 126 | patternProperties map[string]*subSchema 127 | propertyNames *subSchema 128 | 129 | // validation : array 130 | minItems *int 131 | maxItems *int 132 | uniqueItems bool 133 | contains *subSchema 134 | 135 | additionalItems interface{} 136 | 137 | // validation : all 138 | _const *string //const is a golang keyword 139 | enum []string 140 | 141 | // validation : subSchema 142 | oneOf []*subSchema 143 | anyOf []*subSchema 144 | allOf []*subSchema 145 | not *subSchema 146 | _if *subSchema // if/else are golang keywords 147 | _then *subSchema 148 | _else *subSchema 149 | } 150 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/types.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Contains const types for schema and JSON. 23 | // 24 | // created 28-02-2013 25 | 26 | package gojsonschema 27 | 28 | // Type constants 29 | const ( 30 | TYPE_ARRAY = `array` 31 | TYPE_BOOLEAN = `boolean` 32 | TYPE_INTEGER = `integer` 33 | TYPE_NUMBER = `number` 34 | TYPE_NULL = `null` 35 | TYPE_OBJECT = `object` 36 | TYPE_STRING = `string` 37 | ) 38 | 39 | // JSON_TYPES hosts the list of type that are supported in JSON 40 | var JSON_TYPES []string 41 | 42 | // SCHEMA_TYPES hosts the list of type that are supported in schemas 43 | var SCHEMA_TYPES []string 44 | 45 | func init() { 46 | JSON_TYPES = []string{ 47 | TYPE_ARRAY, 48 | TYPE_BOOLEAN, 49 | TYPE_INTEGER, 50 | TYPE_NUMBER, 51 | TYPE_NULL, 52 | TYPE_OBJECT, 53 | TYPE_STRING} 54 | 55 | SCHEMA_TYPES = []string{ 56 | TYPE_ARRAY, 57 | TYPE_BOOLEAN, 58 | TYPE_INTEGER, 59 | TYPE_NUMBER, 60 | TYPE_OBJECT, 61 | TYPE_STRING} 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/xeipuuv/gojsonschema/utils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 xeipuuv ( https://github.com/xeipuuv ) 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 | 15 | // author xeipuuv 16 | // author-github https://github.com/xeipuuv 17 | // author-mail xeipuuv@gmail.com 18 | // 19 | // repository-name gojsonschema 20 | // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language. 21 | // 22 | // description Various utility functions. 23 | // 24 | // created 26-02-2013 25 | 26 | package gojsonschema 27 | 28 | import ( 29 | "encoding/json" 30 | "math/big" 31 | "reflect" 32 | ) 33 | 34 | func isKind(what interface{}, kinds ...reflect.Kind) bool { 35 | target := what 36 | if isJSONNumber(what) { 37 | // JSON Numbers are strings! 38 | target = *mustBeNumber(what) 39 | } 40 | targetKind := reflect.ValueOf(target).Kind() 41 | for _, kind := range kinds { 42 | if targetKind == kind { 43 | return true 44 | } 45 | } 46 | return false 47 | } 48 | 49 | func existsMapKey(m map[string]interface{}, k string) bool { 50 | _, ok := m[k] 51 | return ok 52 | } 53 | 54 | func isStringInSlice(s []string, what string) bool { 55 | for i := range s { 56 | if s[i] == what { 57 | return true 58 | } 59 | } 60 | return false 61 | } 62 | 63 | // indexStringInSlice returns the index of the first instance of 'what' in s or -1 if it is not found in s. 64 | func indexStringInSlice(s []string, what string) int { 65 | for i := range s { 66 | if s[i] == what { 67 | return i 68 | } 69 | } 70 | return -1 71 | } 72 | 73 | func marshalToJSONString(value interface{}) (*string, error) { 74 | 75 | mBytes, err := json.Marshal(value) 76 | if err != nil { 77 | return nil, err 78 | } 79 | 80 | sBytes := string(mBytes) 81 | return &sBytes, nil 82 | } 83 | 84 | func marshalWithoutNumber(value interface{}) (*string, error) { 85 | 86 | // The JSON is decoded using https://golang.org/pkg/encoding/json/#Decoder.UseNumber 87 | // This means the numbers are internally still represented as strings and therefore 1.00 is unequal to 1 88 | // One way to eliminate these differences is to decode and encode the JSON one more time without Decoder.UseNumber 89 | // so that these differences in representation are removed 90 | 91 | jsonString, err := marshalToJSONString(value) 92 | if err != nil { 93 | return nil, err 94 | } 95 | 96 | var document interface{} 97 | 98 | err = json.Unmarshal([]byte(*jsonString), &document) 99 | if err != nil { 100 | return nil, err 101 | } 102 | 103 | return marshalToJSONString(document) 104 | } 105 | 106 | func isJSONNumber(what interface{}) bool { 107 | 108 | switch what.(type) { 109 | 110 | case json.Number: 111 | return true 112 | } 113 | 114 | return false 115 | } 116 | 117 | func checkJSONInteger(what interface{}) (isInt bool) { 118 | 119 | jsonNumber := what.(json.Number) 120 | 121 | bigFloat, isValidNumber := new(big.Rat).SetString(string(jsonNumber)) 122 | 123 | return isValidNumber && bigFloat.IsInt() 124 | 125 | } 126 | 127 | // same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER 128 | const ( 129 | maxJSONFloat = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1 130 | minJSONFloat = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1 131 | ) 132 | 133 | func mustBeInteger(what interface{}) *int { 134 | 135 | if isJSONNumber(what) { 136 | 137 | number := what.(json.Number) 138 | 139 | isInt := checkJSONInteger(number) 140 | 141 | if isInt { 142 | 143 | int64Value, err := number.Int64() 144 | if err != nil { 145 | return nil 146 | } 147 | 148 | int32Value := int(int64Value) 149 | return &int32Value 150 | } 151 | 152 | } 153 | 154 | return nil 155 | } 156 | 157 | func mustBeNumber(what interface{}) *big.Rat { 158 | 159 | if isJSONNumber(what) { 160 | number := what.(json.Number) 161 | float64Value, success := new(big.Rat).SetString(string(number)) 162 | if success { 163 | return float64Value 164 | } 165 | } 166 | 167 | return nil 168 | 169 | } 170 | 171 | func convertDocumentNode(val interface{}) interface{} { 172 | 173 | if lval, ok := val.([]interface{}); ok { 174 | 175 | res := []interface{}{} 176 | for _, v := range lval { 177 | res = append(res, convertDocumentNode(v)) 178 | } 179 | 180 | return res 181 | 182 | } 183 | 184 | if mval, ok := val.(map[interface{}]interface{}); ok { 185 | 186 | res := map[string]interface{}{} 187 | 188 | for k, v := range mval { 189 | res[k.(string)] = convertDocumentNode(v) 190 | } 191 | 192 | return res 193 | 194 | } 195 | 196 | return val 197 | } 198 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - "1.4.x" 5 | - "1.5.x" 6 | - "1.6.x" 7 | - "1.7.x" 8 | - "1.8.x" 9 | - "1.9.x" 10 | - "1.10.x" 11 | - "1.11.x" 12 | - "1.12.x" 13 | - "1.13.x" 14 | - "tip" 15 | 16 | go_import_path: gopkg.in/yaml.v2 17 | -------------------------------------------------------------------------------- /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 | ```Go 52 | package main 53 | 54 | import ( 55 | "fmt" 56 | "log" 57 | 58 | "gopkg.in/yaml.v2" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | // Note: struct fields must be public in order for unmarshal to 69 | // correctly populate the data. 70 | type T struct { 71 | A string 72 | B struct { 73 | RenamedC int `yaml:"c"` 74 | D []int `yaml:",flow"` 75 | } 76 | } 77 | 78 | func main() { 79 | t := T{} 80 | 81 | err := yaml.Unmarshal([]byte(data), &t) 82 | if err != nil { 83 | log.Fatalf("error: %v", err) 84 | } 85 | fmt.Printf("--- t:\n%v\n\n", t) 86 | 87 | d, err := yaml.Marshal(&t) 88 | if err != nil { 89 | log.Fatalf("error: %v", err) 90 | } 91 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 92 | 93 | m := make(map[interface{}]interface{}) 94 | 95 | err = yaml.Unmarshal([]byte(data), &m) 96 | if err != nil { 97 | log.Fatalf("error: %v", err) 98 | } 99 | fmt.Printf("--- m:\n%v\n\n", m) 100 | 101 | d, err = yaml.Marshal(&m) 102 | if err != nil { 103 | log.Fatalf("error: %v", err) 104 | } 105 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 106 | } 107 | ``` 108 | 109 | This example will generate the following output: 110 | 111 | ``` 112 | --- t: 113 | {Easy! {2 [3 4]}} 114 | 115 | --- t dump: 116 | a: Easy! 117 | b: 118 | c: 2 119 | d: [3, 4] 120 | 121 | 122 | --- m: 123 | map[a:Easy! b:map[c:2 d:[3 4]]] 124 | 125 | --- m dump: 126 | a: Easy! 127 | b: 128 | c: 2 129 | d: 130 | - 3 131 | - 4 132 | ``` 133 | 134 | -------------------------------------------------------------------------------- /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 | // jsonNumber is the interface of the encoding/json.Number datatype. 17 | // Repeating the interface here avoids a dependency on encoding/json, and also 18 | // supports other libraries like jsoniter, which use a similar datatype with 19 | // the same interface. Detecting this interface is useful when dealing with 20 | // structures containing json.Number, which is a string under the hood. The 21 | // encoder should prefer the use of Int64(), Float64() and string(), in that 22 | // order, when encoding this type. 23 | type jsonNumber interface { 24 | Float64() (float64, error) 25 | Int64() (int64, error) 26 | String() string 27 | } 28 | 29 | type encoder struct { 30 | emitter yaml_emitter_t 31 | event yaml_event_t 32 | out []byte 33 | flow bool 34 | // doneInit holds whether the initial stream_start_event has been 35 | // emitted. 36 | doneInit bool 37 | } 38 | 39 | func newEncoder() *encoder { 40 | e := &encoder{} 41 | yaml_emitter_initialize(&e.emitter) 42 | yaml_emitter_set_output_string(&e.emitter, &e.out) 43 | yaml_emitter_set_unicode(&e.emitter, true) 44 | return e 45 | } 46 | 47 | func newEncoderWithWriter(w io.Writer) *encoder { 48 | e := &encoder{} 49 | yaml_emitter_initialize(&e.emitter) 50 | yaml_emitter_set_output_writer(&e.emitter, w) 51 | yaml_emitter_set_unicode(&e.emitter, true) 52 | return e 53 | } 54 | 55 | func (e *encoder) init() { 56 | if e.doneInit { 57 | return 58 | } 59 | yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) 60 | e.emit() 61 | e.doneInit = true 62 | } 63 | 64 | func (e *encoder) finish() { 65 | e.emitter.open_ended = false 66 | yaml_stream_end_event_initialize(&e.event) 67 | e.emit() 68 | } 69 | 70 | func (e *encoder) destroy() { 71 | yaml_emitter_delete(&e.emitter) 72 | } 73 | 74 | func (e *encoder) emit() { 75 | // This will internally delete the e.event value. 76 | e.must(yaml_emitter_emit(&e.emitter, &e.event)) 77 | } 78 | 79 | func (e *encoder) must(ok bool) { 80 | if !ok { 81 | msg := e.emitter.problem 82 | if msg == "" { 83 | msg = "unknown problem generating YAML content" 84 | } 85 | failf("%s", msg) 86 | } 87 | } 88 | 89 | func (e *encoder) marshalDoc(tag string, in reflect.Value) { 90 | e.init() 91 | yaml_document_start_event_initialize(&e.event, nil, nil, true) 92 | e.emit() 93 | e.marshal(tag, in) 94 | yaml_document_end_event_initialize(&e.event, true) 95 | e.emit() 96 | } 97 | 98 | func (e *encoder) marshal(tag string, in reflect.Value) { 99 | if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { 100 | e.nilv() 101 | return 102 | } 103 | iface := in.Interface() 104 | switch m := iface.(type) { 105 | case jsonNumber: 106 | integer, err := m.Int64() 107 | if err == nil { 108 | // In this case the json.Number is a valid int64 109 | in = reflect.ValueOf(integer) 110 | break 111 | } 112 | float, err := m.Float64() 113 | if err == nil { 114 | // In this case the json.Number is a valid float64 115 | in = reflect.ValueOf(float) 116 | break 117 | } 118 | // fallback case - no number could be obtained 119 | in = reflect.ValueOf(m.String()) 120 | case time.Time, *time.Time: 121 | // Although time.Time implements TextMarshaler, 122 | // we don't want to treat it as a string for YAML 123 | // purposes because YAML has special support for 124 | // timestamps. 125 | case Marshaler: 126 | v, err := m.MarshalYAML() 127 | if err != nil { 128 | fail(err) 129 | } 130 | if v == nil { 131 | e.nilv() 132 | return 133 | } 134 | in = reflect.ValueOf(v) 135 | case encoding.TextMarshaler: 136 | text, err := m.MarshalText() 137 | if err != nil { 138 | fail(err) 139 | } 140 | in = reflect.ValueOf(string(text)) 141 | case nil: 142 | e.nilv() 143 | return 144 | } 145 | switch in.Kind() { 146 | case reflect.Interface: 147 | e.marshal(tag, in.Elem()) 148 | case reflect.Map: 149 | e.mapv(tag, in) 150 | case reflect.Ptr: 151 | if in.Type() == ptrTimeType { 152 | e.timev(tag, in.Elem()) 153 | } else { 154 | e.marshal(tag, in.Elem()) 155 | } 156 | case reflect.Struct: 157 | if in.Type() == timeType { 158 | e.timev(tag, in) 159 | } else { 160 | e.structv(tag, in) 161 | } 162 | case reflect.Slice, reflect.Array: 163 | if in.Type().Elem() == mapItemType { 164 | e.itemsv(tag, in) 165 | } else { 166 | e.slicev(tag, in) 167 | } 168 | case reflect.String: 169 | e.stringv(tag, in) 170 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 171 | if in.Type() == durationType { 172 | e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) 173 | } else { 174 | e.intv(tag, in) 175 | } 176 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 177 | e.uintv(tag, in) 178 | case reflect.Float32, reflect.Float64: 179 | e.floatv(tag, in) 180 | case reflect.Bool: 181 | e.boolv(tag, in) 182 | default: 183 | panic("cannot marshal type: " + in.Type().String()) 184 | } 185 | } 186 | 187 | func (e *encoder) mapv(tag string, in reflect.Value) { 188 | e.mappingv(tag, func() { 189 | keys := keyList(in.MapKeys()) 190 | sort.Sort(keys) 191 | for _, k := range keys { 192 | e.marshal("", k) 193 | e.marshal("", in.MapIndex(k)) 194 | } 195 | }) 196 | } 197 | 198 | func (e *encoder) itemsv(tag string, in reflect.Value) { 199 | e.mappingv(tag, func() { 200 | slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) 201 | for _, item := range slice { 202 | e.marshal("", reflect.ValueOf(item.Key)) 203 | e.marshal("", reflect.ValueOf(item.Value)) 204 | } 205 | }) 206 | } 207 | 208 | func (e *encoder) structv(tag string, in reflect.Value) { 209 | sinfo, err := getStructInfo(in.Type()) 210 | if err != nil { 211 | panic(err) 212 | } 213 | e.mappingv(tag, func() { 214 | for _, info := range sinfo.FieldsList { 215 | var value reflect.Value 216 | if info.Inline == nil { 217 | value = in.Field(info.Num) 218 | } else { 219 | value = in.FieldByIndex(info.Inline) 220 | } 221 | if info.OmitEmpty && isZero(value) { 222 | continue 223 | } 224 | e.marshal("", reflect.ValueOf(info.Key)) 225 | e.flow = info.Flow 226 | e.marshal("", value) 227 | } 228 | if sinfo.InlineMap >= 0 { 229 | m := in.Field(sinfo.InlineMap) 230 | if m.Len() > 0 { 231 | e.flow = false 232 | keys := keyList(m.MapKeys()) 233 | sort.Sort(keys) 234 | for _, k := range keys { 235 | if _, found := sinfo.FieldsMap[k.String()]; found { 236 | panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String())) 237 | } 238 | e.marshal("", k) 239 | e.flow = false 240 | e.marshal("", m.MapIndex(k)) 241 | } 242 | } 243 | } 244 | }) 245 | } 246 | 247 | func (e *encoder) mappingv(tag string, f func()) { 248 | implicit := tag == "" 249 | style := yaml_BLOCK_MAPPING_STYLE 250 | if e.flow { 251 | e.flow = false 252 | style = yaml_FLOW_MAPPING_STYLE 253 | } 254 | yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) 255 | e.emit() 256 | f() 257 | yaml_mapping_end_event_initialize(&e.event) 258 | e.emit() 259 | } 260 | 261 | func (e *encoder) slicev(tag string, in reflect.Value) { 262 | implicit := tag == "" 263 | style := yaml_BLOCK_SEQUENCE_STYLE 264 | if e.flow { 265 | e.flow = false 266 | style = yaml_FLOW_SEQUENCE_STYLE 267 | } 268 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 269 | e.emit() 270 | n := in.Len() 271 | for i := 0; i < n; i++ { 272 | e.marshal("", in.Index(i)) 273 | } 274 | e.must(yaml_sequence_end_event_initialize(&e.event)) 275 | e.emit() 276 | } 277 | 278 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. 279 | // 280 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported 281 | // in YAML 1.2 and by this package, but these should be marshalled quoted for 282 | // the time being for compatibility with other parsers. 283 | func isBase60Float(s string) (result bool) { 284 | // Fast path. 285 | if s == "" { 286 | return false 287 | } 288 | c := s[0] 289 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { 290 | return false 291 | } 292 | // Do the full match. 293 | return base60float.MatchString(s) 294 | } 295 | 296 | // From http://yaml.org/type/float.html, except the regular expression there 297 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. 298 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) 299 | 300 | func (e *encoder) stringv(tag string, in reflect.Value) { 301 | var style yaml_scalar_style_t 302 | s := in.String() 303 | canUsePlain := true 304 | switch { 305 | case !utf8.ValidString(s): 306 | if tag == yaml_BINARY_TAG { 307 | failf("explicitly tagged !!binary data must be base64-encoded") 308 | } 309 | if tag != "" { 310 | failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) 311 | } 312 | // It can't be encoded directly as YAML so use a binary tag 313 | // and encode it as base64. 314 | tag = yaml_BINARY_TAG 315 | s = encodeBase64(s) 316 | case tag == "": 317 | // Check to see if it would resolve to a specific 318 | // tag when encoded unquoted. If it doesn't, 319 | // there's no need to quote it. 320 | rtag, _ := resolve("", s) 321 | canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s) 322 | } 323 | // Note: it's possible for user code to emit invalid YAML 324 | // if they explicitly specify a tag and a string containing 325 | // text that's incompatible with that tag. 326 | switch { 327 | case strings.Contains(s, "\n"): 328 | style = yaml_LITERAL_SCALAR_STYLE 329 | case canUsePlain: 330 | style = yaml_PLAIN_SCALAR_STYLE 331 | default: 332 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 333 | } 334 | e.emitScalar(s, "", tag, style) 335 | } 336 | 337 | func (e *encoder) boolv(tag string, in reflect.Value) { 338 | var s string 339 | if in.Bool() { 340 | s = "true" 341 | } else { 342 | s = "false" 343 | } 344 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 345 | } 346 | 347 | func (e *encoder) intv(tag string, in reflect.Value) { 348 | s := strconv.FormatInt(in.Int(), 10) 349 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 350 | } 351 | 352 | func (e *encoder) uintv(tag string, in reflect.Value) { 353 | s := strconv.FormatUint(in.Uint(), 10) 354 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 355 | } 356 | 357 | func (e *encoder) timev(tag string, in reflect.Value) { 358 | t := in.Interface().(time.Time) 359 | s := t.Format(time.RFC3339Nano) 360 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 361 | } 362 | 363 | func (e *encoder) floatv(tag string, in reflect.Value) { 364 | // Issue #352: When formatting, use the precision of the underlying value 365 | precision := 64 366 | if in.Kind() == reflect.Float32 { 367 | precision = 32 368 | } 369 | 370 | s := strconv.FormatFloat(in.Float(), 'g', -1, precision) 371 | switch s { 372 | case "+Inf": 373 | s = ".inf" 374 | case "-Inf": 375 | s = "-.inf" 376 | case "NaN": 377 | s = ".nan" 378 | } 379 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 380 | } 381 | 382 | func (e *encoder) nilv() { 383 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) 384 | } 385 | 386 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { 387 | implicit := tag == "" 388 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) 389 | e.emit() 390 | } 391 | -------------------------------------------------------------------------------- /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 | // [Go] This function was changed to guarantee the requested length size at EOF. 97 | // The fact we need to do this is pretty awful, but the description above implies 98 | // for that to be the case, and there are tests 99 | 100 | // If the EOF flag is set and the raw buffer is empty, do nothing. 101 | if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { 102 | // [Go] ACTUALLY! Read the documentation of this function above. 103 | // This is just broken. To return true, we need to have the 104 | // given length in the buffer. Not doing that means every single 105 | // check that calls this function to make sure the buffer has a 106 | // given length is Go) panicking; or C) accessing invalid memory. 107 | //return true 108 | } 109 | 110 | // Return if the buffer contains enough characters. 111 | if parser.unread >= length { 112 | return true 113 | } 114 | 115 | // Determine the input encoding if it is not known yet. 116 | if parser.encoding == yaml_ANY_ENCODING { 117 | if !yaml_parser_determine_encoding(parser) { 118 | return false 119 | } 120 | } 121 | 122 | // Move the unread characters to the beginning of the buffer. 123 | buffer_len := len(parser.buffer) 124 | if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { 125 | copy(parser.buffer, parser.buffer[parser.buffer_pos:]) 126 | buffer_len -= parser.buffer_pos 127 | parser.buffer_pos = 0 128 | } else if parser.buffer_pos == buffer_len { 129 | buffer_len = 0 130 | parser.buffer_pos = 0 131 | } 132 | 133 | // Open the whole buffer for writing, and cut it before returning. 134 | parser.buffer = parser.buffer[:cap(parser.buffer)] 135 | 136 | // Fill the buffer until it has enough characters. 137 | first := true 138 | for parser.unread < length { 139 | 140 | // Fill the raw buffer if necessary. 141 | if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { 142 | if !yaml_parser_update_raw_buffer(parser) { 143 | parser.buffer = parser.buffer[:buffer_len] 144 | return false 145 | } 146 | } 147 | first = false 148 | 149 | // Decode the raw buffer. 150 | inner: 151 | for parser.raw_buffer_pos != len(parser.raw_buffer) { 152 | var value rune 153 | var width int 154 | 155 | raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos 156 | 157 | // Decode the next character. 158 | switch parser.encoding { 159 | case yaml_UTF8_ENCODING: 160 | // Decode a UTF-8 character. Check RFC 3629 161 | // (http://www.ietf.org/rfc/rfc3629.txt) for more details. 162 | // 163 | // The following table (taken from the RFC) is used for 164 | // decoding. 165 | // 166 | // Char. number range | UTF-8 octet sequence 167 | // (hexadecimal) | (binary) 168 | // --------------------+------------------------------------ 169 | // 0000 0000-0000 007F | 0xxxxxxx 170 | // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 171 | // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 172 | // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 173 | // 174 | // Additionally, the characters in the range 0xD800-0xDFFF 175 | // are prohibited as they are reserved for use with UTF-16 176 | // surrogate pairs. 177 | 178 | // Determine the length of the UTF-8 sequence. 179 | octet := parser.raw_buffer[parser.raw_buffer_pos] 180 | switch { 181 | case octet&0x80 == 0x00: 182 | width = 1 183 | case octet&0xE0 == 0xC0: 184 | width = 2 185 | case octet&0xF0 == 0xE0: 186 | width = 3 187 | case octet&0xF8 == 0xF0: 188 | width = 4 189 | default: 190 | // The leading octet is invalid. 191 | return yaml_parser_set_reader_error(parser, 192 | "invalid leading UTF-8 octet", 193 | parser.offset, int(octet)) 194 | } 195 | 196 | // Check if the raw buffer contains an incomplete character. 197 | if width > raw_unread { 198 | if parser.eof { 199 | return yaml_parser_set_reader_error(parser, 200 | "incomplete UTF-8 octet sequence", 201 | parser.offset, -1) 202 | } 203 | break inner 204 | } 205 | 206 | // Decode the leading octet. 207 | switch { 208 | case octet&0x80 == 0x00: 209 | value = rune(octet & 0x7F) 210 | case octet&0xE0 == 0xC0: 211 | value = rune(octet & 0x1F) 212 | case octet&0xF0 == 0xE0: 213 | value = rune(octet & 0x0F) 214 | case octet&0xF8 == 0xF0: 215 | value = rune(octet & 0x07) 216 | default: 217 | value = 0 218 | } 219 | 220 | // Check and decode the trailing octets. 221 | for k := 1; k < width; k++ { 222 | octet = parser.raw_buffer[parser.raw_buffer_pos+k] 223 | 224 | // Check if the octet is valid. 225 | if (octet & 0xC0) != 0x80 { 226 | return yaml_parser_set_reader_error(parser, 227 | "invalid trailing UTF-8 octet", 228 | parser.offset+k, int(octet)) 229 | } 230 | 231 | // Decode the octet. 232 | value = (value << 6) + rune(octet&0x3F) 233 | } 234 | 235 | // Check the length of the sequence against the value. 236 | switch { 237 | case width == 1: 238 | case width == 2 && value >= 0x80: 239 | case width == 3 && value >= 0x800: 240 | case width == 4 && value >= 0x10000: 241 | default: 242 | return yaml_parser_set_reader_error(parser, 243 | "invalid length of a UTF-8 sequence", 244 | parser.offset, -1) 245 | } 246 | 247 | // Check the range of the value. 248 | if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { 249 | return yaml_parser_set_reader_error(parser, 250 | "invalid Unicode character", 251 | parser.offset, int(value)) 252 | } 253 | 254 | case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: 255 | var low, high int 256 | if parser.encoding == yaml_UTF16LE_ENCODING { 257 | low, high = 0, 1 258 | } else { 259 | low, high = 1, 0 260 | } 261 | 262 | // The UTF-16 encoding is not as simple as one might 263 | // naively think. Check RFC 2781 264 | // (http://www.ietf.org/rfc/rfc2781.txt). 265 | // 266 | // Normally, two subsequent bytes describe a Unicode 267 | // character. However a special technique (called a 268 | // surrogate pair) is used for specifying character 269 | // values larger than 0xFFFF. 270 | // 271 | // A surrogate pair consists of two pseudo-characters: 272 | // high surrogate area (0xD800-0xDBFF) 273 | // low surrogate area (0xDC00-0xDFFF) 274 | // 275 | // The following formulas are used for decoding 276 | // and encoding characters using surrogate pairs: 277 | // 278 | // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) 279 | // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) 280 | // W1 = 110110yyyyyyyyyy 281 | // W2 = 110111xxxxxxxxxx 282 | // 283 | // where U is the character value, W1 is the high surrogate 284 | // area, W2 is the low surrogate area. 285 | 286 | // Check for incomplete UTF-16 character. 287 | if raw_unread < 2 { 288 | if parser.eof { 289 | return yaml_parser_set_reader_error(parser, 290 | "incomplete UTF-16 character", 291 | parser.offset, -1) 292 | } 293 | break inner 294 | } 295 | 296 | // Get the character. 297 | value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + 298 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) 299 | 300 | // Check for unexpected low surrogate area. 301 | if value&0xFC00 == 0xDC00 { 302 | return yaml_parser_set_reader_error(parser, 303 | "unexpected low surrogate area", 304 | parser.offset, int(value)) 305 | } 306 | 307 | // Check for a high surrogate area. 308 | if value&0xFC00 == 0xD800 { 309 | width = 4 310 | 311 | // Check for incomplete surrogate pair. 312 | if raw_unread < 4 { 313 | if parser.eof { 314 | return yaml_parser_set_reader_error(parser, 315 | "incomplete UTF-16 surrogate pair", 316 | parser.offset, -1) 317 | } 318 | break inner 319 | } 320 | 321 | // Get the next character. 322 | value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + 323 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) 324 | 325 | // Check for a low surrogate area. 326 | if value2&0xFC00 != 0xDC00 { 327 | return yaml_parser_set_reader_error(parser, 328 | "expected low surrogate area", 329 | parser.offset+2, int(value2)) 330 | } 331 | 332 | // Generate the value of the surrogate pair. 333 | value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) 334 | } else { 335 | width = 2 336 | } 337 | 338 | default: 339 | panic("impossible") 340 | } 341 | 342 | // Check if the character is in the allowed range: 343 | // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) 344 | // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) 345 | // | [#x10000-#x10FFFF] (32 bit) 346 | switch { 347 | case value == 0x09: 348 | case value == 0x0A: 349 | case value == 0x0D: 350 | case value >= 0x20 && value <= 0x7E: 351 | case value == 0x85: 352 | case value >= 0xA0 && value <= 0xD7FF: 353 | case value >= 0xE000 && value <= 0xFFFD: 354 | case value >= 0x10000 && value <= 0x10FFFF: 355 | default: 356 | return yaml_parser_set_reader_error(parser, 357 | "control characters are not allowed", 358 | parser.offset, int(value)) 359 | } 360 | 361 | // Move the raw pointers. 362 | parser.raw_buffer_pos += width 363 | parser.offset += width 364 | 365 | // Finally put the character into the buffer. 366 | if value <= 0x7F { 367 | // 0000 0000-0000 007F . 0xxxxxxx 368 | parser.buffer[buffer_len+0] = byte(value) 369 | buffer_len += 1 370 | } else if value <= 0x7FF { 371 | // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx 372 | parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) 373 | parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) 374 | buffer_len += 2 375 | } else if value <= 0xFFFF { 376 | // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx 377 | parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) 378 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) 379 | parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) 380 | buffer_len += 3 381 | } else { 382 | // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 383 | parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) 384 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) 385 | parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) 386 | parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) 387 | buffer_len += 4 388 | } 389 | 390 | parser.unread++ 391 | } 392 | 393 | // On EOF, put NUL into the buffer and return. 394 | if parser.eof { 395 | parser.buffer[buffer_len] = 0 396 | buffer_len++ 397 | parser.unread++ 398 | break 399 | } 400 | } 401 | // [Go] Read the documentation of this function above. To return true, 402 | // we need to have the given length in the buffer. Not doing that means 403 | // every single check that calls this function to make sure the buffer 404 | // has a given length is Go) panicking; or C) accessing invalid memory. 405 | // This happens here due to the EOF above breaking early. 406 | for buffer_len < length { 407 | parser.buffer[buffer_len] = 0 408 | buffer_len++ 409 | } 410 | parser.buffer = parser.buffer[:buffer_len] 411 | return true 412 | } 413 | -------------------------------------------------------------------------------- /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]+(\.[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 | case yaml_FLOAT_TAG: 96 | if rtag == yaml_INT_TAG { 97 | switch v := out.(type) { 98 | case int64: 99 | rtag = yaml_FLOAT_TAG 100 | out = float64(v) 101 | return 102 | case int: 103 | rtag = yaml_FLOAT_TAG 104 | out = float64(v) 105 | return 106 | } 107 | } 108 | } 109 | failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) 110 | }() 111 | 112 | // Any data is accepted as a !!str or !!binary. 113 | // Otherwise, the prefix is enough of a hint about what it might be. 114 | hint := byte('N') 115 | if in != "" { 116 | hint = resolveTable[in[0]] 117 | } 118 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { 119 | // Handle things we can lookup in a map. 120 | if item, ok := resolveMap[in]; ok { 121 | return item.tag, item.value 122 | } 123 | 124 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 125 | // are purposefully unsupported here. They're still quoted on 126 | // the way out for compatibility with other parser, though. 127 | 128 | switch hint { 129 | case 'M': 130 | // We've already checked the map above. 131 | 132 | case '.': 133 | // Not in the map, so maybe a normal float. 134 | floatv, err := strconv.ParseFloat(in, 64) 135 | if err == nil { 136 | return yaml_FLOAT_TAG, floatv 137 | } 138 | 139 | case 'D', 'S': 140 | // Int, float, or timestamp. 141 | // Only try values as a timestamp if the value is unquoted or there's an explicit 142 | // !!timestamp tag. 143 | if tag == "" || tag == yaml_TIMESTAMP_TAG { 144 | t, ok := parseTimestamp(in) 145 | if ok { 146 | return yaml_TIMESTAMP_TAG, t 147 | } 148 | } 149 | 150 | plain := strings.Replace(in, "_", "", -1) 151 | intv, err := strconv.ParseInt(plain, 0, 64) 152 | if err == nil { 153 | if intv == int64(int(intv)) { 154 | return yaml_INT_TAG, int(intv) 155 | } else { 156 | return yaml_INT_TAG, intv 157 | } 158 | } 159 | uintv, err := strconv.ParseUint(plain, 0, 64) 160 | if err == nil { 161 | return yaml_INT_TAG, uintv 162 | } 163 | if yamlStyleFloat.MatchString(plain) { 164 | floatv, err := strconv.ParseFloat(plain, 64) 165 | if err == nil { 166 | return yaml_FLOAT_TAG, floatv 167 | } 168 | } 169 | if strings.HasPrefix(plain, "0b") { 170 | intv, err := strconv.ParseInt(plain[2:], 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 | uintv, err := strconv.ParseUint(plain[2:], 2, 64) 179 | if err == nil { 180 | return yaml_INT_TAG, uintv 181 | } 182 | } else if strings.HasPrefix(plain, "-0b") { 183 | intv, err := strconv.ParseInt("-" + plain[3:], 2, 64) 184 | if err == nil { 185 | if true || intv == int64(int(intv)) { 186 | return yaml_INT_TAG, int(intv) 187 | } else { 188 | return yaml_INT_TAG, intv 189 | } 190 | } 191 | } 192 | default: 193 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 194 | } 195 | } 196 | return yaml_STR_TAG, in 197 | } 198 | 199 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 200 | // as appropriate for the resulting length. 201 | func encodeBase64(s string) string { 202 | const lineLen = 70 203 | encLen := base64.StdEncoding.EncodedLen(len(s)) 204 | lines := encLen/lineLen + 1 205 | buf := make([]byte, encLen*2+lines) 206 | in := buf[0:encLen] 207 | out := buf[encLen:] 208 | base64.StdEncoding.Encode(in, []byte(s)) 209 | k := 0 210 | for i := 0; i < len(in); i += lineLen { 211 | j := i + lineLen 212 | if j > len(in) { 213 | j = len(in) 214 | } 215 | k += copy(out[k:], in[i:j]) 216 | if lines > 1 { 217 | out[k] = '\n' 218 | k++ 219 | } 220 | } 221 | return string(out[:k]) 222 | } 223 | 224 | // This is a subset of the formats allowed by the regular expression 225 | // defined at http://yaml.org/type/timestamp.html. 226 | var allowedTimestampFormats = []string{ 227 | "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. 228 | "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". 229 | "2006-1-2 15:4:5.999999999", // space separated with no time zone 230 | "2006-1-2", // date only 231 | // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" 232 | // from the set of examples. 233 | } 234 | 235 | // parseTimestamp parses s as a timestamp string and 236 | // returns the timestamp and reports whether it succeeded. 237 | // Timestamp formats are defined at http://yaml.org/type/timestamp.html 238 | func parseTimestamp(s string) (time.Time, bool) { 239 | // TODO write code to check all the formats supported by 240 | // http://yaml.org/type/timestamp.html instead of using time.Parse. 241 | 242 | // Quick check: all date formats start with YYYY-. 243 | i := 0 244 | for ; i < len(s); i++ { 245 | if c := s[i]; c < '0' || c > '9' { 246 | break 247 | } 248 | } 249 | if i != 4 || i == len(s) || s[i] != '-' { 250 | return time.Time{}, false 251 | } 252 | for _, format := range allowedTimestampFormats { 253 | if t, err := time.Parse(format, s); err == nil { 254 | return t, true 255 | } 256 | } 257 | return time.Time{}, false 258 | } 259 | -------------------------------------------------------------------------------- /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 | if ar[i] == '0' || br[i] == '0' { 55 | for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { 56 | if ar[j] != '0' { 57 | an = 1 58 | bn = 1 59 | break 60 | } 61 | } 62 | } 63 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 64 | an = an*10 + int64(ar[ai]-'0') 65 | } 66 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 67 | bn = bn*10 + int64(br[bi]-'0') 68 | } 69 | if an != bn { 70 | return an < bn 71 | } 72 | if ai != bi { 73 | return ai < bi 74 | } 75 | return ar[i] < br[i] 76 | } 77 | return len(ar) < len(br) 78 | } 79 | 80 | // keyFloat returns a float value for v if it is a number/bool 81 | // and whether it is a number/bool or not. 82 | func keyFloat(v reflect.Value) (f float64, ok bool) { 83 | switch v.Kind() { 84 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 85 | return float64(v.Int()), true 86 | case reflect.Float32, reflect.Float64: 87 | return v.Float(), true 88 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 89 | return float64(v.Uint()), true 90 | case reflect.Bool: 91 | if v.Bool() { 92 | return 1, true 93 | } 94 | return 0, true 95 | } 96 | return 0, false 97 | } 98 | 99 | // numLess returns whether a < b. 100 | // a and b must necessarily have the same kind. 101 | func numLess(a, b reflect.Value) bool { 102 | switch a.Kind() { 103 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 104 | return a.Int() < b.Int() 105 | case reflect.Float32, reflect.Float64: 106 | return a.Float() < b.Float() 107 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 108 | return a.Uint() < b.Uint() 109 | case reflect.Bool: 110 | return !a.Bool() && b.Bool() 111 | } 112 | panic("not a number") 113 | } 114 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f 2 | github.com/xeipuuv/gojsonpointer 3 | # github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 4 | github.com/xeipuuv/gojsonreference 5 | # github.com/xeipuuv/gojsonschema v1.2.0 6 | ## explicit 7 | github.com/xeipuuv/gojsonschema 8 | # gopkg.in/yaml.v2 v2.3.0 9 | ## explicit 10 | gopkg.in/yaml.v2 11 | --------------------------------------------------------------------------------