├── 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 [](http://godoc.org/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 |
--------------------------------------------------------------------------------