├── .gitignore
├── Gopkg.lock
├── Gopkg.toml
├── LICENSE
├── README.md
├── hades
└── hades.go
├── init.sh
├── lib
└── server
│ ├── pusher.go
│ ├── response_buffer.go
│ └── server.go
└── vendor
└── github.com
├── gabesullice
└── jq
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc.go
│ ├── op.go
│ ├── op_chain_test.go
│ ├── op_dot_test.go
│ ├── parse.go
│ ├── parse_regexp_test.go
│ ├── parse_test.go
│ └── scanner
│ ├── any.go
│ ├── any_test.go
│ ├── array.go
│ ├── array_test.go
│ ├── as.go
│ ├── as_array_test.go
│ ├── bool.go
│ ├── doc.go
│ ├── err.go
│ ├── find_from.go
│ ├── find_from_test.go
│ ├── find_index.go
│ ├── find_index_test.go
│ ├── find_key.go
│ ├── find_key_test.go
│ ├── find_range.go
│ ├── find_range_test.go
│ ├── find_to.go
│ ├── find_to_test.go
│ ├── null.go
│ ├── null_test.go
│ ├── number.go
│ ├── number_test.go
│ ├── object.go
│ ├── object_test.go
│ ├── string.go
│ ├── string_test.go
│ ├── util.go
│ └── util_test.go
└── satori
└── go.uuid
├── .travis.yml
├── LICENSE
├── README.md
├── codec.go
├── codec_test.go
├── generator.go
├── generator_test.go
├── sql.go
├── sql_test.go
├── uuid.go
└── uuid_test.go
/.gitignore:
--------------------------------------------------------------------------------
1 | /hades/hades
2 | /server.crt
3 | /server.key
4 |
--------------------------------------------------------------------------------
/Gopkg.lock:
--------------------------------------------------------------------------------
1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
2 |
3 |
4 | [[projects]]
5 | branch = "rename-imports"
6 | name = "github.com/gabesullice/jq"
7 | packages = [
8 | ".",
9 | "scanner"
10 | ]
11 | revision = "2f1db31d92127040bab202f0f0a4ee6977eb7c7c"
12 |
13 | [[projects]]
14 | name = "github.com/satori/go.uuid"
15 | packages = ["."]
16 | revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3"
17 | version = "v1.2.0"
18 |
19 | [solve-meta]
20 | analyzer-name = "dep"
21 | analyzer-version = 1
22 | inputs-digest = "67483caa2bd23a0aaa96c343b9a76fdb467749d280a4d2933a1ff48e58b96a5b"
23 | solver-name = "gps-cdcl"
24 | solver-version = 1
25 |
--------------------------------------------------------------------------------
/Gopkg.toml:
--------------------------------------------------------------------------------
1 |
2 | # Gopkg.toml example
3 | #
4 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
5 | # for detailed Gopkg.toml documentation.
6 | #
7 | # required = ["github.com/user/thing/cmd/thing"]
8 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
9 | #
10 | # [[constraint]]
11 | # name = "github.com/user/project"
12 | # version = "1.0.0"
13 | #
14 | # [[constraint]]
15 | # name = "github.com/user/project2"
16 | # branch = "dev"
17 | # source = "github.com/myfork/project2"
18 | #
19 | # [[override]]
20 | # name = "github.com/x/y"
21 | # version = "2.4.0"
22 |
23 |
24 | [[constraint]]
25 | branch = "rename-imports"
26 | name = "github.com/gabesullice/jq"
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Gabriel Sullice
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 | Hades
2 | ===
3 |
4 | Hades is an **experimental** HATEOAS-based HTTP/2 reverse proxy for JSON API backends.
5 |
6 | ## Why?
7 | The JSON API specification makes ample use of `links` objects in its
8 | specification. These links objects contain URLs which enable a client to easily
9 | and automatically traverse documents to fetch subsequent pages, relationship
10 | data and related resources.
11 |
12 | With the ever increasing deployment of HTTP/2, these HATEOAS links become much
13 | more relevant, especially when they can be pushed to the client _before the
14 | client even requests them_.
15 |
16 | Hades is an intelligent reverse proxy that can be deployed in front of any
17 | JSON API server.
18 |
19 | Clients that are HTTP/2 capable can then send an `X-Push-Please` request header
20 | to your application. The values of this header should be comprised of [JSONPath selectors](http://goessner.net/articles/JsonPath/index.html#e2)
21 | which target links in the expected response document. Hades will identify these
22 | links and proactively push the linked resources to the client.
23 |
24 | Clients that are not HTTP/2 capable can also send these headers, Hades will
25 | simply not push the responses. Future versions of Hades might make further
26 | optimizations (like using the request to warm a server-side application cache).
27 |
28 | ## Example
29 | Take a JSON API server with `issue`, `comment` and `user` resource types as an
30 | example.
31 |
32 | A client would like to list the 10 most recent issues and embed user
33 | avatars for every participant in the issue.
34 |
35 | In JSON API terms, the data model is structured such that:
36 |
37 | 1. Issues have a relationship to comments
38 | 1. Comments have an author relationship to users
39 | 1. User resources have an attribute that specifies a URL for the user's avatar
40 |
41 | `issue -> comment -> user -> avatar`
42 |
43 | Traditionally, one might use the `include` query parameter to receive a compound
44 | document response. The compound document would embed the chain of resources in a
45 | single response. However, in this scenario, issues do not support includes on
46 | comments. They would be far too numerous—if 10 issues each have 100 comments,
47 | the compound document would have 1000 resources!
48 |
49 | This means that a client will first need to:
50 |
51 | 1. Fetch the first 10 issues
52 | 1. Fetch from the `related` or `relationship` routes for _each_ issue
53 | 1. Fetch the user resource for each unique author
54 | 1. Finally, download the user's avatar file using a download URL on the user resource
55 |
56 | This chain of requests is often called the "waterfall." Each step needs to be
57 | completed before the next step can proceed because the client can't know which
58 | resources to fetch in advance.
59 |
60 | In other words, the client can't know which users to fetch if it doesn't know
61 | which comments are on an issue... and the client can't know which comments to
62 | fetch without first fetching the issues.
63 |
64 | Hades solves this problem. By specifying the following request, a client can
65 | inform the Hades proxy which resources _it's going to fetch_ and Hades can then
66 | proactively push those resources to the client.
67 |
68 | ```
69 | GET /api/issues?sort=-created&page[limit]=10
70 |
71 | X-Push-Please: $.data[*].relationships.comments.links.related
72 | X-Push-Please: $.data[*].relationships.author.links.related
73 | X-Push-Please: $.data.attributes.avatar.url
74 | ```
75 | Multiple headers are permitted by HTTP/2. Alternatively, values may be
76 | concatenated with `;`
77 |
78 | Hades can use this information to identify the links in the response document
79 | that the client will eventually require. Future versions will permit response
80 | IDs in the `X-Push-Please` header so that link paths can target only specific
81 | responses.
82 |
83 | Apart from the client-sent header, _client applications need not be adapted in
84 | any way_. When the client recieves the initial response document, it should
85 | still request the subsequent documents just as it would under HTTP/1.1.
86 |
87 | However, because those request responses will have already been pushed, they
88 | will already be in a local cache or on the way! That means all responses will
89 | appear to have been received as if the client sent all the requests at the same
90 | time.
91 |
92 | Hades eliminates the waterfall.
93 |
94 | 🔥
95 |
--------------------------------------------------------------------------------
/hades/hades.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | "net/http/httputil"
7 | "net/url"
8 | "os"
9 |
10 | hades "github.com/gabesullice/hades/lib/server"
11 | )
12 |
13 | func main() {
14 | url, err := url.Parse(os.Args[1])
15 | if err != nil {
16 | log.Fatalln("Could not parse backend URL")
17 | }
18 | log.Printf("Started proxy for %v", url)
19 | backend := httputil.NewSingleHostReverseProxy(url)
20 | d := backend.Director
21 | backend.Director = func(r *http.Request) {
22 | r.Header.Set("X-Forwarded-Proto", "https")
23 | d(r)
24 | }
25 | http.Handle("/", hades.NewProxy(backend))
26 | log.Fatalln(http.ListenAndServeTLS(":443", "./server.crt", "./server.key", nil))
27 | }
28 |
--------------------------------------------------------------------------------
/init.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | main () {
6 | openssl genrsa -out server.key 2048
7 | openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
8 | }
9 |
10 | main $@
11 |
--------------------------------------------------------------------------------
/lib/server/pusher.go:
--------------------------------------------------------------------------------
1 | package server
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | "sync"
7 | )
8 |
9 | var ()
10 |
11 | type pusher struct {
12 | sync.WaitGroup
13 | p http.Pusher
14 | }
15 |
16 | func (r *pusher) push(target string, opts *http.PushOptions) {
17 | log.Printf("Pushing: %s", target)
18 | r.Add(1)
19 | if err := r.p.Push(target, opts); err != nil {
20 | r.Done()
21 | log.Printf("Push Error: %s", err)
22 | }
23 | log.Printf("Pushed: %s", target)
24 | }
25 |
26 | type pusherMap struct {
27 | sync.RWMutex
28 | pushers map[string]*pusher
29 | }
30 |
31 | func (r *pusherMap) add(id string, p *pusher) {
32 | r.Lock()
33 | r.pushers[id] = p
34 | r.Unlock()
35 | }
36 |
37 | func (r *pusherMap) get(id string) (*pusher, bool) {
38 | r.RLock()
39 | p, ok := r.pushers[id]
40 | r.RUnlock()
41 | return p, ok
42 | }
43 |
44 | func (r *pusherMap) remove(id string) {
45 | r.Lock()
46 | delete(r.pushers, id)
47 | r.Unlock()
48 | }
49 |
--------------------------------------------------------------------------------
/lib/server/response_buffer.go:
--------------------------------------------------------------------------------
1 | package server
2 |
3 | import (
4 | "bytes"
5 | "io"
6 | "net/http"
7 | )
8 |
9 | type responseBuffer struct {
10 | body *bytes.Buffer
11 | w http.ResponseWriter
12 | }
13 |
14 | func newResponseBuffer(w http.ResponseWriter) responseBuffer {
15 | var buf bytes.Buffer
16 | return responseBuffer{
17 | body: &buf,
18 | w: w,
19 | }
20 | }
21 |
22 | func (b responseBuffer) Header() http.Header {
23 | return b.w.Header()
24 | }
25 |
26 | func (b responseBuffer) WriteHeader(h int) {
27 | b.w.WriteHeader(h)
28 | }
29 |
30 | func (b responseBuffer) Write(bs []byte) (int, error) {
31 | return b.body.Write(bs)
32 | }
33 |
34 | func (b *responseBuffer) Bytes() []byte {
35 | return b.body.Bytes()
36 | }
37 |
38 | func (b *responseBuffer) Flush() {
39 | io.Copy(b.w, bytes.NewReader(b.body.Bytes()))
40 | b.body.Reset()
41 | }
42 |
--------------------------------------------------------------------------------
/lib/server/server.go:
--------------------------------------------------------------------------------
1 | package server
2 |
3 | import (
4 | "encoding/json"
5 | "log"
6 | "net/http"
7 | "net/http/httputil"
8 | "net/url"
9 | "strings"
10 |
11 | "github.com/gabesullice/jq"
12 | "github.com/satori/go.uuid"
13 | )
14 |
15 | func NewProxy(backend *httputil.ReverseProxy) http.Handler {
16 | return &handler{
17 | backend: backend,
18 | pushers: pusherMap{pushers: make(map[string]*pusher)},
19 | }
20 | }
21 |
22 | type handler struct {
23 | pushers pusherMap
24 | backend *httputil.ReverseProxy
25 | }
26 |
27 | func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
28 | isPush := r.Header.Get("X-Push") == "ON"
29 |
30 | if r.Header.Get("Accept") != "application/vnd.api+json" {
31 | h.backend.ServeHTTP(w, r)
32 | return
33 | }
34 |
35 | rb := newResponseBuffer(w)
36 | h.backend.ServeHTTP(rb, r)
37 | defer rb.Flush()
38 |
39 | requestID := r.Header.Get("X-Push-Request-ID")
40 | if requestID == "" {
41 | p, ok := w.(http.Pusher)
42 | if !ok {
43 | log.Println("HTTP/2 is not supported")
44 | } else {
45 | requestID = uuid.NewV4().String()
46 | h.pushers.add(requestID, &pusher{p: p})
47 | defer h.pushers.remove(requestID)
48 | }
49 | }
50 |
51 | if requestID != "" {
52 | if pusher, ok := h.pushers.get(requestID); ok {
53 | ops := parsePushPlease(r.Header.Get("X-Push-Please"))
54 | if len(ops) > 0 {
55 | bs := rb.Bytes()
56 | if pushes := getPushLinks(ops, bs); len(pushes) > 0 {
57 | headers := r.Header
58 | headers.Set("X-Push", "ON")
59 | headers.Set("X-Push-Request-ID", requestID)
60 | opts := &http.PushOptions{Header: headers}
61 | for _, target := range pushes {
62 | pusher.push(target, opts)
63 | }
64 | }
65 | }
66 |
67 | if isPush {
68 | pusher.Done()
69 | } else {
70 | pusher.Wait()
71 | }
72 | }
73 | }
74 | }
75 |
76 | func getPushLinks(ops map[string]jq.Op, b []byte) []string {
77 | var pushes []string
78 | for part, op := range ops {
79 | data, err := op.Apply(b)
80 | if err != nil {
81 | continue
82 | }
83 |
84 | trimmed := strings.TrimSpace(part)
85 | var query string
86 | if strings.Contains(trimmed, "?") {
87 | query = "?" + strings.Split(trimmed, "?")[1]
88 | } else {
89 | query = ""
90 | }
91 |
92 | var links []string
93 | if err := json.Unmarshal(data, &links); err != nil {
94 | var link string
95 | if err := json.Unmarshal(data, &link); err != nil {
96 | continue
97 | }
98 | links = append(links, link)
99 | }
100 |
101 | for _, link := range links {
102 | if url, err := url.Parse(link); err == nil {
103 | pushes = append(pushes, url.RequestURI()+query)
104 | }
105 | }
106 | }
107 | return pushes
108 | }
109 |
110 | func parsePushPlease(please string) map[string]jq.Op {
111 | ops := make(map[string]jq.Op)
112 | for _, part := range strings.Split(please, ";") {
113 | // Invalid paths are simply ignored.
114 | trimmed := strings.TrimSpace(part)
115 | var path string
116 | if strings.Contains(trimmed, "?") {
117 | path = strings.Split(trimmed, "?")[0]
118 | } else {
119 | path = trimmed
120 | }
121 | if op, err := jq.Parse(path); err == nil {
122 | ops[trimmed] = op
123 | }
124 | }
125 | return ops
126 | }
127 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 | *.prof
25 |
26 | # ignore intellij files
27 | .idea
28 | *.iml
29 | *.ipr
30 | *.iws
31 |
32 | # ignore scratch files
33 | sample.json
34 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/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/github.com/gabesullice/jq/README.md:
--------------------------------------------------------------------------------
1 | # jq
2 |
3 | [](https://godoc.org/github.com/savaki/jq)
4 | [](https://snap-ci.com/savaki/jq/branch/master)
5 |
6 | A high performance Golang implementation of the incredibly useful jq command line tool.
7 |
8 | Rather than marshalling json elements into go instances, jq opts to manipulate the json elements as raw []byte. This
9 | is especially useful for apps that need to handle dynamic json data.
10 |
11 | Using jq consists of creation an ```Op``` and then calling ```Apply``` on the ```Op``` to transform one []byte into the
12 | desired []byte. Ops may be chained together to form a transformation chain similar to how the command line jq works.
13 |
14 | ## Installation
15 |
16 | ```
17 | go get github.com/savaki/jq
18 | ```
19 |
20 | ## Example
21 |
22 | ```go
23 | package main
24 |
25 | import (
26 | "fmt"
27 |
28 | "github.com/savaki/jq"
29 | )
30 |
31 | func main() {
32 | op, _ := jq.Parse(".hello") // create an Op
33 | data := []byte(`{"hello":"world"}`) // sample input
34 | value, _ := op.Apply(data) // value == '"world"'
35 | fmt.Println(string(value))
36 | }
37 | ```
38 |
39 | ## Syntax
40 |
41 | The initial goal is to support all the selectors the original jq command line supports.
42 |
43 | | syntax | meaning|
44 | | :--- | :--- |
45 | | . | unchanged input |
46 | | .foo | value at key |
47 | | .foo.bar | value at nested key |
48 | | .[0] | value at specified element of array |
49 | | .[0:1] | array of specified elements of array, inclusive |
50 | | .foo.[0] | nested value |
51 |
52 | ## Examples
53 |
54 | ### Data
55 | ```json
56 | {
57 | "string": "a",
58 | "number": 1.23,
59 | "simple": ["a", "b", "c"],
60 | "mixed": [
61 | "a",
62 | 1,
63 | {"hello":"world"}
64 | ],
65 | "object": {
66 | "first": "joe",
67 | "array": [1,2,3]
68 | }
69 | }
70 | ```
71 |
72 | | syntax | value |
73 | | :--- | :--- |
74 | | .string | "a" |
75 | | .number| 1.23 |
76 | | .simple | ["a", "b", "c"] |
77 | | .simple.[0] | "a" |
78 | | .simple.[0:1] | ["a","b"] |
79 | | .mixed.[1] | 1
80 | | .object.first | "joe" |
81 | | .object.array.[2] | 3 |
82 |
83 | ## Performance
84 |
85 | ```
86 | BenchmarkAny-8 20000000 80.8 ns/op 0 B/op 0 allocs/op
87 | BenchmarkArray-8 20000000 108 ns/op 0 B/op 0 allocs/op
88 | BenchmarkFindIndex-8 10000000 125 ns/op 0 B/op 0 allocs/op
89 | BenchmarkFindKey-8 10000000 125 ns/op 0 B/op 0 allocs/op
90 | BenchmarkFindRange-8 10000000 186 ns/op 16 B/op 1 allocs/op
91 | BenchmarkNumber-8 50000000 28.9 ns/op 0 B/op 0 allocs/op
92 | BenchmarkObject-8 20000000 98.5 ns/op 0 B/op 0 allocs/op
93 | BenchmarkString-8 30000000 40.4 ns/op 0 B/op 0 allocs/op
94 | ```
95 |
96 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/doc.go:
--------------------------------------------------------------------------------
1 | // Package jp offers a highly performant json selector in the style of the jq command line
2 | //
3 | // Usage of this package involves the concept of an Op. An Op is a transformation that converts a []byte into a []byte.
4 | // To get started, use the Parse function to obtain an Op.
5 | //
6 | // op, err := jq.Parse(".key")
7 | //
8 | // This will create an Op that will accept a JSON object in []byte format and return the value associated with "key."
9 | // For example:
10 | //
11 | // in := []byte(`{"key":"value"}`)
12 | // data, _ := op.Apply(in))
13 | // fmt.Println(string(data))
14 | //
15 | // Will print the string "value". The goal is to support all the select operations supported by jq's command line
16 | // namesake.
17 | //
18 | package jq
19 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/op.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 jq
16 |
17 | import (
18 | "bytes"
19 | "strings"
20 |
21 | "github.com/gabesullice/jq/scanner"
22 | )
23 |
24 | // Op defines a single transformation to be applied to a []byte
25 | type Op interface {
26 | Apply([]byte) ([]byte, error)
27 | Iterate([][]byte) ([]byte, error)
28 | }
29 |
30 | // OpFunc provides a convenient func type wrapper on Op
31 | type OpFunc func([]byte) ([]byte, error)
32 |
33 | // Apply executes the transformation defined by OpFunc
34 | func (fn OpFunc) Apply(in []byte) ([]byte, error) {
35 | return fn(in)
36 | }
37 |
38 | func (fn OpFunc) Iterate(in [][]byte) ([]byte, error) {
39 | iterated := make([][]byte, len(in))
40 | var err error
41 | for i, _ := range in {
42 | iterated[i], err = fn(in[i])
43 | if err != nil {
44 | return nil, err
45 | }
46 | }
47 | return bytes.Join(
48 | [][]byte{
49 | []byte("["),
50 | bytes.Join(iterated, []byte(",")),
51 | []byte("]"),
52 | },
53 | []byte(""),
54 | ), nil
55 | }
56 |
57 | func Iterator(fn Op) OpFunc {
58 | return func(in []byte) ([]byte, error) {
59 | split, err := scanner.AsArray(in, 0)
60 | if err != nil {
61 | return nil, err
62 | }
63 | return fn.Iterate(split)
64 | }
65 | }
66 |
67 | // Dot extract the specific key from the map provided; to extract a nested value, use the Dot Op in conjunction with the
68 | // Chain Op
69 | func Dot(key string) OpFunc {
70 | key = strings.TrimSpace(key)
71 | if key == "" {
72 | return func(in []byte) ([]byte, error) { return in, nil }
73 | }
74 |
75 | k := []byte(key)
76 |
77 | return func(in []byte) ([]byte, error) {
78 | return scanner.FindKey(in, 0, k)
79 | }
80 | }
81 |
82 | // Chain executes a series of operations in the order provided
83 | func Chain(filters ...Op) OpFunc {
84 | return func(in []byte) ([]byte, error) {
85 | if filters == nil {
86 | return in, nil
87 | }
88 |
89 | var err error
90 | data := in
91 | for _, filter := range filters {
92 | data, err = filter.Apply(data)
93 | if err != nil {
94 | return nil, err
95 | }
96 | }
97 |
98 | return data, nil
99 | }
100 | }
101 |
102 | // Index extracts a specific element from the array provided
103 | func Index(index int) OpFunc {
104 | return func(in []byte) ([]byte, error) {
105 | return scanner.FindIndex(in, 0, index)
106 | }
107 | }
108 |
109 | // Range extracts a selection of elements from the array provided, inclusive
110 | func Range(from, to int) OpFunc {
111 | return func(in []byte) ([]byte, error) {
112 | return scanner.FindRange(in, 0, from, to)
113 | }
114 | }
115 |
116 | // From extracts all elements from the array provided from the given index onward, inclusive
117 | func From(from int) OpFunc {
118 | return func(in []byte) ([]byte, error) {
119 | return scanner.FindFrom(in, 0, from)
120 | }
121 | }
122 |
123 | // To extracts all elements from the array provided up to the given index, inclusive
124 | func To(to int) OpFunc {
125 | return func(in []byte) ([]byte, error) {
126 | return scanner.FindTo(in, 0, to)
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/op_chain_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 jq_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq"
21 | )
22 |
23 | func BenchmarkChain(t *testing.B) {
24 | op := jq.Chain(jq.Dot("a"), jq.Dot("b"))
25 | data := []byte(`{"a":{"b":"value"}}`)
26 |
27 | for i := 0; i < t.N; i++ {
28 | _, err := op.Apply(data)
29 | if err != nil {
30 | t.FailNow()
31 | return
32 | }
33 | }
34 | }
35 |
36 | func TestChain(t *testing.T) {
37 | testCases := map[string]struct {
38 | In string
39 | Op jq.Op
40 | Expected string
41 | HasError bool
42 | }{
43 | "simple": {
44 | In: `{"hello":"world"}`,
45 | Op: jq.Chain(jq.Dot("hello")),
46 | Expected: `"world"`,
47 | },
48 | "nested": {
49 | In: `{"a":{"b":"world"}}`,
50 | Op: jq.Chain(jq.Dot("a"), jq.Dot("b")),
51 | Expected: `"world"`,
52 | },
53 | }
54 |
55 | for label, tc := range testCases {
56 | t.Run(label, func(t *testing.T) {
57 | data, err := tc.Op.Apply([]byte(tc.In))
58 | if tc.HasError {
59 | if err == nil {
60 | t.FailNow()
61 | }
62 | } else {
63 | if string(data) != tc.Expected {
64 | t.FailNow()
65 | }
66 | if err != nil {
67 | t.FailNow()
68 | }
69 | }
70 | })
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/op_dot_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 jq_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq"
21 | )
22 |
23 | func BenchmarkDot(t *testing.B) {
24 | op := jq.Dot("hello")
25 | data := []byte(`{"hello":"world"}`)
26 |
27 | for i := 0; i < t.N; i++ {
28 | _, err := op.Apply(data)
29 | if err != nil {
30 | t.FailNow()
31 | return
32 | }
33 | }
34 | }
35 |
36 | func TestDot(t *testing.T) {
37 | testCases := map[string]struct {
38 | In string
39 | Key string
40 | Expected string
41 | HasError bool
42 | }{
43 | "simple": {
44 | In: `{"hello":"world"}`,
45 | Key: "hello",
46 | Expected: `"world"`,
47 | },
48 | "key not found": {
49 | In: `{"hello":"world"}`,
50 | Key: "junk",
51 | HasError: true,
52 | },
53 | "unclosed value": {
54 | In: `{"hello":"world`,
55 | Key: "hello",
56 | HasError: true,
57 | },
58 | }
59 |
60 | for label, tc := range testCases {
61 | t.Run(label, func(t *testing.T) {
62 | op := jq.Dot(tc.Key)
63 | data, err := op.Apply([]byte(tc.In))
64 | if tc.HasError {
65 | if err == nil {
66 | t.FailNow()
67 | }
68 | } else {
69 | if string(data) != tc.Expected {
70 | t.FailNow()
71 | }
72 | if err != nil {
73 | t.FailNow()
74 | }
75 | }
76 | })
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/parse.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 jq
16 |
17 | import (
18 | "fmt"
19 | "regexp"
20 | "strconv"
21 | "strings"
22 | )
23 |
24 | var (
25 | reArray = regexp.MustCompile(`^\s*\[\s*(?:(\d+))?\s*(?:(:))?\s*(?:(\d+))?\s*\]\s*$`)
26 | )
27 |
28 | // Must is a convenience method similar to template.Must
29 | func Must(op Op, err error) Op {
30 | if err != nil {
31 | panic(fmt.Errorf("unable to parse selector; %v", err.Error()))
32 | }
33 |
34 | return op
35 | }
36 |
37 | // Parse takes a string representation of a selector and returns the corresponding Op definition
38 | func Parse(selector string) (Op, error) {
39 | return transform(strings.Split(selector, ".")), nil
40 | }
41 |
42 | func transform(segments []string) Op {
43 | ops := make([]Op, 0, len(segments))
44 |
45 | for k, _ := range segments {
46 | key := strings.TrimSpace(segments[k])
47 | if key == "" {
48 | continue
49 | }
50 |
51 | if op, ok := parseArray(key); ok {
52 | if k < len(segments)-1 {
53 | ops = append(ops, Chain(op, Iterator(transform(segments[k+1:]))))
54 | } else {
55 | ops = append(ops, op)
56 | }
57 | break
58 | }
59 |
60 | ops = append(ops, Dot(key))
61 | }
62 |
63 | return Chain(ops...)
64 | }
65 |
66 | func parseArray(key string) (Op, bool) {
67 | match := FindIndices(key)
68 |
69 | if len(match) == 0 {
70 | return nil, false
71 | }
72 |
73 | matches := match[0]
74 |
75 | if matches[1]+matches[2]+matches[3] == "" {
76 | return From(0), true
77 | }
78 |
79 | if matches[2] == "" {
80 | idx, err := strconv.Atoi(matches[1])
81 | if err != nil {
82 | return nil, false
83 | }
84 | return Index(idx), true
85 | }
86 |
87 | if matches[1] == "" {
88 | to, err := strconv.Atoi(matches[3])
89 | if err != nil {
90 | return nil, false
91 | }
92 | return To(to), true
93 | }
94 |
95 | if matches[3] == "" {
96 | from, err := strconv.Atoi(matches[1])
97 | if err != nil {
98 | return nil, false
99 | }
100 | return From(from), true
101 | }
102 |
103 | from, err := strconv.Atoi(matches[1])
104 | if err != nil {
105 | return nil, false
106 | }
107 |
108 | to, err := strconv.Atoi(matches[3])
109 | if err != nil {
110 | return nil, false
111 | }
112 |
113 | return Range(from, to), true
114 | }
115 |
116 | func FindIndices(key string) [][]string {
117 | return reArray.FindAllStringSubmatch(key, -1)
118 | }
119 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/parse_regexp_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 jq
16 |
17 | import (
18 | "testing"
19 | )
20 |
21 | func TestRegexp(t *testing.T) {
22 | testCases := map[string]struct {
23 | In string
24 | From string
25 | To string
26 | }{
27 | "simple": {
28 | In: `[0]`,
29 | From: "0",
30 | },
31 | "range": {
32 | In: `[0:1]`,
33 | From: "0",
34 | To: "1",
35 | },
36 | "space before": {
37 | In: ` [0:1]`,
38 | From: "0",
39 | To: "1",
40 | },
41 | "space after": {
42 | In: `[0:1] `,
43 | From: "0",
44 | To: "1",
45 | },
46 | "space from": {
47 | In: `[ 0 :1] `,
48 | From: "0",
49 | To: "1",
50 | },
51 | "space to": {
52 | In: `[0: 1 ] `,
53 | From: "0",
54 | To: "1",
55 | },
56 | }
57 |
58 | for label, tc := range testCases {
59 | t.Run(label, func(t *testing.T) {
60 | matches := reArray.FindAllStringSubmatch(tc.In, -1)
61 | if len(matches) != 1 {
62 | t.FailNow()
63 | }
64 | if len(matches[0]) != 4 {
65 | t.FailNow()
66 | }
67 | if matches[0][1] != tc.From {
68 | t.FailNow()
69 | }
70 | if matches[0][3] != tc.To {
71 | t.FailNow()
72 | }
73 | })
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/parse_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 jq_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq"
21 | )
22 |
23 | func TestParse(t *testing.T) {
24 | testCases := map[string]struct {
25 | In string
26 | Op string
27 | Expected string
28 | HasError bool
29 | }{
30 | "simple": {
31 | In: `{"hello":"world"}`,
32 | Op: ".hello",
33 | Expected: `"world"`,
34 | },
35 | "nested": {
36 | In: `{"a":{"b":"world"}}`,
37 | Op: ".a.b",
38 | Expected: `"world"`,
39 | },
40 | "index": {
41 | In: `["a","b","c"]`,
42 | Op: ".[1]",
43 | Expected: `"b"`,
44 | },
45 | "range": {
46 | In: `["a","b","c"]`,
47 | Op: ".[1:2]",
48 | Expected: `["b","c"]`,
49 | },
50 | "from": {
51 | In: `["a","b","c","d"]`,
52 | Op: ".[1:]",
53 | Expected: `["b","c","d"]`,
54 | },
55 | "to": {
56 | In: `["a","b","c","d"]`,
57 | Op: ".[:2]",
58 | Expected: `["a","b","c"]`,
59 | },
60 | "all": {
61 | In: `["a","b","c","d"]`,
62 | Op: ".[]",
63 | Expected: `["a","b","c","d"]`,
64 | },
65 | "nested index": {
66 | In: `{"abc":"-","def":["a","b","c"]}`,
67 | Op: ".def.[1]",
68 | Expected: `"b"`,
69 | },
70 | "interated index": {
71 | In: `[{"foo":"bar"},{"foo":"baz"}]`,
72 | Op: ".[].foo",
73 | Expected: `["bar","baz"]`,
74 | },
75 | "nested range": {
76 | In: `{"abc":"-","def":["a","b","c"]}`,
77 | Op: ".def.[1:2]",
78 | Expected: `["b","c"]`,
79 | },
80 | }
81 |
82 | for label, tc := range testCases {
83 | t.Run(label, func(t *testing.T) {
84 | op, err := jq.Parse(tc.Op)
85 | if err != nil {
86 | t.FailNow()
87 | }
88 |
89 | data, err := op.Apply([]byte(tc.In))
90 | if tc.HasError {
91 | if err == nil {
92 | t.FailNow()
93 | }
94 | } else {
95 | if string(data) != tc.Expected {
96 | t.Logf("op: %q", data)
97 | t.FailNow()
98 | }
99 | if err != nil {
100 | t.FailNow()
101 | }
102 | }
103 | })
104 | }
105 | }
106 |
107 | //func TestFindIndices(t *testing.T) {
108 | // testCases := map[string]struct {
109 | // In string
110 | // Expect []string
111 | // }{
112 | // "simple": {
113 | // In: "[0]",
114 | // Expect: []string{"0"},
115 | // },
116 | // "range": {
117 | // In: "[0:1]",
118 | // Expect: []string{"0"},
119 | // },
120 | // "from": {
121 | // In: "[1:]",
122 | // Expect: []string{"0"},
123 | // },
124 | // "to": {
125 | // In: "[:1]",
126 | // Expect: []string{"0"},
127 | // },
128 | // }
129 | // for label, tc := range testCases {
130 | // t.Run(label, func(t *testing.T) {
131 | // matches := jq.FindIndices(tc.In)
132 | // t.Logf("%#v", matches[0])
133 | // if len(matches) == 0 {
134 | // t.Log("no matches")
135 | // t.FailNow()
136 | // }
137 | // if len(matches[0]) != len(tc.Expect) {
138 | // t.Log("count mismatch")
139 | // t.FailNow()
140 | // }
141 | // for k, v := range tc.Expect {
142 | // if v != matches[0][k] {
143 | // t.Log("expected mismatch")
144 | // t.FailNow()
145 | // }
146 | // }
147 | // })
148 | // }
149 | //}
150 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/any.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // Any returns the position of the end of the current element that begins at pos; handles any valid json element
18 | func Any(in []byte, pos int) (int, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return 0, err
22 | }
23 |
24 | switch in[pos] {
25 | case '"':
26 | return String(in, pos)
27 | case '{':
28 | return Object(in, pos)
29 | case '.', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0':
30 | return Number(in, pos)
31 | case '[':
32 | return Array(in, pos)
33 | case 't', 'f':
34 | return Boolean(in, pos)
35 | case 'n':
36 | return Null(in, pos)
37 | default:
38 | max := len(in) - pos
39 | if max > 20 {
40 | max = 20
41 | }
42 |
43 | return 0, opErr{
44 | pos: pos,
45 | msg: "invalid object",
46 | content: string(in[pos : pos+max]),
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/any_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkAny(t *testing.B) {
24 | data := []byte(`"Hello, 世界 - 生日快乐"`)
25 |
26 | for i := 0; i < t.N; i++ {
27 | end, err := scanner.Any(data, 0)
28 | if err != nil {
29 | t.FailNow()
30 | return
31 | }
32 |
33 | if end == 0 {
34 | t.FailNow()
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestAny(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | Out string
44 | }{
45 | "string": {
46 | In: `"hello"`,
47 | Out: `"hello"`,
48 | },
49 | "array": {
50 | In: `["a","b","c"]`,
51 | Out: `["a","b","c"]`,
52 | },
53 | "object": {
54 | In: `{"a":"b"}`,
55 | Out: `{"a":"b"}`,
56 | },
57 | "number": {
58 | In: `1.234e+10`,
59 | Out: `1.234e+10`,
60 | },
61 | }
62 |
63 | for label, tc := range testCases {
64 | t.Run(label, func(t *testing.T) {
65 | end, err := scanner.Any([]byte(tc.In), 0)
66 | if err != nil {
67 | t.FailNow()
68 | }
69 | data := tc.In[0:end]
70 | if string(data) != tc.Out {
71 | t.FailNow()
72 | }
73 | })
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/array.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // Array returns the position of the end of the array that begins at the position specified
18 | func Array(in []byte, pos int) (int, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return 0, err
22 | }
23 |
24 | if v := in[pos]; v != '[' {
25 | return 0, newError(pos, v)
26 | }
27 | pos++
28 |
29 | // clean initial spaces
30 | pos, err = skipSpace(in, pos)
31 | if err != nil {
32 | return 0, err
33 | }
34 |
35 | if in[pos] == ']' {
36 | return pos + 1, nil
37 | }
38 |
39 | for {
40 | // data
41 | pos, err = Any(in, pos)
42 | if err != nil {
43 | return 0, err
44 | }
45 |
46 | pos, err = skipSpace(in, pos)
47 | if err != nil {
48 | return 0, err
49 | }
50 |
51 | switch in[pos] {
52 | case ',':
53 | pos++
54 | case ']':
55 | return pos + 1, nil
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/array_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkArray(t *testing.B) {
24 | data := []byte(`["hello","world"]`)
25 |
26 | for i := 0; i < t.N; i++ {
27 | end, err := scanner.Array(data, 0)
28 | if err != nil {
29 | t.FailNow()
30 | return
31 | }
32 |
33 | if end == 0 {
34 | t.FailNow()
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestArray(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | Out string
44 | HasErr bool
45 | }{
46 | "simple": {
47 | In: `["hello","world"]`,
48 | Out: `["hello","world"]`,
49 | },
50 | "empty": {
51 | In: `[]`,
52 | Out: `[]`,
53 | },
54 | "spaced": {
55 | In: ` [ "hello" , "world" ] `,
56 | Out: ` [ "hello" , "world" ]`,
57 | },
58 | "all types": {
59 | In: ` [ "hello" , 123, {"hello":"world"} ] `,
60 | Out: ` [ "hello" , 123, {"hello":"world"} ]`,
61 | },
62 | }
63 |
64 | for label, tc := range testCases {
65 | t.Run(label, func(t *testing.T) {
66 | end, err := scanner.Array([]byte(tc.In), 0)
67 | if tc.HasErr {
68 | if err == nil {
69 | t.FailNow()
70 | }
71 |
72 | } else {
73 | data := tc.In[0:end]
74 | if string(data) != tc.Out {
75 | t.FailNow()
76 | }
77 | if err != nil {
78 | t.FailNow()
79 | }
80 | }
81 | })
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/as.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // AsArray accepts an []byte encoded json array as an input and returns the array's elements
18 | func AsArray(in []byte, pos int) ([][]byte, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return nil, err
22 | }
23 |
24 | if v := in[pos]; v != '[' {
25 | return nil, newError(pos, v)
26 | }
27 | pos++
28 |
29 | // clean initial spaces
30 | pos, err = skipSpace(in, pos)
31 | if err != nil {
32 | return nil, err
33 | }
34 |
35 | if in[pos] == ']' {
36 | return [][]byte{}, nil
37 | }
38 |
39 | // 1. Count the number of elements in the array
40 |
41 | start := pos
42 |
43 | elements := make([][]byte, 0, 256)
44 | for {
45 | pos, err = skipSpace(in, pos)
46 | if err != nil {
47 | return nil, err
48 | }
49 |
50 | start = pos
51 |
52 | // data
53 | pos, err = Any(in, pos)
54 | if err != nil {
55 | return nil, err
56 | }
57 | elements = append(elements, in[start:pos])
58 |
59 | pos, err = skipSpace(in, pos)
60 | if err != nil {
61 | return nil, err
62 | }
63 |
64 | switch in[pos] {
65 | case ',':
66 | pos++
67 | case ']':
68 | return elements, nil
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/as_array_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "bytes"
19 | "testing"
20 |
21 | "github.com/gabesullice/jq/scanner"
22 | )
23 |
24 | func BenchmarkAsArray(t *testing.B) {
25 | data := []byte(`["hello","world"]`)
26 |
27 | for i := 0; i < t.N; i++ {
28 | out, err := scanner.AsArray(data, 0)
29 | if err != nil {
30 | t.Errorf("expected nil err; got %v", err)
31 | return
32 | }
33 | if v := len(out); v != 2 {
34 | t.Errorf("want %v, got %v", 2, v)
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestAsArray(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | Out []string
44 | HasErr bool
45 | }{
46 | "simple": {
47 | In: `["hello","world"]`,
48 | Out: []string{`"hello"`, `"world"`},
49 | },
50 | "empty": {
51 | In: `[]`,
52 | Out: []string{},
53 | },
54 | "spaced": {
55 | In: ` [ "hello" , "world" ] `,
56 | Out: []string{`"hello"`, `"world"`},
57 | },
58 | "all types": {
59 | In: ` [ "hello" , 123, {"hello":"world"} ] `,
60 | Out: []string{`"hello"`, `123`, `{"hello":"world"}`},
61 | },
62 | }
63 |
64 | for label, tc := range testCases {
65 | t.Run(label, func(t *testing.T) {
66 | out, err := scanner.AsArray([]byte(tc.In), 0)
67 | if tc.HasErr {
68 | if err == nil {
69 | t.FailNow()
70 | }
71 |
72 | } else {
73 | if err != nil {
74 | t.Errorf("expected nil err; got %v", err)
75 | return
76 | }
77 | if len(out) != len(tc.Out) {
78 | t.Errorf("expected output lengths to match; want %v, got %v", len(tc.Out), len(out))
79 | return
80 | }
81 | for index, item := range tc.Out {
82 | if v := out[index]; bytes.Compare(v, []byte(item)) != 0 {
83 | t.Errorf("expected content at index %v to match; want %v, got %v", index, item, string(v))
84 | return
85 | }
86 | }
87 | }
88 | })
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/bool.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | var (
18 | t = []byte("true")
19 | f = []byte("false")
20 | )
21 |
22 | // Boolean matches a boolean at the specified position
23 | func Boolean(in []byte, pos int) (int, error) {
24 | switch in[pos] {
25 | case 't':
26 | return expect(in, pos, t...)
27 | case 'f':
28 | return expect(in, pos, f...)
29 | default:
30 | return 0, errUnexpectedValue
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/doc.go:
--------------------------------------------------------------------------------
1 | // Package scanner provides various utilities for parsing and extracting json data from []byte
2 |
3 | package scanner
4 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/err.go:
--------------------------------------------------------------------------------
1 | package scanner
2 |
3 | type opErr struct {
4 | pos int
5 | msg string
6 | content string
7 | }
8 |
9 | func (o opErr) Error() string {
10 | return o.msg + "; ..." + o.content
11 | }
12 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_from.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // FindTo finds the elements of an array between the specified indexes; inclusive
18 | func FindFrom(in []byte, pos, from int) ([]byte, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return nil, err
22 | }
23 |
24 | if v := in[pos]; v != '[' {
25 | return nil, newError(pos, v)
26 | }
27 | pos++
28 |
29 | idx := 0
30 | itemStart := pos
31 |
32 | for {
33 | pos, err = skipSpace(in, pos)
34 | if err != nil {
35 | return nil, err
36 | }
37 |
38 | if idx == from {
39 | itemStart = pos
40 | }
41 |
42 | // data
43 | pos, err = Any(in, pos)
44 | if err != nil {
45 | return nil, err
46 | }
47 |
48 | pos, err = skipSpace(in, pos)
49 | if err != nil {
50 | return nil, err
51 | }
52 |
53 | switch in[pos] {
54 | case ',':
55 | pos++
56 | case ']':
57 | if idx < from {
58 | return nil, errFromOutOfBounds
59 | }
60 |
61 | data := in[itemStart:pos]
62 | result := make([]byte, 0, len(data)+2)
63 | result = append(result, '[')
64 | result = append(result, data...)
65 | result = append(result, ']')
66 | return result, nil
67 | }
68 |
69 | idx++
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_from_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func TestFindFrom(t *testing.T) {
24 | testCases := map[string]struct {
25 | In string
26 | From int
27 | Expected string
28 | HasErr bool
29 | }{
30 | "all": {
31 | In: `["a","b","c","d","e"]`,
32 | From: 0,
33 | Expected: `["a","b","c","d","e"]`,
34 | },
35 | "last": {
36 | In: `["a","b","c","d","e"]`,
37 | From: 4,
38 | Expected: `["e"]`,
39 | },
40 | "middle": {
41 | In: `["a","b","c","d","e"]`,
42 | From: 2,
43 | Expected: `["c","d","e"]`,
44 | },
45 | "mixed": {
46 | In: `["a",{"hello":"world"},"c","d","e"]`,
47 | From: 0,
48 | Expected: `["a",{"hello":"world"},"c","d","e"]`,
49 | },
50 | "out of bounds": {
51 | In: `["a",{"hello":"world"},"c","d","e"]`,
52 | From: 20,
53 | HasErr: true,
54 | },
55 | }
56 |
57 | for label, tc := range testCases {
58 | t.Run(label, func(t *testing.T) {
59 | data, err := scanner.FindFrom([]byte(tc.In), 0, tc.From)
60 | if tc.HasErr {
61 | if err == nil {
62 | t.FailNow()
63 | }
64 | } else {
65 | if string(data) != tc.Expected {
66 | t.FailNow()
67 | }
68 | if err != nil {
69 | t.FailNow()
70 | }
71 | }
72 | })
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_index.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // FindIndex accepts a JSON array and return the value of the element at the specified index
18 | func FindIndex(in []byte, pos, index int) ([]byte, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return nil, err
22 | }
23 |
24 | if v := in[pos]; v != '[' {
25 | return nil, newError(pos, v)
26 | }
27 | pos++
28 |
29 | idx := 0
30 | for {
31 | pos, err = skipSpace(in, pos)
32 | if err != nil {
33 | return nil, err
34 | }
35 |
36 | itemStart := pos
37 | // data
38 | pos, err = Any(in, pos)
39 | if err != nil {
40 | return nil, err
41 | }
42 | if index == idx {
43 | return in[itemStart:pos], nil
44 | }
45 |
46 | pos, err = skipSpace(in, pos)
47 | if err != nil {
48 | return nil, err
49 | }
50 |
51 | switch in[pos] {
52 | case ',':
53 | pos++
54 | case ']':
55 | return nil, errIndexOutOfBounds
56 | }
57 |
58 | idx++
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_index_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkFindIndex(t *testing.B) {
24 | data := []byte(`["hello","world"]`)
25 |
26 | for i := 0; i < t.N; i++ {
27 | data, err := scanner.FindIndex(data, 0, 1)
28 | if err != nil {
29 | t.FailNow()
30 | return
31 | }
32 |
33 | if string(data) != `"world"` {
34 | t.FailNow()
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestFindIndex(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | Index int
44 | Expected string
45 | HasErr bool
46 | }{
47 | "simple": {
48 | In: `["hello","world"]`,
49 | Index: 1,
50 | Expected: `"world"`,
51 | },
52 | "spaced": {
53 | In: ` [ "hello" , "world" ] `,
54 | Index: 1,
55 | Expected: `"world"`,
56 | },
57 | "all types": {
58 | In: ` [ "hello" , 123, {"hello":"world"} ] `,
59 | Index: 2,
60 | Expected: `{"hello":"world"}`,
61 | },
62 | }
63 |
64 | for label, tc := range testCases {
65 | t.Run(label, func(t *testing.T) {
66 | data, err := scanner.FindIndex([]byte(tc.In), 0, tc.Index)
67 | if tc.HasErr {
68 | if err == nil {
69 | t.FailNow()
70 | }
71 | } else {
72 | if string(data) != tc.Expected {
73 | t.FailNow()
74 | }
75 | if err != nil {
76 | t.FailNow()
77 | }
78 | }
79 | })
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_key.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | import "bytes"
18 |
19 | // FindKey accepts a JSON object and returns the value associated with the key specified
20 | func FindKey(in []byte, pos int, k []byte) ([]byte, error) {
21 | pos, err := skipSpace(in, pos)
22 | if err != nil {
23 | return nil, err
24 | }
25 |
26 | if v := in[pos]; v != '{' {
27 | return nil, newError(pos, v)
28 | }
29 | pos++
30 |
31 | for {
32 | pos, err = skipSpace(in, pos)
33 | if err != nil {
34 | return nil, err
35 | }
36 |
37 | keyStart := pos
38 | // key
39 | pos, err = String(in, pos)
40 | if err != nil {
41 | return nil, err
42 | }
43 | key := in[keyStart+1 : pos-1]
44 | match := bytes.Equal(k, key)
45 |
46 | // leading spaces
47 | pos, err = skipSpace(in, pos)
48 | if err != nil {
49 | return nil, err
50 | }
51 |
52 | // colon
53 | pos, err = expect(in, pos, ':')
54 | if err != nil {
55 | return nil, err
56 | }
57 |
58 | pos, err = skipSpace(in, pos)
59 | if err != nil {
60 | return nil, err
61 | }
62 |
63 | valueStart := pos
64 | // data
65 | pos, err = Any(in, pos)
66 | if err != nil {
67 | return nil, err
68 | }
69 |
70 | if match {
71 | return in[valueStart:pos], nil
72 | }
73 |
74 | pos, err = skipSpace(in, pos)
75 | if err != nil {
76 | return nil, err
77 | }
78 |
79 | switch in[pos] {
80 | case ',':
81 | pos++
82 | case '}':
83 | return nil, errKeyNotFound
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_key_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkFindKey(t *testing.B) {
24 | data := []byte(`{"hello":"world"}`)
25 |
26 | for i := 0; i < t.N; i++ {
27 | out, err := scanner.FindKey(data, 0, []byte("hello"))
28 | if err != nil {
29 | t.FailNow()
30 | return
31 | }
32 |
33 | if string(out) != `"world"` {
34 | t.FailNow()
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestFindKey(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | Key string
44 | Expected string
45 | HasErr bool
46 | }{
47 | "simple": {
48 | In: `{"hello":"world"}`,
49 | Key: "hello",
50 | Expected: `"world"`,
51 | },
52 | "spaced": {
53 | In: ` { "hello" : "world" } `,
54 | Key: "hello",
55 | Expected: `"world"`,
56 | },
57 | }
58 |
59 | for label, tc := range testCases {
60 | t.Run(label, func(t *testing.T) {
61 | data, err := scanner.FindKey([]byte(tc.In), 0, []byte(tc.Key))
62 | if tc.HasErr {
63 | if err == nil {
64 | t.FailNow()
65 | }
66 | } else {
67 | if string(data) != tc.Expected {
68 | t.FailNow()
69 | }
70 | if err != nil {
71 | t.FailNow()
72 | }
73 | }
74 | })
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_range.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // FindRange finds the elements of an array between the specified indexes; inclusive
18 | func FindRange(in []byte, pos, from, to int) ([]byte, error) {
19 | if to < from {
20 | return nil, errToLessThanFrom
21 | }
22 |
23 | pos, err := skipSpace(in, pos)
24 | if err != nil {
25 | return nil, err
26 | }
27 |
28 | if v := in[pos]; v != '[' {
29 | return nil, newError(pos, v)
30 | }
31 | pos++
32 |
33 | idx := 0
34 | itemStart := pos
35 |
36 | for {
37 | pos, err = skipSpace(in, pos)
38 | if err != nil {
39 | return nil, err
40 | }
41 |
42 | if idx == from {
43 | itemStart = pos
44 | }
45 |
46 | // data
47 | pos, err = Any(in, pos)
48 | if err != nil {
49 | return nil, err
50 | }
51 |
52 | if idx == to {
53 | data := in[itemStart:pos]
54 | result := make([]byte, 0, len(data)+2)
55 | result = append(result, '[')
56 | result = append(result, data...)
57 | result = append(result, ']')
58 | return result, nil
59 | }
60 |
61 | pos, err = skipSpace(in, pos)
62 | if err != nil {
63 | return nil, err
64 | }
65 |
66 | switch in[pos] {
67 | case ',':
68 | pos++
69 | case ']':
70 | return nil, errIndexOutOfBounds
71 | }
72 |
73 | idx++
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_range_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkFindRange(t *testing.B) {
24 | data := []byte(`["a","b","c","d","e"]`)
25 |
26 | for i := 0; i < t.N; i++ {
27 | out, err := scanner.FindRange(data, 0, 1, 2)
28 | if err != nil {
29 | t.FailNow()
30 | return
31 | }
32 |
33 | if string(out) != `["b","c"]` {
34 | t.FailNow()
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestFindRange(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | From int
44 | To int
45 | Expected string
46 | HasErr bool
47 | }{
48 | "simple": {
49 | In: `["a","b","c","d","e"]`,
50 | From: 1,
51 | To: 2,
52 | Expected: `["b","c"]`,
53 | },
54 | "single": {
55 | In: `["a","b","c","d","e"]`,
56 | From: 1,
57 | To: 1,
58 | Expected: `["b"]`,
59 | },
60 | "mixed": {
61 | In: `["a",{"hello":"world"},"c","d","e"]`,
62 | From: 1,
63 | To: 1,
64 | Expected: `[{"hello":"world"}]`,
65 | },
66 | "ordering": {
67 | In: `["a",{"hello":"world"},"c","d","e"]`,
68 | From: 1,
69 | To: 0,
70 | HasErr: true,
71 | },
72 | "out of bounds": {
73 | In: `["a",{"hello":"world"},"c","d","e"]`,
74 | From: 1,
75 | To: 20,
76 | HasErr: true,
77 | },
78 | }
79 |
80 | for label, tc := range testCases {
81 | t.Run(label, func(t *testing.T) {
82 | data, err := scanner.FindRange([]byte(tc.In), 0, tc.From, tc.To)
83 | if tc.HasErr {
84 | if err == nil {
85 | t.FailNow()
86 | }
87 | } else {
88 | if string(data) != tc.Expected {
89 | t.FailNow()
90 | }
91 | if err != nil {
92 | t.FailNow()
93 | }
94 | }
95 | })
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_to.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // FindTo finds the elements of an array between the specified indexes; inclusive
18 | func FindTo(in []byte, pos, to int) ([]byte, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return nil, err
22 | }
23 |
24 | if v := in[pos]; v != '[' {
25 | return nil, newError(pos, v)
26 | }
27 | pos++
28 |
29 | idx := 0
30 | itemStart := pos
31 |
32 | for {
33 | pos, err = skipSpace(in, pos)
34 | if err != nil {
35 | return nil, err
36 | }
37 |
38 | // data
39 | pos, err = Any(in, pos)
40 | if err != nil {
41 | return nil, err
42 | }
43 |
44 | if idx == to {
45 | data := in[itemStart:pos]
46 | result := make([]byte, 0, len(data)+2)
47 | result = append(result, '[')
48 | result = append(result, data...)
49 | result = append(result, ']')
50 | return result, nil
51 | }
52 |
53 | pos, err = skipSpace(in, pos)
54 | if err != nil {
55 | return nil, err
56 | }
57 |
58 | switch in[pos] {
59 | case ',':
60 | pos++
61 | case ']':
62 | return nil, errIndexOutOfBounds
63 | }
64 |
65 | idx++
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/find_to_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func TestFindTo(t *testing.T) {
24 | testCases := map[string]struct {
25 | In string
26 | To int
27 | Expected string
28 | HasErr bool
29 | }{
30 | "first": {
31 | In: `["a","b","c","d","e"]`,
32 | To: 0,
33 | Expected: `["a"]`,
34 | },
35 | "second": {
36 | In: `["a","b","c","d","e"]`,
37 | To: 1,
38 | Expected: `["a","b"]`,
39 | },
40 | "mixed": {
41 | In: `["a",{"hello":"world"},"c","d","e"]`,
42 | To: 1,
43 | Expected: `["a",{"hello":"world"}]`,
44 | },
45 | "negative": {
46 | In: `["a",{"hello":"world"},"c","d","e"]`,
47 | To: -1,
48 | HasErr: true,
49 | },
50 | "out of bounds": {
51 | In: `["a",{"hello":"world"},"c","d","e"]`,
52 | To: 20,
53 | HasErr: true,
54 | },
55 | }
56 |
57 | for label, tc := range testCases {
58 | t.Run(label, func(t *testing.T) {
59 | data, err := scanner.FindTo([]byte(tc.In), 0, tc.To)
60 | if tc.HasErr {
61 | if err == nil {
62 | t.FailNow()
63 | }
64 | } else {
65 | if string(data) != tc.Expected {
66 | t.FailNow()
67 | }
68 | if err != nil {
69 | t.FailNow()
70 | }
71 | }
72 | })
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/null.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | var (
18 | n = []byte("null")
19 | )
20 |
21 | // Null verifies the contents of bytes provided is a null starting as pos
22 | func Null(in []byte, pos int) (int, error) {
23 | switch in[pos] {
24 | case 'n':
25 | return expect(in, pos, n...)
26 | return pos + 4, nil
27 | default:
28 | return 0, errUnexpectedValue
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/null_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkNull(t *testing.B) {
24 | data := []byte("null")
25 | for i := 0; i < t.N; i++ {
26 | pos, err := scanner.Null(data, 0)
27 | if err != nil {
28 | t.FailNow()
29 | }
30 | if pos != 4 {
31 | t.FailNow()
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/number.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // Number returns the end position of the number that begins at the specified pos
18 | func Number(in []byte, pos int) (int, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return 0, err
22 | }
23 |
24 | max := len(in)
25 | for {
26 | v := in[pos]
27 | switch v {
28 | case '-', '+', '.', 'e', 'E', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0':
29 | pos++
30 | default:
31 | return pos, nil
32 | }
33 |
34 | if pos >= max {
35 | return pos, nil
36 | }
37 | }
38 |
39 | return pos, nil
40 | }
41 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/number_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkNumber(t *testing.B) {
24 | data := []byte(`12.34e+9`)
25 |
26 | for i := 0; i < t.N; i++ {
27 | end, err := scanner.Number(data, 0)
28 | if err != nil {
29 | t.FailNow()
30 | return
31 | }
32 |
33 | if end == 0 {
34 | t.FailNow()
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestNumber(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | Out string
44 | HasErr bool
45 | }{
46 | "simple": {
47 | In: `1234`,
48 | Out: `1234`,
49 | },
50 | "decimal": {
51 | In: `1.234`,
52 | Out: `1.234`,
53 | },
54 | "spaced": {
55 | In: ` 1.234 `,
56 | Out: ` 1.234`,
57 | },
58 | "kitchen-sink": {
59 | In: ` +-123.25eE10 `,
60 | Out: ` +-123.25eE10`,
61 | },
62 | }
63 |
64 | for label, tc := range testCases {
65 | t.Run(label, func(t *testing.T) {
66 | end, err := scanner.Number([]byte(tc.In), 0)
67 | if tc.HasErr {
68 | if err == nil {
69 | t.FailNow()
70 | }
71 | } else {
72 | data := tc.In[0:end]
73 | if string(data) != tc.Out {
74 | t.FailNow()
75 | }
76 | if err != nil {
77 | t.FailNow()
78 | }
79 | }
80 | })
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/object.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | // Object returns the position of the end of the object that begins at the specified pos
18 | func Object(in []byte, pos int) (int, error) {
19 | pos, err := skipSpace(in, pos)
20 | if err != nil {
21 | return 0, err
22 | }
23 |
24 | if v := in[pos]; v != '{' {
25 | return 0, newError(pos, v)
26 | }
27 | pos++
28 |
29 | // clean initial spaces
30 | pos, err = skipSpace(in, pos)
31 | if err != nil {
32 | return 0, err
33 | }
34 |
35 | if in[pos] == '}' {
36 | return pos + 1, nil
37 | }
38 |
39 | for {
40 | // key
41 | pos, err = String(in, pos)
42 | if err != nil {
43 | return 0, err
44 | }
45 |
46 | // leading spaces
47 | pos, err = skipSpace(in, pos)
48 | if err != nil {
49 | return 0, err
50 | }
51 |
52 | // colon
53 | pos, err = expect(in, pos, ':')
54 | if err != nil {
55 | return 0, err
56 | }
57 |
58 | // data
59 | pos, err = Any(in, pos)
60 | if err != nil {
61 | return 0, err
62 | }
63 |
64 | pos, err = skipSpace(in, pos)
65 | if err != nil {
66 | return 0, err
67 | }
68 |
69 | switch in[pos] {
70 | case ',':
71 | pos++
72 | case '}':
73 | return pos + 1, nil
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/object_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 |
20 | "github.com/gabesullice/jq/scanner"
21 | )
22 |
23 | func BenchmarkObject(t *testing.B) {
24 | data := []byte(`{"hello":"world"}`)
25 |
26 | for i := 0; i < t.N; i++ {
27 | end, err := scanner.Object(data, 0)
28 | if err != nil {
29 | t.FailNow()
30 | return
31 | }
32 |
33 | if end == 0 {
34 | t.FailNow()
35 | return
36 | }
37 | }
38 | }
39 |
40 | func TestObject(t *testing.T) {
41 | testCases := map[string]struct {
42 | In string
43 | Out string
44 | HasErr bool
45 | }{
46 | "simple": {
47 | In: `{"hello":"world"}`,
48 | Out: `{"hello":"world"}`,
49 | },
50 | "empty": {
51 | In: `{}`,
52 | Out: `{}`,
53 | },
54 | "spaced": {
55 | In: ` { "hello" : "world" } `,
56 | Out: ` { "hello" : "world" }`,
57 | },
58 | }
59 |
60 | for label, tc := range testCases {
61 | t.Run(label, func(t *testing.T) {
62 | end, err := scanner.Object([]byte(tc.In), 0)
63 | if tc.HasErr {
64 | if err == nil {
65 | t.FailNow()
66 | }
67 | } else {
68 | data := tc.In[0:end]
69 | if string(data) != tc.Out {
70 | t.FailNow()
71 | }
72 | if err != nil {
73 | t.FailNow()
74 | }
75 | }
76 | })
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/string.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | import "errors"
18 |
19 | // String returns the position of the string that begins at the specified pos
20 | func String(in []byte, pos int) (int, error) {
21 | pos, err := skipSpace(in, pos)
22 | if err != nil {
23 | return 0, err
24 | }
25 |
26 | max := len(in)
27 |
28 | if v := in[pos]; v != '"' {
29 | return 0, newError(pos, v)
30 | }
31 | pos++
32 |
33 | for {
34 | switch in[pos] {
35 | case '\\':
36 | if in[pos+1] == '"' {
37 | pos++
38 | }
39 | case '"':
40 | return pos + 1, nil
41 | }
42 | pos++
43 |
44 | if pos >= max {
45 | break
46 | }
47 | }
48 |
49 | return 0, errors.New("unclosed string")
50 | }
51 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/string_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner_test
16 |
17 | import (
18 | "testing"
19 | "unicode/utf8"
20 |
21 | "github.com/gabesullice/jq/scanner"
22 | )
23 |
24 | func BenchmarkString(t *testing.B) {
25 | data := []byte(`"hello world"`)
26 |
27 | for i := 0; i < t.N; i++ {
28 | end, err := scanner.String(data, 0)
29 | if err != nil {
30 | t.FailNow()
31 | return
32 | }
33 |
34 | if end == 0 {
35 | t.FailNow()
36 | return
37 | }
38 | }
39 | }
40 |
41 | func TestString(t *testing.T) {
42 | testCases := map[string]struct {
43 | In string
44 | Out string
45 | HasErr bool
46 | }{
47 | "simple": {
48 | In: `"hello"`,
49 | Out: `"hello"`,
50 | },
51 | "array": {
52 | In: `"hello", "world"`,
53 | Out: `"hello"`,
54 | },
55 | "escaped": {
56 | In: `"hello\"\"world"`,
57 | Out: `"hello\"\"world"`,
58 | },
59 | "unclosed": {
60 | In: `"hello`,
61 | HasErr: true,
62 | },
63 | "unclosed escape": {
64 | In: `"hello\"`,
65 | HasErr: true,
66 | },
67 | "utf8": {
68 | In: `"生日快乐"`,
69 | Out: `"生日快乐"`,
70 | },
71 | }
72 |
73 | for label, tc := range testCases {
74 | t.Run(label, func(t *testing.T) {
75 | end, err := scanner.String([]byte(tc.In), 0)
76 | if tc.HasErr {
77 | if err == nil {
78 | t.FailNow()
79 | }
80 | } else {
81 | data := tc.In[0:end]
82 | if string(data) != tc.Out {
83 | t.FailNow()
84 | }
85 | if err != nil {
86 | t.FailNow()
87 | }
88 | }
89 | })
90 | }
91 | }
92 |
93 | func TestDecode(t *testing.T) {
94 | v := ""
95 | _, size := utf8.DecodeRune([]byte(v))
96 | if size != 0 {
97 | t.FailNow()
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/util.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | import (
18 | "errors"
19 | "fmt"
20 | "unicode"
21 | "unicode/utf8"
22 | )
23 |
24 | var (
25 | errUnexpectedEOF = errors.New("unexpected EOF")
26 | errKeyNotFound = errors.New("key not found")
27 | errIndexOutOfBounds = errors.New("index out of bounds")
28 | errToLessThanFrom = errors.New("to index less than from index")
29 | errFromOutOfBounds = errors.New("from index out of bounds")
30 | errUnexpectedValue = errors.New("unexpected value")
31 | )
32 |
33 | func skipSpace(in []byte, pos int) (int, error) {
34 | for {
35 | r, size := utf8.DecodeRune(in[pos:])
36 | if size == 0 {
37 | return 0, errUnexpectedEOF
38 | }
39 | if !unicode.IsSpace(r) {
40 | break
41 | }
42 | pos += size
43 | }
44 |
45 | return pos, nil
46 | }
47 |
48 | func expect(in []byte, pos int, content ...byte) (int, error) {
49 | if pos+len(content) > len(in) {
50 | return 0, errUnexpectedEOF
51 | }
52 |
53 | for _, b := range content {
54 | if v := in[pos]; v != b {
55 | return 0, errUnexpectedValue
56 | }
57 | pos++
58 | }
59 |
60 | return pos, nil
61 | }
62 |
63 | func newError(pos int, b byte) error {
64 | return fmt.Errorf("invalid character at position, %v; %v", pos, string([]byte{b}))
65 | }
66 |
--------------------------------------------------------------------------------
/vendor/github.com/gabesullice/jq/scanner/util_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2016 Matt Ho
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 scanner
16 |
17 | import (
18 | "fmt"
19 | "testing"
20 | )
21 |
22 | func TestSkipSpace(t *testing.T) {
23 | content := []byte(" \t\n\r!")
24 | end, err := skipSpace(content, 0)
25 | if err != nil {
26 | t.FailNow()
27 | }
28 | if end+1 != len(content) {
29 | t.FailNow()
30 | }
31 | }
32 |
33 | func TestExpect(t *testing.T) {
34 | testCases := map[string]struct {
35 | In string
36 | Expected string
37 | HasError bool
38 | }{
39 | "simple": {
40 | In: "abc",
41 | Expected: "abc",
42 | },
43 | "extra": {
44 | In: "abcdef",
45 | Expected: "abc",
46 | },
47 | "no match": {
48 | In: "abc",
49 | Expected: "def",
50 | HasError: true,
51 | },
52 | "unexpected EOF": {
53 | In: "ab",
54 | Expected: "abc",
55 | HasError: true,
56 | },
57 | }
58 |
59 | for label, tc := range testCases {
60 | t.Run(label, func(t *testing.T) {
61 | pos, err := expect([]byte(tc.In), 0, []byte(tc.Expected)...)
62 | if tc.HasError {
63 | if err == nil {
64 | t.FailNow()
65 | }
66 |
67 | } else {
68 | if err != nil {
69 | fmt.Println(err)
70 | t.FailNow()
71 | }
72 | if pos != len([]byte(tc.Expected)) {
73 | t.FailNow()
74 | }
75 |
76 | }
77 | })
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 | sudo: false
3 | go:
4 | - 1.2
5 | - 1.3
6 | - 1.4
7 | - 1.5
8 | - 1.6
9 | - 1.7
10 | - 1.8
11 | - 1.9
12 | - tip
13 | matrix:
14 | allow_failures:
15 | - go: tip
16 | fast_finish: true
17 | before_install:
18 | - go get github.com/mattn/goveralls
19 | - go get golang.org/x/tools/cmd/cover
20 | script:
21 | - $HOME/gopath/bin/goveralls -service=travis-ci
22 | notifications:
23 | email: false
24 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2013-2018 by Maxim Bublis
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/README.md:
--------------------------------------------------------------------------------
1 | # UUID package for Go language
2 |
3 | [](https://travis-ci.org/satori/go.uuid)
4 | [](https://coveralls.io/github/satori/go.uuid)
5 | [](http://godoc.org/github.com/satori/go.uuid)
6 |
7 | This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs.
8 |
9 | With 100% test coverage and benchmarks out of box.
10 |
11 | Supported versions:
12 | * Version 1, based on timestamp and MAC address (RFC 4122)
13 | * Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1)
14 | * Version 3, based on MD5 hashing (RFC 4122)
15 | * Version 4, based on random numbers (RFC 4122)
16 | * Version 5, based on SHA-1 hashing (RFC 4122)
17 |
18 | ## Installation
19 |
20 | Use the `go` command:
21 |
22 | $ go get github.com/satori/go.uuid
23 |
24 | ## Requirements
25 |
26 | UUID package requires Go >= 1.2.
27 |
28 | ## Example
29 |
30 | ```go
31 | package main
32 |
33 | import (
34 | "fmt"
35 | "github.com/satori/go.uuid"
36 | )
37 |
38 | func main() {
39 | // Creating UUID Version 4
40 | u1 := uuid.NewV4()
41 | fmt.Printf("UUIDv4: %s\n", u1)
42 |
43 | // Parsing UUID from string input
44 | u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
45 | if err != nil {
46 | fmt.Printf("Something gone wrong: %s", err)
47 | }
48 | fmt.Printf("Successfully parsed: %s", u2)
49 | }
50 | ```
51 |
52 | ## Documentation
53 |
54 | [Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project.
55 |
56 | ## Links
57 | * [RFC 4122](http://tools.ietf.org/html/rfc4122)
58 | * [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01)
59 |
60 | ## Copyright
61 |
62 | Copyright (C) 2013-2018 by Maxim Bublis .
63 |
64 | UUID package released under MIT License.
65 | See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details.
66 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/codec.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | package uuid
23 |
24 | import (
25 | "bytes"
26 | "encoding/hex"
27 | "fmt"
28 | )
29 |
30 | // FromBytes returns UUID converted from raw byte slice input.
31 | // It will return error if the slice isn't 16 bytes long.
32 | func FromBytes(input []byte) (u UUID, err error) {
33 | err = u.UnmarshalBinary(input)
34 | return
35 | }
36 |
37 | // FromBytesOrNil returns UUID converted from raw byte slice input.
38 | // Same behavior as FromBytes, but returns a Nil UUID on error.
39 | func FromBytesOrNil(input []byte) UUID {
40 | uuid, err := FromBytes(input)
41 | if err != nil {
42 | return Nil
43 | }
44 | return uuid
45 | }
46 |
47 | // FromString returns UUID parsed from string input.
48 | // Input is expected in a form accepted by UnmarshalText.
49 | func FromString(input string) (u UUID, err error) {
50 | err = u.UnmarshalText([]byte(input))
51 | return
52 | }
53 |
54 | // FromStringOrNil returns UUID parsed from string input.
55 | // Same behavior as FromString, but returns a Nil UUID on error.
56 | func FromStringOrNil(input string) UUID {
57 | uuid, err := FromString(input)
58 | if err != nil {
59 | return Nil
60 | }
61 | return uuid
62 | }
63 |
64 | // MarshalText implements the encoding.TextMarshaler interface.
65 | // The encoding is the same as returned by String.
66 | func (u UUID) MarshalText() (text []byte, err error) {
67 | text = []byte(u.String())
68 | return
69 | }
70 |
71 | // UnmarshalText implements the encoding.TextUnmarshaler interface.
72 | // Following formats are supported:
73 | // "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
74 | // "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
75 | // "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
76 | // "6ba7b8109dad11d180b400c04fd430c8"
77 | // ABNF for supported UUID text representation follows:
78 | // uuid := canonical | hashlike | braced | urn
79 | // plain := canonical | hashlike
80 | // canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
81 | // hashlike := 12hexoct
82 | // braced := '{' plain '}'
83 | // urn := URN ':' UUID-NID ':' plain
84 | // URN := 'urn'
85 | // UUID-NID := 'uuid'
86 | // 12hexoct := 6hexoct 6hexoct
87 | // 6hexoct := 4hexoct 2hexoct
88 | // 4hexoct := 2hexoct 2hexoct
89 | // 2hexoct := hexoct hexoct
90 | // hexoct := hexdig hexdig
91 | // hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
92 | // 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
93 | // 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
94 | func (u *UUID) UnmarshalText(text []byte) (err error) {
95 | switch len(text) {
96 | case 32:
97 | return u.decodeHashLike(text)
98 | case 36:
99 | return u.decodeCanonical(text)
100 | case 38:
101 | return u.decodeBraced(text)
102 | case 41:
103 | fallthrough
104 | case 45:
105 | return u.decodeURN(text)
106 | default:
107 | return fmt.Errorf("uuid: incorrect UUID length: %s", text)
108 | }
109 | }
110 |
111 | // decodeCanonical decodes UUID string in format
112 | // "6ba7b810-9dad-11d1-80b4-00c04fd430c8".
113 | func (u *UUID) decodeCanonical(t []byte) (err error) {
114 | if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' {
115 | return fmt.Errorf("uuid: incorrect UUID format %s", t)
116 | }
117 |
118 | src := t[:]
119 | dst := u[:]
120 |
121 | for i, byteGroup := range byteGroups {
122 | if i > 0 {
123 | src = src[1:] // skip dash
124 | }
125 | _, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup])
126 | if err != nil {
127 | return
128 | }
129 | src = src[byteGroup:]
130 | dst = dst[byteGroup/2:]
131 | }
132 |
133 | return
134 | }
135 |
136 | // decodeHashLike decodes UUID string in format
137 | // "6ba7b8109dad11d180b400c04fd430c8".
138 | func (u *UUID) decodeHashLike(t []byte) (err error) {
139 | src := t[:]
140 | dst := u[:]
141 |
142 | if _, err = hex.Decode(dst, src); err != nil {
143 | return err
144 | }
145 | return
146 | }
147 |
148 | // decodeBraced decodes UUID string in format
149 | // "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format
150 | // "{6ba7b8109dad11d180b400c04fd430c8}".
151 | func (u *UUID) decodeBraced(t []byte) (err error) {
152 | l := len(t)
153 |
154 | if t[0] != '{' || t[l-1] != '}' {
155 | return fmt.Errorf("uuid: incorrect UUID format %s", t)
156 | }
157 |
158 | return u.decodePlain(t[1 : l-1])
159 | }
160 |
161 | // decodeURN decodes UUID string in format
162 | // "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format
163 | // "urn:uuid:6ba7b8109dad11d180b400c04fd430c8".
164 | func (u *UUID) decodeURN(t []byte) (err error) {
165 | total := len(t)
166 |
167 | urn_uuid_prefix := t[:9]
168 |
169 | if !bytes.Equal(urn_uuid_prefix, urnPrefix) {
170 | return fmt.Errorf("uuid: incorrect UUID format: %s", t)
171 | }
172 |
173 | return u.decodePlain(t[9:total])
174 | }
175 |
176 | // decodePlain decodes UUID string in canonical format
177 | // "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format
178 | // "6ba7b8109dad11d180b400c04fd430c8".
179 | func (u *UUID) decodePlain(t []byte) (err error) {
180 | switch len(t) {
181 | case 32:
182 | return u.decodeHashLike(t)
183 | case 36:
184 | return u.decodeCanonical(t)
185 | default:
186 | return fmt.Errorf("uuid: incorrrect UUID length: %s", t)
187 | }
188 | }
189 |
190 | // MarshalBinary implements the encoding.BinaryMarshaler interface.
191 | func (u UUID) MarshalBinary() (data []byte, err error) {
192 | data = u.Bytes()
193 | return
194 | }
195 |
196 | // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
197 | // It will return error if the slice isn't 16 bytes long.
198 | func (u *UUID) UnmarshalBinary(data []byte) (err error) {
199 | if len(data) != Size {
200 | err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
201 | return
202 | }
203 | copy(u[:], data)
204 |
205 | return
206 | }
207 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/codec_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | package uuid
23 |
24 | import (
25 | "bytes"
26 |
27 | . "gopkg.in/check.v1"
28 | )
29 |
30 | type codecTestSuite struct{}
31 |
32 | var _ = Suite(&codecTestSuite{})
33 |
34 | func (s *codecTestSuite) TestFromBytes(c *C) {
35 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
36 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
37 |
38 | u1, err := FromBytes(b1)
39 | c.Assert(err, IsNil)
40 | c.Assert(u1, Equals, u)
41 |
42 | b2 := []byte{}
43 | _, err = FromBytes(b2)
44 | c.Assert(err, NotNil)
45 | }
46 |
47 | func (s *codecTestSuite) BenchmarkFromBytes(c *C) {
48 | bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
49 | for i := 0; i < c.N; i++ {
50 | FromBytes(bytes)
51 | }
52 | }
53 |
54 | func (s *codecTestSuite) TestMarshalBinary(c *C) {
55 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
56 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
57 |
58 | b2, err := u.MarshalBinary()
59 | c.Assert(err, IsNil)
60 | c.Assert(bytes.Equal(b1, b2), Equals, true)
61 | }
62 |
63 | func (s *codecTestSuite) BenchmarkMarshalBinary(c *C) {
64 | u := NewV4()
65 | for i := 0; i < c.N; i++ {
66 | u.MarshalBinary()
67 | }
68 | }
69 |
70 | func (s *codecTestSuite) TestUnmarshalBinary(c *C) {
71 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
72 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
73 |
74 | u1 := UUID{}
75 | err := u1.UnmarshalBinary(b1)
76 | c.Assert(err, IsNil)
77 | c.Assert(u1, Equals, u)
78 |
79 | b2 := []byte{}
80 | u2 := UUID{}
81 | err = u2.UnmarshalBinary(b2)
82 | c.Assert(err, NotNil)
83 | }
84 |
85 | func (s *codecTestSuite) TestFromString(c *C) {
86 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
87 |
88 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
89 | s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}"
90 | s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
91 | s4 := "6ba7b8109dad11d180b400c04fd430c8"
92 | s5 := "urn:uuid:6ba7b8109dad11d180b400c04fd430c8"
93 |
94 | _, err := FromString("")
95 | c.Assert(err, NotNil)
96 |
97 | u1, err := FromString(s1)
98 | c.Assert(err, IsNil)
99 | c.Assert(u1, Equals, u)
100 |
101 | u2, err := FromString(s2)
102 | c.Assert(err, IsNil)
103 | c.Assert(u2, Equals, u)
104 |
105 | u3, err := FromString(s3)
106 | c.Assert(err, IsNil)
107 | c.Assert(u3, Equals, u)
108 |
109 | u4, err := FromString(s4)
110 | c.Assert(err, IsNil)
111 | c.Assert(u4, Equals, u)
112 |
113 | u5, err := FromString(s5)
114 | c.Assert(err, IsNil)
115 | c.Assert(u5, Equals, u)
116 | }
117 |
118 | func (s *codecTestSuite) BenchmarkFromString(c *C) {
119 | str := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
120 | for i := 0; i < c.N; i++ {
121 | FromString(str)
122 | }
123 | }
124 |
125 | func (s *codecTestSuite) BenchmarkFromStringUrn(c *C) {
126 | str := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
127 | for i := 0; i < c.N; i++ {
128 | FromString(str)
129 | }
130 | }
131 |
132 | func (s *codecTestSuite) BenchmarkFromStringWithBrackets(c *C) {
133 | str := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}"
134 | for i := 0; i < c.N; i++ {
135 | FromString(str)
136 | }
137 | }
138 |
139 | func (s *codecTestSuite) TestFromStringShort(c *C) {
140 | // Invalid 35-character UUID string
141 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c"
142 |
143 | for i := len(s1); i >= 0; i-- {
144 | _, err := FromString(s1[:i])
145 | c.Assert(err, NotNil)
146 | }
147 | }
148 |
149 | func (s *codecTestSuite) TestFromStringLong(c *C) {
150 | // Invalid 37+ character UUID string
151 | strings := []string{
152 | "6ba7b810-9dad-11d1-80b4-00c04fd430c8=",
153 | "6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
154 | "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f",
155 | "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8",
156 | }
157 |
158 | for _, str := range strings {
159 | _, err := FromString(str)
160 | c.Assert(err, NotNil)
161 | }
162 | }
163 |
164 | func (s *codecTestSuite) TestFromStringInvalid(c *C) {
165 | // Invalid UUID string formats
166 | strings := []string{
167 | "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8",
168 | "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
169 | "uuid:urn:6ba7b810-9dad-11d1-80b4-00c04fd430c8",
170 | "uuid:urn:6ba7b8109dad11d180b400c04fd430c8",
171 | "6ba7b8109-dad-11d1-80b4-00c04fd430c8",
172 | "6ba7b810-9dad1-1d1-80b4-00c04fd430c8",
173 | "6ba7b810-9dad-11d18-0b4-00c04fd430c8",
174 | "6ba7b810-9dad-11d1-80b40-0c04fd430c8",
175 | "6ba7b810+9dad+11d1+80b4+00c04fd430c8",
176 | "(6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
177 | "{6ba7b810-9dad-11d1-80b4-00c04fd430c8>",
178 | "zba7b810-9dad-11d1-80b4-00c04fd430c8",
179 | "6ba7b810-9dad11d180b400c04fd430c8",
180 | "6ba7b8109dad-11d180b400c04fd430c8",
181 | "6ba7b8109dad11d1-80b400c04fd430c8",
182 | "6ba7b8109dad11d180b4-00c04fd430c8",
183 | }
184 |
185 | for _, str := range strings {
186 | _, err := FromString(str)
187 | c.Assert(err, NotNil)
188 | }
189 | }
190 |
191 | func (s *codecTestSuite) TestFromStringOrNil(c *C) {
192 | u := FromStringOrNil("")
193 | c.Assert(u, Equals, Nil)
194 | }
195 |
196 | func (s *codecTestSuite) TestFromBytesOrNil(c *C) {
197 | b := []byte{}
198 | u := FromBytesOrNil(b)
199 | c.Assert(u, Equals, Nil)
200 | }
201 |
202 | func (s *codecTestSuite) TestMarshalText(c *C) {
203 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
204 | b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
205 |
206 | b2, err := u.MarshalText()
207 | c.Assert(err, IsNil)
208 | c.Assert(bytes.Equal(b1, b2), Equals, true)
209 | }
210 |
211 | func (s *codecTestSuite) BenchmarkMarshalText(c *C) {
212 | u := NewV4()
213 | for i := 0; i < c.N; i++ {
214 | u.MarshalText()
215 | }
216 | }
217 |
218 | func (s *codecTestSuite) TestUnmarshalText(c *C) {
219 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
220 | b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
221 |
222 | u1 := UUID{}
223 | err := u1.UnmarshalText(b1)
224 | c.Assert(err, IsNil)
225 | c.Assert(u1, Equals, u)
226 |
227 | b2 := []byte("")
228 | u2 := UUID{}
229 | err = u2.UnmarshalText(b2)
230 | c.Assert(err, NotNil)
231 | }
232 |
233 | func (s *codecTestSuite) BenchmarkUnmarshalText(c *C) {
234 | bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
235 | u := UUID{}
236 | for i := 0; i < c.N; i++ {
237 | u.UnmarshalText(bytes)
238 | }
239 | }
240 |
241 | var sink string
242 |
243 | func (s *codecTestSuite) BenchmarkMarshalToString(c *C) {
244 | u := NewV4()
245 | for i := 0; i < c.N; i++ {
246 | sink = u.String()
247 | }
248 | }
249 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/generator.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | package uuid
23 |
24 | import (
25 | "crypto/md5"
26 | "crypto/rand"
27 | "crypto/sha1"
28 | "encoding/binary"
29 | "hash"
30 | "net"
31 | "os"
32 | "sync"
33 | "time"
34 | )
35 |
36 | // Difference in 100-nanosecond intervals between
37 | // UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
38 | const epochStart = 122192928000000000
39 |
40 | var (
41 | global = newDefaultGenerator()
42 |
43 | epochFunc = unixTimeFunc
44 | posixUID = uint32(os.Getuid())
45 | posixGID = uint32(os.Getgid())
46 | )
47 |
48 | // NewV1 returns UUID based on current timestamp and MAC address.
49 | func NewV1() UUID {
50 | return global.NewV1()
51 | }
52 |
53 | // NewV2 returns DCE Security UUID based on POSIX UID/GID.
54 | func NewV2(domain byte) UUID {
55 | return global.NewV2(domain)
56 | }
57 |
58 | // NewV3 returns UUID based on MD5 hash of namespace UUID and name.
59 | func NewV3(ns UUID, name string) UUID {
60 | return global.NewV3(ns, name)
61 | }
62 |
63 | // NewV4 returns random generated UUID.
64 | func NewV4() UUID {
65 | return global.NewV4()
66 | }
67 |
68 | // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
69 | func NewV5(ns UUID, name string) UUID {
70 | return global.NewV5(ns, name)
71 | }
72 |
73 | // Generator provides interface for generating UUIDs.
74 | type Generator interface {
75 | NewV1() UUID
76 | NewV2(domain byte) UUID
77 | NewV3(ns UUID, name string) UUID
78 | NewV4() UUID
79 | NewV5(ns UUID, name string) UUID
80 | }
81 |
82 | // Default generator implementation.
83 | type generator struct {
84 | storageOnce sync.Once
85 | storageMutex sync.Mutex
86 |
87 | lastTime uint64
88 | clockSequence uint16
89 | hardwareAddr [6]byte
90 | }
91 |
92 | func newDefaultGenerator() Generator {
93 | return &generator{}
94 | }
95 |
96 | // NewV1 returns UUID based on current timestamp and MAC address.
97 | func (g *generator) NewV1() UUID {
98 | u := UUID{}
99 |
100 | timeNow, clockSeq, hardwareAddr := g.getStorage()
101 |
102 | binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
103 | binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
104 | binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
105 | binary.BigEndian.PutUint16(u[8:], clockSeq)
106 |
107 | copy(u[10:], hardwareAddr)
108 |
109 | u.SetVersion(V1)
110 | u.SetVariant(VariantRFC4122)
111 |
112 | return u
113 | }
114 |
115 | // NewV2 returns DCE Security UUID based on POSIX UID/GID.
116 | func (g *generator) NewV2(domain byte) UUID {
117 | u := UUID{}
118 |
119 | timeNow, clockSeq, hardwareAddr := g.getStorage()
120 |
121 | switch domain {
122 | case DomainPerson:
123 | binary.BigEndian.PutUint32(u[0:], posixUID)
124 | case DomainGroup:
125 | binary.BigEndian.PutUint32(u[0:], posixGID)
126 | }
127 |
128 | binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
129 | binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
130 | binary.BigEndian.PutUint16(u[8:], clockSeq)
131 | u[9] = domain
132 |
133 | copy(u[10:], hardwareAddr)
134 |
135 | u.SetVersion(V2)
136 | u.SetVariant(VariantRFC4122)
137 |
138 | return u
139 | }
140 |
141 | // NewV3 returns UUID based on MD5 hash of namespace UUID and name.
142 | func (g *generator) NewV3(ns UUID, name string) UUID {
143 | u := newFromHash(md5.New(), ns, name)
144 | u.SetVersion(V3)
145 | u.SetVariant(VariantRFC4122)
146 |
147 | return u
148 | }
149 |
150 | // NewV4 returns random generated UUID.
151 | func (g *generator) NewV4() UUID {
152 | u := UUID{}
153 | g.safeRandom(u[:])
154 | u.SetVersion(V4)
155 | u.SetVariant(VariantRFC4122)
156 |
157 | return u
158 | }
159 |
160 | // NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
161 | func (g *generator) NewV5(ns UUID, name string) UUID {
162 | u := newFromHash(sha1.New(), ns, name)
163 | u.SetVersion(V5)
164 | u.SetVariant(VariantRFC4122)
165 |
166 | return u
167 | }
168 |
169 | func (g *generator) initStorage() {
170 | g.initClockSequence()
171 | g.initHardwareAddr()
172 | }
173 |
174 | func (g *generator) initClockSequence() {
175 | buf := make([]byte, 2)
176 | g.safeRandom(buf)
177 | g.clockSequence = binary.BigEndian.Uint16(buf)
178 | }
179 |
180 | func (g *generator) initHardwareAddr() {
181 | interfaces, err := net.Interfaces()
182 | if err == nil {
183 | for _, iface := range interfaces {
184 | if len(iface.HardwareAddr) >= 6 {
185 | copy(g.hardwareAddr[:], iface.HardwareAddr)
186 | return
187 | }
188 | }
189 | }
190 |
191 | // Initialize hardwareAddr randomly in case
192 | // of real network interfaces absence
193 | g.safeRandom(g.hardwareAddr[:])
194 |
195 | // Set multicast bit as recommended in RFC 4122
196 | g.hardwareAddr[0] |= 0x01
197 | }
198 |
199 | func (g *generator) safeRandom(dest []byte) {
200 | if _, err := rand.Read(dest); err != nil {
201 | panic(err)
202 | }
203 | }
204 |
205 | // Returns UUID v1/v2 storage state.
206 | // Returns epoch timestamp, clock sequence, and hardware address.
207 | func (g *generator) getStorage() (uint64, uint16, []byte) {
208 | g.storageOnce.Do(g.initStorage)
209 |
210 | g.storageMutex.Lock()
211 | defer g.storageMutex.Unlock()
212 |
213 | timeNow := epochFunc()
214 | // Clock changed backwards since last UUID generation.
215 | // Should increase clock sequence.
216 | if timeNow <= g.lastTime {
217 | g.clockSequence++
218 | }
219 | g.lastTime = timeNow
220 |
221 | return timeNow, g.clockSequence, g.hardwareAddr[:]
222 | }
223 |
224 | // Returns difference in 100-nanosecond intervals between
225 | // UUID epoch (October 15, 1582) and current time.
226 | // This is default epoch calculation function.
227 | func unixTimeFunc() uint64 {
228 | return epochStart + uint64(time.Now().UnixNano()/100)
229 | }
230 |
231 | // Returns UUID based on hashing of namespace UUID and name.
232 | func newFromHash(h hash.Hash, ns UUID, name string) UUID {
233 | u := UUID{}
234 | h.Write(ns[:])
235 | h.Write([]byte(name))
236 | copy(u[:], h.Sum(nil))
237 |
238 | return u
239 | }
240 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/generator_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | package uuid
23 |
24 | import (
25 | . "gopkg.in/check.v1"
26 | )
27 |
28 | type genTestSuite struct{}
29 |
30 | var _ = Suite(&genTestSuite{})
31 |
32 | func (s *genTestSuite) TestNewV1(c *C) {
33 | u := NewV1()
34 | c.Assert(u.Version(), Equals, V1)
35 | c.Assert(u.Variant(), Equals, VariantRFC4122)
36 |
37 | u1 := NewV1()
38 | u2 := NewV1()
39 | c.Assert(u1, Not(Equals), u2)
40 |
41 | oldFunc := epochFunc
42 | epochFunc = func() uint64 { return 0 }
43 |
44 | u3 := NewV1()
45 | u4 := NewV1()
46 | c.Assert(u3, Not(Equals), u4)
47 |
48 | epochFunc = oldFunc
49 | }
50 |
51 | func (s *genTestSuite) BenchmarkNewV1(c *C) {
52 | for i := 0; i < c.N; i++ {
53 | NewV1()
54 | }
55 | }
56 |
57 | func (s *genTestSuite) TestNewV2(c *C) {
58 | u1 := NewV2(DomainPerson)
59 | c.Assert(u1.Version(), Equals, V2)
60 | c.Assert(u1.Variant(), Equals, VariantRFC4122)
61 |
62 | u2 := NewV2(DomainGroup)
63 | c.Assert(u2.Version(), Equals, V2)
64 | c.Assert(u2.Variant(), Equals, VariantRFC4122)
65 | }
66 |
67 | func (s *genTestSuite) BenchmarkNewV2(c *C) {
68 | for i := 0; i < c.N; i++ {
69 | NewV2(DomainPerson)
70 | }
71 | }
72 |
73 | func (s *genTestSuite) TestNewV3(c *C) {
74 | u := NewV3(NamespaceDNS, "www.example.com")
75 | c.Assert(u.Version(), Equals, V3)
76 | c.Assert(u.Variant(), Equals, VariantRFC4122)
77 | c.Assert(u.String(), Equals, "5df41881-3aed-3515-88a7-2f4a814cf09e")
78 |
79 | u = NewV3(NamespaceDNS, "python.org")
80 | c.Assert(u.String(), Equals, "6fa459ea-ee8a-3ca4-894e-db77e160355e")
81 |
82 | u1 := NewV3(NamespaceDNS, "golang.org")
83 | u2 := NewV3(NamespaceDNS, "golang.org")
84 | c.Assert(u1, Equals, u2)
85 |
86 | u3 := NewV3(NamespaceDNS, "example.com")
87 | c.Assert(u1, Not(Equals), u3)
88 |
89 | u4 := NewV3(NamespaceURL, "golang.org")
90 | c.Assert(u1, Not(Equals), u4)
91 | }
92 |
93 | func (s *genTestSuite) BenchmarkNewV3(c *C) {
94 | for i := 0; i < c.N; i++ {
95 | NewV3(NamespaceDNS, "www.example.com")
96 | }
97 | }
98 |
99 | func (s *genTestSuite) TestNewV4(c *C) {
100 | u := NewV4()
101 | c.Assert(u.Version(), Equals, V4)
102 | c.Assert(u.Variant(), Equals, VariantRFC4122)
103 | }
104 |
105 | func (s *genTestSuite) BenchmarkNewV4(c *C) {
106 | for i := 0; i < c.N; i++ {
107 | NewV4()
108 | }
109 | }
110 |
111 | func (s *genTestSuite) TestNewV5(c *C) {
112 | u := NewV5(NamespaceDNS, "www.example.com")
113 | c.Assert(u.Version(), Equals, V5)
114 | c.Assert(u.Variant(), Equals, VariantRFC4122)
115 |
116 | u = NewV5(NamespaceDNS, "python.org")
117 | c.Assert(u.String(), Equals, "886313e1-3b8a-5372-9b90-0c9aee199e5d")
118 |
119 | u1 := NewV5(NamespaceDNS, "golang.org")
120 | u2 := NewV5(NamespaceDNS, "golang.org")
121 | c.Assert(u1, Equals, u2)
122 |
123 | u3 := NewV5(NamespaceDNS, "example.com")
124 | c.Assert(u1, Not(Equals), u3)
125 |
126 | u4 := NewV5(NamespaceURL, "golang.org")
127 | c.Assert(u1, Not(Equals), u4)
128 | }
129 |
130 | func (s *genTestSuite) BenchmarkNewV5(c *C) {
131 | for i := 0; i < c.N; i++ {
132 | NewV5(NamespaceDNS, "www.example.com")
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/sql.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | package uuid
23 |
24 | import (
25 | "database/sql/driver"
26 | "fmt"
27 | )
28 |
29 | // Value implements the driver.Valuer interface.
30 | func (u UUID) Value() (driver.Value, error) {
31 | return u.String(), nil
32 | }
33 |
34 | // Scan implements the sql.Scanner interface.
35 | // A 16-byte slice is handled by UnmarshalBinary, while
36 | // a longer byte slice or a string is handled by UnmarshalText.
37 | func (u *UUID) Scan(src interface{}) error {
38 | switch src := src.(type) {
39 | case []byte:
40 | if len(src) == Size {
41 | return u.UnmarshalBinary(src)
42 | }
43 | return u.UnmarshalText(src)
44 |
45 | case string:
46 | return u.UnmarshalText([]byte(src))
47 | }
48 |
49 | return fmt.Errorf("uuid: cannot convert %T to UUID", src)
50 | }
51 |
52 | // NullUUID can be used with the standard sql package to represent a
53 | // UUID value that can be NULL in the database
54 | type NullUUID struct {
55 | UUID UUID
56 | Valid bool
57 | }
58 |
59 | // Value implements the driver.Valuer interface.
60 | func (u NullUUID) Value() (driver.Value, error) {
61 | if !u.Valid {
62 | return nil, nil
63 | }
64 | // Delegate to UUID Value function
65 | return u.UUID.Value()
66 | }
67 |
68 | // Scan implements the sql.Scanner interface.
69 | func (u *NullUUID) Scan(src interface{}) error {
70 | if src == nil {
71 | u.UUID, u.Valid = Nil, false
72 | return nil
73 | }
74 |
75 | // Delegate to UUID Scan function
76 | u.Valid = true
77 | return u.UUID.Scan(src)
78 | }
79 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/sql_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | package uuid
23 |
24 | import (
25 | . "gopkg.in/check.v1"
26 | )
27 |
28 | type sqlTestSuite struct{}
29 |
30 | var _ = Suite(&sqlTestSuite{})
31 |
32 | func (s *sqlTestSuite) TestValue(c *C) {
33 | u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
34 | c.Assert(err, IsNil)
35 |
36 | val, err := u.Value()
37 | c.Assert(err, IsNil)
38 | c.Assert(val, Equals, u.String())
39 | }
40 |
41 | func (s *sqlTestSuite) TestValueNil(c *C) {
42 | u := UUID{}
43 |
44 | val, err := u.Value()
45 | c.Assert(err, IsNil)
46 | c.Assert(val, Equals, Nil.String())
47 | }
48 |
49 | func (s *sqlTestSuite) TestNullUUIDValueNil(c *C) {
50 | u := NullUUID{}
51 |
52 | val, err := u.Value()
53 | c.Assert(err, IsNil)
54 | c.Assert(val, IsNil)
55 | }
56 |
57 | func (s *sqlTestSuite) TestScanBinary(c *C) {
58 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
59 | b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
60 |
61 | u1 := UUID{}
62 | err := u1.Scan(b1)
63 | c.Assert(err, IsNil)
64 | c.Assert(u, Equals, u1)
65 |
66 | b2 := []byte{}
67 | u2 := UUID{}
68 |
69 | err = u2.Scan(b2)
70 | c.Assert(err, NotNil)
71 | }
72 |
73 | func (s *sqlTestSuite) TestScanString(c *C) {
74 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
75 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
76 |
77 | u1 := UUID{}
78 | err := u1.Scan(s1)
79 | c.Assert(err, IsNil)
80 | c.Assert(u, Equals, u1)
81 |
82 | s2 := ""
83 | u2 := UUID{}
84 |
85 | err = u2.Scan(s2)
86 | c.Assert(err, NotNil)
87 | }
88 |
89 | func (s *sqlTestSuite) TestScanText(c *C) {
90 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
91 | b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
92 |
93 | u1 := UUID{}
94 | err := u1.Scan(b1)
95 | c.Assert(err, IsNil)
96 | c.Assert(u, Equals, u1)
97 |
98 | b2 := []byte("")
99 | u2 := UUID{}
100 | err = u2.Scan(b2)
101 | c.Assert(err, NotNil)
102 | }
103 |
104 | func (s *sqlTestSuite) TestScanUnsupported(c *C) {
105 | u := UUID{}
106 |
107 | err := u.Scan(true)
108 | c.Assert(err, NotNil)
109 | }
110 |
111 | func (s *sqlTestSuite) TestScanNil(c *C) {
112 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
113 |
114 | err := u.Scan(nil)
115 | c.Assert(err, NotNil)
116 | }
117 |
118 | func (s *sqlTestSuite) TestNullUUIDScanValid(c *C) {
119 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
120 | s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
121 |
122 | u1 := NullUUID{}
123 | err := u1.Scan(s1)
124 | c.Assert(err, IsNil)
125 | c.Assert(u1.Valid, Equals, true)
126 | c.Assert(u1.UUID, Equals, u)
127 | }
128 |
129 | func (s *sqlTestSuite) TestNullUUIDScanNil(c *C) {
130 | u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true}
131 |
132 | err := u.Scan(nil)
133 | c.Assert(err, IsNil)
134 | c.Assert(u.Valid, Equals, false)
135 | c.Assert(u.UUID, Equals, Nil)
136 | }
137 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/uuid.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | // Package uuid provides implementation of Universally Unique Identifier (UUID).
23 | // Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
24 | // version 2 (as specified in DCE 1.1).
25 | package uuid
26 |
27 | import (
28 | "bytes"
29 | "encoding/hex"
30 | )
31 |
32 | // Size of a UUID in bytes.
33 | const Size = 16
34 |
35 | // UUID representation compliant with specification
36 | // described in RFC 4122.
37 | type UUID [Size]byte
38 |
39 | // UUID versions
40 | const (
41 | _ byte = iota
42 | V1
43 | V2
44 | V3
45 | V4
46 | V5
47 | )
48 |
49 | // UUID layout variants.
50 | const (
51 | VariantNCS byte = iota
52 | VariantRFC4122
53 | VariantMicrosoft
54 | VariantFuture
55 | )
56 |
57 | // UUID DCE domains.
58 | const (
59 | DomainPerson = iota
60 | DomainGroup
61 | DomainOrg
62 | )
63 |
64 | // String parse helpers.
65 | var (
66 | urnPrefix = []byte("urn:uuid:")
67 | byteGroups = []int{8, 4, 4, 4, 12}
68 | )
69 |
70 | // Nil is special form of UUID that is specified to have all
71 | // 128 bits set to zero.
72 | var Nil = UUID{}
73 |
74 | // Predefined namespace UUIDs.
75 | var (
76 | NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
77 | NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
78 | NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
79 | NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
80 | )
81 |
82 | // Equal returns true if u1 and u2 equals, otherwise returns false.
83 | func Equal(u1 UUID, u2 UUID) bool {
84 | return bytes.Equal(u1[:], u2[:])
85 | }
86 |
87 | // Version returns algorithm version used to generate UUID.
88 | func (u UUID) Version() byte {
89 | return u[6] >> 4
90 | }
91 |
92 | // Variant returns UUID layout variant.
93 | func (u UUID) Variant() byte {
94 | switch {
95 | case (u[8] >> 7) == 0x00:
96 | return VariantNCS
97 | case (u[8] >> 6) == 0x02:
98 | return VariantRFC4122
99 | case (u[8] >> 5) == 0x06:
100 | return VariantMicrosoft
101 | case (u[8] >> 5) == 0x07:
102 | fallthrough
103 | default:
104 | return VariantFuture
105 | }
106 | }
107 |
108 | // Bytes returns bytes slice representation of UUID.
109 | func (u UUID) Bytes() []byte {
110 | return u[:]
111 | }
112 |
113 | // Returns canonical string representation of UUID:
114 | // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
115 | func (u UUID) String() string {
116 | buf := make([]byte, 36)
117 |
118 | hex.Encode(buf[0:8], u[0:4])
119 | buf[8] = '-'
120 | hex.Encode(buf[9:13], u[4:6])
121 | buf[13] = '-'
122 | hex.Encode(buf[14:18], u[6:8])
123 | buf[18] = '-'
124 | hex.Encode(buf[19:23], u[8:10])
125 | buf[23] = '-'
126 | hex.Encode(buf[24:], u[10:])
127 |
128 | return string(buf)
129 | }
130 |
131 | // SetVersion sets version bits.
132 | func (u *UUID) SetVersion(v byte) {
133 | u[6] = (u[6] & 0x0f) | (v << 4)
134 | }
135 |
136 | // SetVariant sets variant bits.
137 | func (u *UUID) SetVariant(v byte) {
138 | switch v {
139 | case VariantNCS:
140 | u[8] = (u[8]&(0xff>>1) | (0x00 << 7))
141 | case VariantRFC4122:
142 | u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
143 | case VariantMicrosoft:
144 | u[8] = (u[8]&(0xff>>3) | (0x06 << 5))
145 | case VariantFuture:
146 | fallthrough
147 | default:
148 | u[8] = (u[8]&(0xff>>3) | (0x07 << 5))
149 | }
150 | }
151 |
152 | // Must is a helper that wraps a call to a function returning (UUID, error)
153 | // and panics if the error is non-nil. It is intended for use in variable
154 | // initializations such as
155 | // var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
156 | func Must(u UUID, err error) UUID {
157 | if err != nil {
158 | panic(err)
159 | }
160 | return u
161 | }
162 |
--------------------------------------------------------------------------------
/vendor/github.com/satori/go.uuid/uuid_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013-2018 by Maxim Bublis
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining
4 | // a copy of this software and associated documentation files (the
5 | // "Software"), to deal in the Software without restriction, including
6 | // without limitation the rights to use, copy, modify, merge, publish,
7 | // distribute, sublicense, and/or sell copies of the Software, and to
8 | // permit persons to whom the Software is furnished to do so, subject to
9 | // the following conditions:
10 | //
11 | // The above copyright notice and this permission notice shall be
12 | // included in all copies or substantial portions of the Software.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | package uuid
23 |
24 | import (
25 | "bytes"
26 | "testing"
27 |
28 | . "gopkg.in/check.v1"
29 | )
30 |
31 | // Hook up gocheck into the "go test" runner.
32 | func TestUUID(t *testing.T) { TestingT(t) }
33 |
34 | type testSuite struct{}
35 |
36 | var _ = Suite(&testSuite{})
37 |
38 | func (s *testSuite) TestBytes(c *C) {
39 | u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
40 |
41 | bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
42 |
43 | c.Assert(bytes.Equal(u.Bytes(), bytes1), Equals, true)
44 | }
45 |
46 | func (s *testSuite) TestString(c *C) {
47 | c.Assert(NamespaceDNS.String(), Equals, "6ba7b810-9dad-11d1-80b4-00c04fd430c8")
48 | }
49 |
50 | func (s *testSuite) TestEqual(c *C) {
51 | c.Assert(Equal(NamespaceDNS, NamespaceDNS), Equals, true)
52 | c.Assert(Equal(NamespaceDNS, NamespaceURL), Equals, false)
53 | }
54 |
55 | func (s *testSuite) TestVersion(c *C) {
56 | u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
57 | c.Assert(u.Version(), Equals, V1)
58 | }
59 |
60 | func (s *testSuite) TestSetVersion(c *C) {
61 | u := UUID{}
62 | u.SetVersion(4)
63 | c.Assert(u.Version(), Equals, V4)
64 | }
65 |
66 | func (s *testSuite) TestVariant(c *C) {
67 | u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
68 | c.Assert(u1.Variant(), Equals, VariantNCS)
69 |
70 | u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
71 | c.Assert(u2.Variant(), Equals, VariantRFC4122)
72 |
73 | u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
74 | c.Assert(u3.Variant(), Equals, VariantMicrosoft)
75 |
76 | u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
77 | c.Assert(u4.Variant(), Equals, VariantFuture)
78 | }
79 |
80 | func (s *testSuite) TestSetVariant(c *C) {
81 | u := UUID{}
82 | u.SetVariant(VariantNCS)
83 | c.Assert(u.Variant(), Equals, VariantNCS)
84 | u.SetVariant(VariantRFC4122)
85 | c.Assert(u.Variant(), Equals, VariantRFC4122)
86 | u.SetVariant(VariantMicrosoft)
87 | c.Assert(u.Variant(), Equals, VariantMicrosoft)
88 | u.SetVariant(VariantFuture)
89 | c.Assert(u.Variant(), Equals, VariantFuture)
90 | }
91 |
--------------------------------------------------------------------------------