mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-15 00:19:24 +01:00
Add TLSConfig to nctalk (#1195)
Signed-off-by: Gary Kim <gary@garykim.dev>
This commit is contained in:
parent
c63f08c811
commit
a0741d99b8
@ -2,6 +2,7 @@ package nctalk
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
@ -31,8 +32,18 @@ type Broom struct {
|
|||||||
|
|
||||||
func (b *Btalk) Connect() error {
|
func (b *Btalk) Connect() error {
|
||||||
b.Log.Info("Connecting")
|
b.Log.Info("Connecting")
|
||||||
b.user = talk.NewUser(b.GetString("Server"), b.GetString("Login"), b.GetString("Password"))
|
tconfig := &user.TalkUserConfig{
|
||||||
_, err := b.user.Capabilities()
|
TLSConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: b.GetBool("SkipTLSVerify"), //nolint:gosec
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
b.user, err = user.NewUser(b.GetString("Server"), b.GetString("Login"), b.GetString("Password"), tconfig)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Error("Config could not be used")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = b.user.Capabilities()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Error("Cannot Connect")
|
b.Log.Error("Cannot Connect")
|
||||||
return err
|
return err
|
||||||
|
4
go.mod
4
go.mod
@ -42,14 +42,14 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.6.0
|
github.com/sirupsen/logrus v1.6.0
|
||||||
github.com/slack-go/slack v0.6.5
|
github.com/slack-go/slack v0.6.5
|
||||||
github.com/spf13/viper v1.7.0
|
github.com/spf13/viper v1.7.0
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.6.1
|
||||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
|
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
|
||||||
github.com/yaegashi/msgraph.go v0.1.3
|
github.com/yaegashi/msgraph.go v0.1.3
|
||||||
github.com/zfjagann/golang-ring v0.0.0-20190304061218-d34796e0a6c2
|
github.com/zfjagann/golang-ring v0.0.0-20190304061218-d34796e0a6c2
|
||||||
golang.org/x/image v0.0.0-20200618115811-c13761719519
|
golang.org/x/image v0.0.0-20200618115811-c13761719519
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||||
gomod.garykim.dev/nc-talk v0.0.2
|
gomod.garykim.dev/nc-talk v0.1.1
|
||||||
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
||||||
)
|
)
|
||||||
|
|
||||||
|
10
go.sum
10
go.sum
@ -422,6 +422,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
|||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/monaco-io/request v1.0.3 h1:FsiIwXCCbHEyWx9A7lgg6JBTMHhHlEEsADsgAOvZ9HA=
|
github.com/monaco-io/request v1.0.3 h1:FsiIwXCCbHEyWx9A7lgg6JBTMHhHlEEsADsgAOvZ9HA=
|
||||||
github.com/monaco-io/request v1.0.3/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ=
|
github.com/monaco-io/request v1.0.3/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ=
|
||||||
|
github.com/monaco-io/request v1.0.4 h1:AbogA+IvPOWqyGZIFU7kSb8YS2Jv5Dnl5ncMj8cQV+o=
|
||||||
|
github.com/monaco-io/request v1.0.4/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ=
|
||||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 h1:oKIteTqeSpenyTrOVj5zkiyCaflLa8B+CD0324otT+o=
|
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 h1:oKIteTqeSpenyTrOVj5zkiyCaflLa8B+CD0324otT+o=
|
||||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||||
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff h1:HLGD5/9UxxfEuO9DtP8gnTmNtMxbPyhYltfxsITel8g=
|
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff h1:HLGD5/9UxxfEuO9DtP8gnTmNtMxbPyhYltfxsITel8g=
|
||||||
@ -610,6 +612,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
@ -854,6 +858,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
|
|||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gomod.garykim.dev/nc-talk v0.0.2 h1:QagJzL1Ie/sJDachAC42fEXlIh2mK8IDk1/ue0u8IcI=
|
gomod.garykim.dev/nc-talk v0.0.2 h1:QagJzL1Ie/sJDachAC42fEXlIh2mK8IDk1/ue0u8IcI=
|
||||||
gomod.garykim.dev/nc-talk v0.0.2/go.mod h1:0/Ksg0osAYmnWKs1OcCG+gBQ4HU1xiF1699g9B6jWZw=
|
gomod.garykim.dev/nc-talk v0.0.2/go.mod h1:0/Ksg0osAYmnWKs1OcCG+gBQ4HU1xiF1699g9B6jWZw=
|
||||||
|
gomod.garykim.dev/nc-talk v0.1.0 h1:JCT36+bLuGpYFye+e8ZY8oj54K/1ij/lPvaH7yw38Rg=
|
||||||
|
gomod.garykim.dev/nc-talk v0.1.0/go.mod h1:zKg8yxCk2KaTy6aPDEfRac0Jik72czX+nRsG8CZuhtc=
|
||||||
|
gomod.garykim.dev/nc-talk v0.1.1 h1:hRQ5vjKS0AreTs5gDcAOWeoDcf2w6HAHvrj+6/L+lZ0=
|
||||||
|
gomod.garykim.dev/nc-talk v0.1.1/go.mod h1:zKg8yxCk2KaTy6aPDEfRac0Jik72czX+nRsG8CZuhtc=
|
||||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
@ -941,6 +949,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
@ -1394,6 +1394,11 @@ ShowTopicChange=false
|
|||||||
# Url of your Nextcloud server
|
# Url of your Nextcloud server
|
||||||
Server = "https://cloud.youdomain.me"
|
Server = "https://cloud.youdomain.me"
|
||||||
|
|
||||||
|
# Enable to not verify the certificate on your Nextcloud server.
|
||||||
|
# e.g. when using selfsigned certificates
|
||||||
|
# OPTIONAL (default false)
|
||||||
|
SkipTLSVerify=true
|
||||||
|
|
||||||
# Username of the bot
|
# Username of the bot
|
||||||
Login = "talkuser"
|
Login = "talkuser"
|
||||||
|
|
||||||
|
16
vendor/github.com/monaco-io/request/.travis.yml
generated
vendored
16
vendor/github.com/monaco-io/request/.travis.yml
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.14.x
|
|
||||||
- tip
|
|
||||||
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- go get -t -v ./...
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -race -coverprofile=coverage.txt -covermode=atomic
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- bash <(curl -s https://codecov.io/bash) -t 6cf6f7ab-26e6-429c-ac44-f0ad85c1e586
|
|
26
vendor/github.com/monaco-io/request/README.md
generated
vendored
26
vendor/github.com/monaco-io/request/README.md
generated
vendored
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
<img align="right" width="159px" src="https://raw.githubusercontent.com/gin-gonic/logo/master/color.png">
|
<img align="right" width="159px" src="https://raw.githubusercontent.com/gin-gonic/logo/master/color.png">
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/monaco-io/request.svg?branch=master)](https://travis-ci.org/monaco-io/request)
|
|
||||||
[![GoDoc](https://godoc.org/github.com/monaco-io/request?status.svg)](https://pkg.go.dev/github.com/monaco-io/request?tab=doc)
|
[![GoDoc](https://godoc.org/github.com/monaco-io/request?status.svg)](https://pkg.go.dev/github.com/monaco-io/request?tab=doc)
|
||||||
[![codecov](https://codecov.io/gh/monaco-io/request/branch/master/graph/badge.svg)](https://codecov.io/gh/monaco-io/request)
|
[![codecov](https://codecov.io/gh/monaco-io/request/branch/master/graph/badge.svg)](https://codecov.io/gh/monaco-io/request)
|
||||||
[![Release](https://img.shields.io/github/release/monaco-io/request.svg?style=flat-square)](https://github.com/monaco-io/request/releases)
|
[![Release](https://img.shields.io/github/release/monaco-io/request.svg?style=flat-square)](https://github.com/monaco-io/request/releases)
|
||||||
@ -192,6 +191,31 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### TLS
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"crypto/tls"
|
||||||
|
|
||||||
|
"github.com/monaco-io/request"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
client := request.Client{
|
||||||
|
URL: "https://google.com",
|
||||||
|
TLSConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do()
|
||||||
|
|
||||||
|
log.Println(resp.Code, string(resp.Data), err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](LICENSE)
|
[MIT](LICENSE)
|
||||||
|
98
vendor/github.com/monaco-io/request/build.go
generated
vendored
Normal file
98
vendor/github.com/monaco-io/request/build.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package request
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
"net/http/cookiejar"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: func unit test coverage
|
||||||
|
func (c *Client) buildRequest() (err error) {
|
||||||
|
if err = c.applyRequest(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.transport = &http.Transport{}
|
||||||
|
|
||||||
|
c.applyHTTPHeader()
|
||||||
|
c.applyBasicAuth()
|
||||||
|
c.applyClient()
|
||||||
|
c.applyTimeout()
|
||||||
|
c.applyCookies()
|
||||||
|
c.applyTLSConfig()
|
||||||
|
err = c.applyProxy()
|
||||||
|
|
||||||
|
c.client.Transport = c.transport
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) applyRequest() (err error) {
|
||||||
|
// encode requestURL.httpURL like https://google.com?hello=world&package=request
|
||||||
|
c.requestURL = requestURL{
|
||||||
|
urlString: c.URL,
|
||||||
|
parameters: c.Params,
|
||||||
|
}
|
||||||
|
if err = c.requestURL.EncodeURL(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.req, err = http.NewRequest(c.Method, c.requestURL.string(), bytes.NewReader(c.Body))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) applyHTTPHeader() {
|
||||||
|
if c.Method == POST {
|
||||||
|
if c.ContentType == emptyString {
|
||||||
|
c.ContentType = ApplicationJSON
|
||||||
|
}
|
||||||
|
c.req.Header.Set(contentType, string(c.ContentType))
|
||||||
|
}
|
||||||
|
for k, v := range c.Header {
|
||||||
|
c.req.Header.Add(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) applyBasicAuth() {
|
||||||
|
if c.BasicAuth.Username != emptyString && c.BasicAuth.Password != emptyString {
|
||||||
|
c.req.SetBasicAuth(c.BasicAuth.Username, c.BasicAuth.Password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) applyClient() {
|
||||||
|
c.client = &http.Client{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) applyTimeout() {
|
||||||
|
if c.Timeout > 0 {
|
||||||
|
c.client.Timeout = c.Timeout * time.Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) applyCookies() {
|
||||||
|
if c.Cookies != nil {
|
||||||
|
jar, _ := cookiejar.New(nil)
|
||||||
|
jar.SetCookies(&url.URL{Scheme: c.requestURL.scheme(), Host: c.requestURL.host()}, c.Cookies)
|
||||||
|
c.client.Jar = jar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test case
|
||||||
|
func (c *Client) applyProxy() (err error) {
|
||||||
|
if c.ProxyURL != emptyString {
|
||||||
|
var proxy *url.URL
|
||||||
|
if proxy, err = url.Parse(c.ProxyURL); err != nil {
|
||||||
|
return
|
||||||
|
} else if proxy != nil {
|
||||||
|
c.transport.Proxy = http.ProxyURL(proxy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) applyTLSConfig() {
|
||||||
|
// &tls.Config{InsecureSkipVerify: true}
|
||||||
|
if c.TLSConfig != nil {
|
||||||
|
c.transport.TLSClientConfig = c.TLSConfig
|
||||||
|
}
|
||||||
|
}
|
46
vendor/github.com/monaco-io/request/const.go
generated
vendored
Normal file
46
vendor/github.com/monaco-io/request/const.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package request
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ApplicationJSON application/json
|
||||||
|
ApplicationJSON ContentType = "application/json"
|
||||||
|
|
||||||
|
// ApplicationXWwwFormURLEncoded application/x-www-form-urlencoded
|
||||||
|
ApplicationXWwwFormURLEncoded ContentType = "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
|
// MultipartFormData multipart/form-data
|
||||||
|
MultipartFormData ContentType = "multipart/form-data"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// OPTIONS http options
|
||||||
|
OPTIONS = "OPTIONS"
|
||||||
|
|
||||||
|
// GET http get
|
||||||
|
GET = "GET"
|
||||||
|
|
||||||
|
// HEAD http head
|
||||||
|
HEAD = "HEAD"
|
||||||
|
|
||||||
|
// POST http post
|
||||||
|
POST = "POST"
|
||||||
|
|
||||||
|
// PUT http put
|
||||||
|
PUT = "PUT"
|
||||||
|
|
||||||
|
// DELETE http delete
|
||||||
|
DELETE = "DELETE"
|
||||||
|
|
||||||
|
// TRACE http trace
|
||||||
|
TRACE = "TRACE"
|
||||||
|
|
||||||
|
// CONNECT http connect
|
||||||
|
CONNECT = "CONNECT"
|
||||||
|
|
||||||
|
// PATCH http patch
|
||||||
|
PATCH = "PATCH"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
emptyString = ""
|
||||||
|
contentType = "Content-Type"
|
||||||
|
)
|
19
vendor/github.com/monaco-io/request/model.go
generated
vendored
19
vendor/github.com/monaco-io/request/model.go
generated
vendored
@ -1,24 +1,18 @@
|
|||||||
package request
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// ApplicationJSON application/json
|
|
||||||
ApplicationJSON ContentType = "application/json"
|
|
||||||
|
|
||||||
// ApplicationXWwwFormURLEncoded application/x-www-form-urlencoded
|
|
||||||
ApplicationXWwwFormURLEncoded ContentType = "application/x-www-form-urlencoded"
|
|
||||||
|
|
||||||
// MultipartFormData multipart/form-data
|
|
||||||
MultipartFormData ContentType = "multipart/form-data"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ContentType Content-Type
|
// ContentType Content-Type
|
||||||
type ContentType string
|
type ContentType string
|
||||||
|
|
||||||
|
// Method http method
|
||||||
|
// TODO:
|
||||||
|
type Method string
|
||||||
|
|
||||||
// Client Method
|
// Client Method
|
||||||
/*
|
/*
|
||||||
Method = "OPTIONS" ; Section 9.2
|
Method = "OPTIONS" ; Section 9.2
|
||||||
@ -44,10 +38,13 @@ type Client struct {
|
|||||||
ProxyURL string
|
ProxyURL string
|
||||||
ContentType ContentType
|
ContentType ContentType
|
||||||
Cookies []*http.Cookie
|
Cookies []*http.Cookie
|
||||||
|
TLSConfig *tls.Config
|
||||||
|
|
||||||
// private
|
// private
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
requestURL requestURL
|
||||||
req *http.Request
|
req *http.Request
|
||||||
|
transport *http.Transport
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasicAuth Add Username:Password as Basic Auth
|
// BasicAuth Add Username:Password as Basic Auth
|
||||||
|
75
vendor/github.com/monaco-io/request/request.go
generated
vendored
75
vendor/github.com/monaco-io/request/request.go
generated
vendored
@ -1,98 +1,33 @@
|
|||||||
package request
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/cookiejar"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Do send http request
|
// Do send http request
|
||||||
func (c *Client) Do() (resp SugaredResp, err error) {
|
func (c *Client) Do() (resp SugaredResp, err error) {
|
||||||
defer resp.Close()
|
defer resp.Close()
|
||||||
|
|
||||||
if err := c.buildRequest(); err != nil {
|
if err = c.buildRequest(); err != nil {
|
||||||
return resp, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// send request and close on func call end
|
// send request and close on func call end
|
||||||
if resp.resp, err = c.client.Do(c.req); err != nil {
|
if resp.resp, err = c.client.Do(c.req); err != nil {
|
||||||
return resp, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// read response data form resp
|
// read response data form resp
|
||||||
resp.Data, err = ioutil.ReadAll(resp.resp.Body)
|
resp.Data, err = ioutil.ReadAll(resp.resp.Body)
|
||||||
resp.Code = resp.resp.StatusCode
|
resp.Code = resp.resp.StatusCode
|
||||||
return resp, err
|
return
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) buildRequest() (err error) {
|
|
||||||
|
|
||||||
// encode requestURL.httpURL like https://google.com?hello=world&package=request
|
|
||||||
ru := requestURL{
|
|
||||||
urlString: c.URL,
|
|
||||||
parameters: c.Params,
|
|
||||||
}
|
|
||||||
if err := ru.EncodeURL(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// build request
|
|
||||||
c.req, err = http.NewRequest(c.Method, ru.string(), bytes.NewReader(c.Body))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply Header to request
|
|
||||||
if c.Method == "POST" {
|
|
||||||
if c.ContentType == "" {
|
|
||||||
c.ContentType = ApplicationJSON
|
|
||||||
}
|
|
||||||
c.req.Header.Set("Content-Type", string(c.ContentType))
|
|
||||||
}
|
|
||||||
for k, v := range c.Header {
|
|
||||||
c.req.Header.Add(k, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply basic Auth of request header
|
|
||||||
if c.BasicAuth.Username != "" && c.BasicAuth.Password != "" {
|
|
||||||
c.req.SetBasicAuth(c.BasicAuth.Username, c.BasicAuth.Password)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.client = &http.Client{}
|
|
||||||
|
|
||||||
// apply timeout
|
|
||||||
if c.Timeout > 0 {
|
|
||||||
c.client.Timeout = c.Timeout * time.Second
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply cookies
|
|
||||||
if c.Cookies != nil {
|
|
||||||
jar, _ := cookiejar.New(nil)
|
|
||||||
jar.SetCookies(&url.URL{Scheme: ru.scheme(), Host: ru.host()}, c.Cookies)
|
|
||||||
c.client.Jar = jar
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply proxy
|
|
||||||
if c.ProxyURL != "" {
|
|
||||||
if proxy, err := url.Parse(c.ProxyURL); err == nil && proxy != nil {
|
|
||||||
c.client.Transport = &http.Transport{
|
|
||||||
Proxy: http.ProxyURL(proxy),
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resp do request and get original http response struct
|
// Resp do request and get original http response struct
|
||||||
func (c *Client) Resp() (resp *http.Response, err error) {
|
func (c *Client) Resp() (resp *http.Response, err error) {
|
||||||
if err = c.buildRequest(); err != nil {
|
if err = c.buildRequest(); err != nil {
|
||||||
return resp, err
|
return
|
||||||
}
|
}
|
||||||
return c.client.Do(c.req)
|
return c.client.Do(c.req)
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/monaco-io/request/url.go
generated
vendored
4
vendor/github.com/monaco-io/request/url.go
generated
vendored
@ -12,14 +12,14 @@ type requestURL struct {
|
|||||||
func (ru *requestURL) EncodeURL() (err error) {
|
func (ru *requestURL) EncodeURL() (err error) {
|
||||||
ru.httpURL, err = url.Parse(ru.urlString)
|
ru.httpURL, err = url.Parse(ru.urlString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
query := ru.httpURL.Query()
|
query := ru.httpURL.Query()
|
||||||
for k := range ru.parameters {
|
for k := range ru.parameters {
|
||||||
query.Set(k, ru.parameters[k])
|
query.Set(k, ru.parameters[k])
|
||||||
}
|
}
|
||||||
ru.httpURL.RawQuery = query.Encode()
|
ru.httpURL.RawQuery = query.Encode()
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// String return example: https://www.google.com/search?a=1&b=2
|
// String return example: https://www.google.com/search?a=1&b=2
|
||||||
|
2
vendor/github.com/stretchr/testify/LICENSE
generated
vendored
2
vendor/github.com/stretchr/testify/LICENSE
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell
|
Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -5,20 +5,28 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
type CompareType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
compareLess CompareType = iota - 1
|
||||||
|
compareEqual
|
||||||
|
compareGreater
|
||||||
|
)
|
||||||
|
|
||||||
|
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||||
switch kind {
|
switch kind {
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
{
|
{
|
||||||
intobj1 := obj1.(int)
|
intobj1 := obj1.(int)
|
||||||
intobj2 := obj2.(int)
|
intobj2 := obj2.(int)
|
||||||
if intobj1 > intobj2 {
|
if intobj1 > intobj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if intobj1 == intobj2 {
|
if intobj1 == intobj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if intobj1 < intobj2 {
|
if intobj1 < intobj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
@ -26,13 +34,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
int8obj1 := obj1.(int8)
|
int8obj1 := obj1.(int8)
|
||||||
int8obj2 := obj2.(int8)
|
int8obj2 := obj2.(int8)
|
||||||
if int8obj1 > int8obj2 {
|
if int8obj1 > int8obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if int8obj1 == int8obj2 {
|
if int8obj1 == int8obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if int8obj1 < int8obj2 {
|
if int8obj1 < int8obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
@ -40,13 +48,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
int16obj1 := obj1.(int16)
|
int16obj1 := obj1.(int16)
|
||||||
int16obj2 := obj2.(int16)
|
int16obj2 := obj2.(int16)
|
||||||
if int16obj1 > int16obj2 {
|
if int16obj1 > int16obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if int16obj1 == int16obj2 {
|
if int16obj1 == int16obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if int16obj1 < int16obj2 {
|
if int16obj1 < int16obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
@ -54,13 +62,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
int32obj1 := obj1.(int32)
|
int32obj1 := obj1.(int32)
|
||||||
int32obj2 := obj2.(int32)
|
int32obj2 := obj2.(int32)
|
||||||
if int32obj1 > int32obj2 {
|
if int32obj1 > int32obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if int32obj1 == int32obj2 {
|
if int32obj1 == int32obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if int32obj1 < int32obj2 {
|
if int32obj1 < int32obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
@ -68,13 +76,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
int64obj1 := obj1.(int64)
|
int64obj1 := obj1.(int64)
|
||||||
int64obj2 := obj2.(int64)
|
int64obj2 := obj2.(int64)
|
||||||
if int64obj1 > int64obj2 {
|
if int64obj1 > int64obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if int64obj1 == int64obj2 {
|
if int64obj1 == int64obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if int64obj1 < int64obj2 {
|
if int64obj1 < int64obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Uint:
|
case reflect.Uint:
|
||||||
@ -82,13 +90,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
uintobj1 := obj1.(uint)
|
uintobj1 := obj1.(uint)
|
||||||
uintobj2 := obj2.(uint)
|
uintobj2 := obj2.(uint)
|
||||||
if uintobj1 > uintobj2 {
|
if uintobj1 > uintobj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if uintobj1 == uintobj2 {
|
if uintobj1 == uintobj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if uintobj1 < uintobj2 {
|
if uintobj1 < uintobj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
@ -96,13 +104,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
uint8obj1 := obj1.(uint8)
|
uint8obj1 := obj1.(uint8)
|
||||||
uint8obj2 := obj2.(uint8)
|
uint8obj2 := obj2.(uint8)
|
||||||
if uint8obj1 > uint8obj2 {
|
if uint8obj1 > uint8obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if uint8obj1 == uint8obj2 {
|
if uint8obj1 == uint8obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if uint8obj1 < uint8obj2 {
|
if uint8obj1 < uint8obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Uint16:
|
case reflect.Uint16:
|
||||||
@ -110,13 +118,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
uint16obj1 := obj1.(uint16)
|
uint16obj1 := obj1.(uint16)
|
||||||
uint16obj2 := obj2.(uint16)
|
uint16obj2 := obj2.(uint16)
|
||||||
if uint16obj1 > uint16obj2 {
|
if uint16obj1 > uint16obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if uint16obj1 == uint16obj2 {
|
if uint16obj1 == uint16obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if uint16obj1 < uint16obj2 {
|
if uint16obj1 < uint16obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
@ -124,13 +132,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
uint32obj1 := obj1.(uint32)
|
uint32obj1 := obj1.(uint32)
|
||||||
uint32obj2 := obj2.(uint32)
|
uint32obj2 := obj2.(uint32)
|
||||||
if uint32obj1 > uint32obj2 {
|
if uint32obj1 > uint32obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if uint32obj1 == uint32obj2 {
|
if uint32obj1 == uint32obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if uint32obj1 < uint32obj2 {
|
if uint32obj1 < uint32obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
@ -138,13 +146,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
uint64obj1 := obj1.(uint64)
|
uint64obj1 := obj1.(uint64)
|
||||||
uint64obj2 := obj2.(uint64)
|
uint64obj2 := obj2.(uint64)
|
||||||
if uint64obj1 > uint64obj2 {
|
if uint64obj1 > uint64obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if uint64obj1 == uint64obj2 {
|
if uint64obj1 == uint64obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if uint64obj1 < uint64obj2 {
|
if uint64obj1 < uint64obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
@ -152,13 +160,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
float32obj1 := obj1.(float32)
|
float32obj1 := obj1.(float32)
|
||||||
float32obj2 := obj2.(float32)
|
float32obj2 := obj2.(float32)
|
||||||
if float32obj1 > float32obj2 {
|
if float32obj1 > float32obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if float32obj1 == float32obj2 {
|
if float32obj1 == float32obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if float32obj1 < float32obj2 {
|
if float32obj1 < float32obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
@ -166,13 +174,13 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
float64obj1 := obj1.(float64)
|
float64obj1 := obj1.(float64)
|
||||||
float64obj2 := obj2.(float64)
|
float64obj2 := obj2.(float64)
|
||||||
if float64obj1 > float64obj2 {
|
if float64obj1 > float64obj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if float64obj1 == float64obj2 {
|
if float64obj1 == float64obj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if float64obj1 < float64obj2 {
|
if float64obj1 < float64obj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
@ -180,18 +188,18 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
stringobj1 := obj1.(string)
|
stringobj1 := obj1.(string)
|
||||||
stringobj2 := obj2.(string)
|
stringobj2 := obj2.(string)
|
||||||
if stringobj1 > stringobj2 {
|
if stringobj1 > stringobj2 {
|
||||||
return -1, true
|
return compareGreater, true
|
||||||
}
|
}
|
||||||
if stringobj1 == stringobj2 {
|
if stringobj1 == stringobj2 {
|
||||||
return 0, true
|
return compareEqual, true
|
||||||
}
|
}
|
||||||
if stringobj1 < stringobj2 {
|
if stringobj1 < stringobj2 {
|
||||||
return 1, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, false
|
return compareEqual, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Greater asserts that the first element is greater than the second
|
// Greater asserts that the first element is greater than the second
|
||||||
@ -200,26 +208,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
|||||||
// assert.Greater(t, float64(2), float64(1))
|
// assert.Greater(t, float64(2), float64(1))
|
||||||
// assert.Greater(t, "b", "a")
|
// assert.Greater(t, "b", "a")
|
||||||
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs)
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
|
|
||||||
e1Kind := reflect.ValueOf(e1).Kind()
|
|
||||||
e2Kind := reflect.ValueOf(e2).Kind()
|
|
||||||
if e1Kind != e2Kind {
|
|
||||||
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
res, isComparable := compare(e1, e2, e1Kind)
|
|
||||||
if !isComparable {
|
|
||||||
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res != -1 {
|
|
||||||
return Fail(t, fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
||||||
@ -229,26 +218,7 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
|
|||||||
// assert.GreaterOrEqual(t, "b", "a")
|
// assert.GreaterOrEqual(t, "b", "a")
|
||||||
// assert.GreaterOrEqual(t, "b", "b")
|
// assert.GreaterOrEqual(t, "b", "b")
|
||||||
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs)
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
|
|
||||||
e1Kind := reflect.ValueOf(e1).Kind()
|
|
||||||
e2Kind := reflect.ValueOf(e2).Kind()
|
|
||||||
if e1Kind != e2Kind {
|
|
||||||
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
res, isComparable := compare(e1, e2, e1Kind)
|
|
||||||
if !isComparable {
|
|
||||||
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res != -1 && res != 0 {
|
|
||||||
return Fail(t, fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Less asserts that the first element is less than the second
|
// Less asserts that the first element is less than the second
|
||||||
@ -257,26 +227,7 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
|
|||||||
// assert.Less(t, float64(1), float64(2))
|
// assert.Less(t, float64(1), float64(2))
|
||||||
// assert.Less(t, "a", "b")
|
// assert.Less(t, "a", "b")
|
||||||
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs)
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
|
|
||||||
e1Kind := reflect.ValueOf(e1).Kind()
|
|
||||||
e2Kind := reflect.ValueOf(e2).Kind()
|
|
||||||
if e1Kind != e2Kind {
|
|
||||||
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
res, isComparable := compare(e1, e2, e1Kind)
|
|
||||||
if !isComparable {
|
|
||||||
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res != 1 {
|
|
||||||
return Fail(t, fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LessOrEqual asserts that the first element is less than or equal to the second
|
// LessOrEqual asserts that the first element is less than or equal to the second
|
||||||
@ -286,6 +237,10 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
|
|||||||
// assert.LessOrEqual(t, "a", "b")
|
// assert.LessOrEqual(t, "a", "b")
|
||||||
// assert.LessOrEqual(t, "b", "b")
|
// assert.LessOrEqual(t, "b", "b")
|
||||||
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
@ -296,14 +251,24 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
|
|||||||
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, isComparable := compare(e1, e2, e1Kind)
|
compareResult, isComparable := compare(e1, e2, e1Kind)
|
||||||
if !isComparable {
|
if !isComparable {
|
||||||
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if res != 1 && res != 0 {
|
if !containsValue(allowedComparesResults, compareResult) {
|
||||||
return Fail(t, fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2), msgAndArgs...)
|
return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func containsValue(values []CompareType, value CompareType) bool {
|
||||||
|
for _, v := range values {
|
||||||
|
if v == value {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
40
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
40
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
@ -93,7 +93,7 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
|
|||||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
// and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
|
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -127,7 +127,7 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick
|
|||||||
|
|
||||||
// Exactlyf asserts that two objects are equal in value and type.
|
// Exactlyf asserts that two objects are equal in value and type.
|
||||||
//
|
//
|
||||||
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
|
||||||
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -173,7 +173,7 @@ func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool
|
|||||||
// Greaterf asserts that the first element is greater than the second
|
// Greaterf asserts that the first element is greater than the second
|
||||||
//
|
//
|
||||||
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
|
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
|
||||||
// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1))
|
// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
|
||||||
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
|
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
|
||||||
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
@ -225,7 +225,7 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u
|
|||||||
//
|
//
|
||||||
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -237,7 +237,7 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string,
|
|||||||
//
|
//
|
||||||
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -245,6 +245,18 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
|
|||||||
return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPSuccessf asserts that a specified handler returns a success status code.
|
// HTTPSuccessf asserts that a specified handler returns a success status code.
|
||||||
//
|
//
|
||||||
// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
|
// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
|
||||||
@ -259,7 +271,7 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin
|
|||||||
|
|
||||||
// Implementsf asserts that an object is implemented by the specified interface.
|
// Implementsf asserts that an object is implemented by the specified interface.
|
||||||
//
|
//
|
||||||
// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||||
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -341,7 +353,7 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf
|
|||||||
// Lessf asserts that the first element is less than the second
|
// Lessf asserts that the first element is less than the second
|
||||||
//
|
//
|
||||||
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
|
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
|
||||||
// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2))
|
// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
|
||||||
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
|
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
|
||||||
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
@ -454,6 +466,16 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string,
|
|||||||
return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
|
||||||
|
func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotNilf asserts that the specified object is not nil.
|
// NotNilf asserts that the specified object is not nil.
|
||||||
//
|
//
|
||||||
// assert.NotNilf(t, err, "error message %s", "formatted")
|
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||||
@ -476,7 +498,7 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo
|
|||||||
|
|
||||||
// NotRegexpf asserts that a specified regexp does not match a string.
|
// NotRegexpf asserts that a specified regexp does not match a string.
|
||||||
//
|
//
|
||||||
// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
|
||||||
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
||||||
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
@ -552,7 +574,7 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str
|
|||||||
|
|
||||||
// Regexpf asserts that a specified regexp matches a string.
|
// Regexpf asserts that a specified regexp matches a string.
|
||||||
//
|
//
|
||||||
// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
|
||||||
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
||||||
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
62
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
62
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
@ -169,7 +169,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
|||||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
// and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
|
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -251,7 +251,7 @@ func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArg
|
|||||||
|
|
||||||
// Exactlyf asserts that two objects are equal in value and type.
|
// Exactlyf asserts that two objects are equal in value and type.
|
||||||
//
|
//
|
||||||
// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
|
// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted")
|
||||||
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -370,7 +370,7 @@ func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string,
|
|||||||
// Greaterf asserts that the first element is greater than the second
|
// Greaterf asserts that the first element is greater than the second
|
||||||
//
|
//
|
||||||
// a.Greaterf(2, 1, "error message %s", "formatted")
|
// a.Greaterf(2, 1, "error message %s", "formatted")
|
||||||
// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1))
|
// a.Greaterf(float64(2), float64(1), "error message %s", "formatted")
|
||||||
// a.Greaterf("b", "a", "error message %s", "formatted")
|
// a.Greaterf("b", "a", "error message %s", "formatted")
|
||||||
func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
@ -447,7 +447,7 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri
|
|||||||
//
|
//
|
||||||
// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -471,7 +471,7 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s
|
|||||||
//
|
//
|
||||||
// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -479,6 +479,30 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
|
|||||||
return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
|
return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCode asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPSuccess asserts that a specified handler returns a success status code.
|
// HTTPSuccess asserts that a specified handler returns a success status code.
|
||||||
//
|
//
|
||||||
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
||||||
@ -515,7 +539,7 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{},
|
|||||||
|
|
||||||
// Implementsf asserts that an object is implemented by the specified interface.
|
// Implementsf asserts that an object is implemented by the specified interface.
|
||||||
//
|
//
|
||||||
// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||||
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -706,7 +730,7 @@ func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, ar
|
|||||||
// Lessf asserts that the first element is less than the second
|
// Lessf asserts that the first element is less than the second
|
||||||
//
|
//
|
||||||
// a.Lessf(1, 2, "error message %s", "formatted")
|
// a.Lessf(1, 2, "error message %s", "formatted")
|
||||||
// a.Lessf(float64(1, "error message %s", "formatted"), float64(2))
|
// a.Lessf(float64(1), float64(2), "error message %s", "formatted")
|
||||||
// a.Lessf("a", "b", "error message %s", "formatted")
|
// a.Lessf("a", "b", "error message %s", "formatted")
|
||||||
func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
@ -884,6 +908,26 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr
|
|||||||
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotEqualValues asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// a.NotEqualValues(obj1, obj2)
|
||||||
|
func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotEqualValues(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted")
|
||||||
|
func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return NotEqualValuesf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEqualf asserts that the specified values are NOT equal.
|
// NotEqualf asserts that the specified values are NOT equal.
|
||||||
//
|
//
|
||||||
// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
|
// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
|
||||||
@ -950,7 +994,7 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in
|
|||||||
|
|
||||||
// NotRegexpf asserts that a specified regexp does not match a string.
|
// NotRegexpf asserts that a specified regexp does not match a string.
|
||||||
//
|
//
|
||||||
// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
|
||||||
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
||||||
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
@ -1102,7 +1146,7 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter
|
|||||||
|
|
||||||
// Regexpf asserts that a specified regexp matches a string.
|
// Regexpf asserts that a specified regexp matches a string.
|
||||||
//
|
//
|
||||||
// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
|
||||||
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
||||||
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
169
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
169
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
@ -19,7 +19,7 @@ import (
|
|||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
"github.com/pmezard/go-difflib/difflib"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
|
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
|
||||||
@ -45,7 +45,7 @@ type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
|
|||||||
// for table driven tests.
|
// for table driven tests.
|
||||||
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
|
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
|
||||||
|
|
||||||
// Comparison a custom function that returns true on success and false on failure
|
// Comparison is a custom function that returns true on success and false on failure
|
||||||
type Comparison func() (success bool)
|
type Comparison func() (success bool)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -104,11 +104,11 @@ the problem actually occurred in calling code.*/
|
|||||||
// failed.
|
// failed.
|
||||||
func CallerInfo() []string {
|
func CallerInfo() []string {
|
||||||
|
|
||||||
pc := uintptr(0)
|
var pc uintptr
|
||||||
file := ""
|
var ok bool
|
||||||
line := 0
|
var file string
|
||||||
ok := false
|
var line int
|
||||||
name := ""
|
var name string
|
||||||
|
|
||||||
callers := []string{}
|
callers := []string{}
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
@ -429,14 +429,27 @@ func samePointers(first, second interface{}) bool {
|
|||||||
// to a type conversion in the Go grammar.
|
// to a type conversion in the Go grammar.
|
||||||
func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
||||||
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
|
if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
|
||||||
return fmt.Sprintf("%T(%#v)", expected, expected),
|
return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)),
|
||||||
fmt.Sprintf("%T(%#v)", actual, actual)
|
fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual))
|
||||||
}
|
}
|
||||||
switch expected.(type) {
|
switch expected.(type) {
|
||||||
case time.Duration:
|
case time.Duration:
|
||||||
return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
|
return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%#v", expected), fmt.Sprintf("%#v", actual)
|
return truncatingFormat(expected), truncatingFormat(actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
// truncatingFormat formats the data and truncates it if it's too long.
|
||||||
|
//
|
||||||
|
// This helps keep formatted error messages lines from exceeding the
|
||||||
|
// bufio.MaxScanTokenSize max line length that the go testing framework imposes.
|
||||||
|
func truncatingFormat(data interface{}) string {
|
||||||
|
value := fmt.Sprintf("%#v", data)
|
||||||
|
max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed.
|
||||||
|
if len(value) > max {
|
||||||
|
value = value[0:max] + "<... truncated>"
|
||||||
|
}
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||||
@ -483,12 +496,12 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
|||||||
//
|
//
|
||||||
// assert.NotNil(t, err)
|
// assert.NotNil(t, err)
|
||||||
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
if !isNil(object) {
|
if !isNil(object) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,12 +542,12 @@ func isNil(object interface{}) bool {
|
|||||||
//
|
//
|
||||||
// assert.Nil(t, err)
|
// assert.Nil(t, err)
|
||||||
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
if isNil(object) {
|
if isNil(object) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,12 +584,11 @@ func isEmpty(object interface{}) bool {
|
|||||||
//
|
//
|
||||||
// assert.Empty(t, obj)
|
// assert.Empty(t, obj)
|
||||||
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
pass := isEmpty(object)
|
||||||
|
if !pass {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
pass := isEmpty(object)
|
|
||||||
if !pass {
|
|
||||||
Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
|
Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,12 +603,11 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
|||||||
// assert.Equal(t, "two", obj[1])
|
// assert.Equal(t, "two", obj[1])
|
||||||
// }
|
// }
|
||||||
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
pass := !isEmpty(object)
|
||||||
|
if !pass {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
pass := !isEmpty(object)
|
|
||||||
if !pass {
|
|
||||||
Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
|
Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,16 +650,10 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
|
|||||||
//
|
//
|
||||||
// assert.True(t, myBool)
|
// assert.True(t, myBool)
|
||||||
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
if !value {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
if h, ok := t.(interface {
|
|
||||||
Helper()
|
|
||||||
}); ok {
|
|
||||||
h.Helper()
|
|
||||||
}
|
|
||||||
|
|
||||||
if value != true {
|
|
||||||
return Fail(t, "Should be true", msgAndArgs...)
|
return Fail(t, "Should be true", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,11 +665,10 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
|||||||
//
|
//
|
||||||
// assert.False(t, myBool)
|
// assert.False(t, myBool)
|
||||||
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
if value {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
if value != false {
|
|
||||||
return Fail(t, "Should be false", msgAndArgs...)
|
return Fail(t, "Should be false", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,6 +699,21 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotEqualValues asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// assert.NotEqualValues(t, obj1, obj2)
|
||||||
|
func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ObjectsAreEqualValues(expected, actual) {
|
||||||
|
return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// containsElement try loop over the list check if the list includes the element.
|
// containsElement try loop over the list check if the list includes the element.
|
||||||
// return (false, false) if impossible.
|
// return (false, false) if impossible.
|
||||||
// return (true, false) if element was not found.
|
// return (true, false) if element was not found.
|
||||||
@ -747,10 +766,10 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
|
|||||||
|
|
||||||
ok, found := includeElement(s, contains)
|
ok, found := includeElement(s, contains)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@ -881,27 +900,39 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
aKind := reflect.TypeOf(listA).Kind()
|
if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) {
|
||||||
bKind := reflect.TypeOf(listB).Kind()
|
return false
|
||||||
|
|
||||||
if aKind != reflect.Array && aKind != reflect.Slice {
|
|
||||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if bKind != reflect.Array && bKind != reflect.Slice {
|
extraA, extraB := diffLists(listA, listB)
|
||||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...)
|
|
||||||
|
if len(extraA) == 0 && len(extraB) == 0 {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// isList checks that the provided value is array or slice.
|
||||||
|
func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||||
|
kind := reflect.TypeOf(list).Kind()
|
||||||
|
if kind != reflect.Array && kind != reflect.Slice {
|
||||||
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind),
|
||||||
|
msgAndArgs...)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B.
|
||||||
|
// If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and
|
||||||
|
// 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored.
|
||||||
|
func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) {
|
||||||
aValue := reflect.ValueOf(listA)
|
aValue := reflect.ValueOf(listA)
|
||||||
bValue := reflect.ValueOf(listB)
|
bValue := reflect.ValueOf(listB)
|
||||||
|
|
||||||
aLen := aValue.Len()
|
aLen := aValue.Len()
|
||||||
bLen := bValue.Len()
|
bLen := bValue.Len()
|
||||||
|
|
||||||
if aLen != bLen {
|
|
||||||
return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark indexes in bValue that we already used
|
// Mark indexes in bValue that we already used
|
||||||
visited := make([]bool, bLen)
|
visited := make([]bool, bLen)
|
||||||
for i := 0; i < aLen; i++ {
|
for i := 0; i < aLen; i++ {
|
||||||
@ -918,11 +949,38 @@ func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...)
|
extraA = append(extraA, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
for j := 0; j < bLen; j++ {
|
||||||
|
if visited[j] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
extraB = append(extraB, bValue.Index(j).Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string {
|
||||||
|
var msg bytes.Buffer
|
||||||
|
|
||||||
|
msg.WriteString("elements differ")
|
||||||
|
if len(extraA) > 0 {
|
||||||
|
msg.WriteString("\n\nextra elements in list A:\n")
|
||||||
|
msg.WriteString(spewConfig.Sdump(extraA))
|
||||||
|
}
|
||||||
|
if len(extraB) > 0 {
|
||||||
|
msg.WriteString("\n\nextra elements in list B:\n")
|
||||||
|
msg.WriteString(spewConfig.Sdump(extraB))
|
||||||
|
}
|
||||||
|
msg.WriteString("\n\nlistA:\n")
|
||||||
|
msg.WriteString(spewConfig.Sdump(listA))
|
||||||
|
msg.WriteString("\n\nlistB:\n")
|
||||||
|
msg.WriteString(spewConfig.Sdump(listB))
|
||||||
|
|
||||||
|
return msg.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Condition uses a Comparison to assert a complex condition.
|
// Condition uses a Comparison to assert a complex condition.
|
||||||
@ -1058,6 +1116,8 @@ func toFloat(x interface{}) (float64, bool) {
|
|||||||
xok := true
|
xok := true
|
||||||
|
|
||||||
switch xn := x.(type) {
|
switch xn := x.(type) {
|
||||||
|
case uint:
|
||||||
|
xf = float64(xn)
|
||||||
case uint8:
|
case uint8:
|
||||||
xf = float64(xn)
|
xf = float64(xn)
|
||||||
case uint16:
|
case uint16:
|
||||||
@ -1079,7 +1139,7 @@ func toFloat(x interface{}) (float64, bool) {
|
|||||||
case float32:
|
case float32:
|
||||||
xf = float64(xn)
|
xf = float64(xn)
|
||||||
case float64:
|
case float64:
|
||||||
xf = float64(xn)
|
xf = xn
|
||||||
case time.Duration:
|
case time.Duration:
|
||||||
xf = float64(xn)
|
xf = float64(xn)
|
||||||
default:
|
default:
|
||||||
@ -1193,6 +1253,9 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
|
|||||||
if !aok {
|
if !aok {
|
||||||
return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
|
return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
|
||||||
}
|
}
|
||||||
|
if math.IsNaN(af) {
|
||||||
|
return 0, errors.New("expected value must not be NaN")
|
||||||
|
}
|
||||||
if af == 0 {
|
if af == 0 {
|
||||||
return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
|
return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
|
||||||
}
|
}
|
||||||
@ -1200,6 +1263,9 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
|
|||||||
if !bok {
|
if !bok {
|
||||||
return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
|
return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
|
||||||
}
|
}
|
||||||
|
if math.IsNaN(bf) {
|
||||||
|
return 0, errors.New("actual value must not be NaN")
|
||||||
|
}
|
||||||
|
|
||||||
return math.Abs(af-bf) / math.Abs(af), nil
|
return math.Abs(af-bf) / math.Abs(af), nil
|
||||||
}
|
}
|
||||||
@ -1209,6 +1275,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
|
|||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
if math.IsNaN(epsilon) {
|
||||||
|
return Fail(t, "epsilon must not be NaN")
|
||||||
|
}
|
||||||
actualEpsilon, err := calcRelativeError(expected, actual)
|
actualEpsilon, err := calcRelativeError(expected, actual)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Fail(t, err.Error(), msgAndArgs...)
|
return Fail(t, err.Error(), msgAndArgs...)
|
||||||
@ -1256,10 +1325,10 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
|||||||
// assert.Equal(t, expectedObj, actualObj)
|
// assert.Equal(t, expectedObj, actualObj)
|
||||||
// }
|
// }
|
||||||
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||||
|
if err != nil {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1273,11 +1342,10 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
|||||||
// assert.Equal(t, expectedError, err)
|
// assert.Equal(t, expectedError, err)
|
||||||
// }
|
// }
|
||||||
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||||
|
if err == nil {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
return Fail(t, "An error is expected but got nil.", msgAndArgs...)
|
return Fail(t, "An error is expected but got nil.", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1553,6 +1621,7 @@ var spewConfig = spew.ConfigState{
|
|||||||
DisablePointerAddresses: true,
|
DisablePointerAddresses: true,
|
||||||
DisableCapacities: true,
|
DisableCapacities: true,
|
||||||
SortKeys: true,
|
SortKeys: true,
|
||||||
|
DisableMethods: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
type tHelper interface {
|
type tHelper interface {
|
||||||
|
25
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
25
vendor/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
@ -33,7 +33,6 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
|||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
|
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
|
||||||
@ -56,7 +55,6 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
|||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
|
||||||
@ -79,7 +77,6 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
|
|||||||
code, err := httpCode(handler, method, url, values)
|
code, err := httpCode(handler, method, url, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isErrorCode := code >= http.StatusBadRequest
|
isErrorCode := code >= http.StatusBadRequest
|
||||||
@ -90,6 +87,28 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
|
|||||||
return isErrorCode
|
return isErrorCode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCode asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
code, err := httpCode(handler, method, url, values)
|
||||||
|
if err != nil {
|
||||||
|
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
successful := code == statuscode
|
||||||
|
if !successful {
|
||||||
|
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code))
|
||||||
|
}
|
||||||
|
|
||||||
|
return successful
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPBody is a helper that returns HTTP body of the response. It returns
|
// HTTPBody is a helper that returns HTTP body of the response. It returns
|
||||||
// empty string if building a new request fails.
|
// empty string if building a new request fails.
|
||||||
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
||||||
|
74
vendor/github.com/stretchr/testify/require/require.go
generated
vendored
74
vendor/github.com/stretchr/testify/require/require.go
generated
vendored
@ -212,7 +212,7 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg
|
|||||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
// and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
|
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -315,7 +315,7 @@ func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ..
|
|||||||
|
|
||||||
// Exactlyf asserts that two objects are equal in value and type.
|
// Exactlyf asserts that two objects are equal in value and type.
|
||||||
//
|
//
|
||||||
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted")
|
||||||
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -470,7 +470,7 @@ func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, arg
|
|||||||
// Greaterf asserts that the first element is greater than the second
|
// Greaterf asserts that the first element is greater than the second
|
||||||
//
|
//
|
||||||
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
|
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
|
||||||
// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1))
|
// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted")
|
||||||
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
|
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
|
||||||
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
@ -565,7 +565,7 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string,
|
|||||||
//
|
//
|
||||||
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -595,7 +595,7 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url strin
|
|||||||
//
|
//
|
||||||
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -606,6 +606,36 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCode asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
if assert.HTTPStatusCode(t, handler, method, url, values, statuscode, msgAndArgs...) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
if assert.HTTPStatusCodef(t, handler, method, url, values, statuscode, msg, args...) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPSuccess asserts that a specified handler returns a success status code.
|
// HTTPSuccess asserts that a specified handler returns a success status code.
|
||||||
//
|
//
|
||||||
// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
|
// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
|
||||||
@ -651,7 +681,7 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
|
|||||||
|
|
||||||
// Implementsf asserts that an object is implemented by the specified interface.
|
// Implementsf asserts that an object is implemented by the specified interface.
|
||||||
//
|
//
|
||||||
// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||||
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -902,7 +932,7 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args .
|
|||||||
// Lessf asserts that the first element is less than the second
|
// Lessf asserts that the first element is less than the second
|
||||||
//
|
//
|
||||||
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
|
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
|
||||||
// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2))
|
// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted")
|
||||||
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
|
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
|
||||||
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
@ -1128,6 +1158,32 @@ func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs .
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotEqualValues asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// assert.NotEqualValues(t, obj1, obj2)
|
||||||
|
func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
if assert.NotEqualValues(t, expected, actual, msgAndArgs...) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted")
|
||||||
|
func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
if assert.NotEqualValuesf(t, expected, actual, msg, args...) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
// NotEqualf asserts that the specified values are NOT equal.
|
// NotEqualf asserts that the specified values are NOT equal.
|
||||||
//
|
//
|
||||||
// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
|
// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
|
||||||
@ -1212,7 +1268,7 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
|
|||||||
|
|
||||||
// NotRegexpf asserts that a specified regexp does not match a string.
|
// NotRegexpf asserts that a specified regexp does not match a string.
|
||||||
//
|
//
|
||||||
// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
|
||||||
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
||||||
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
|
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
@ -1406,7 +1462,7 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface
|
|||||||
|
|
||||||
// Regexpf asserts that a specified regexp matches a string.
|
// Regexpf asserts that a specified regexp matches a string.
|
||||||
//
|
//
|
||||||
// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
|
||||||
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
||||||
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
|
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
62
vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
62
vendor/github.com/stretchr/testify/require/require_forward.go
generated
vendored
@ -170,7 +170,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
|
|||||||
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
// EqualValuesf asserts that two objects are equal or convertable to the same types
|
||||||
// and equal.
|
// and equal.
|
||||||
//
|
//
|
||||||
// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
|
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
|
||||||
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -252,7 +252,7 @@ func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArg
|
|||||||
|
|
||||||
// Exactlyf asserts that two objects are equal in value and type.
|
// Exactlyf asserts that two objects are equal in value and type.
|
||||||
//
|
//
|
||||||
// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
|
// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted")
|
||||||
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -371,7 +371,7 @@ func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string,
|
|||||||
// Greaterf asserts that the first element is greater than the second
|
// Greaterf asserts that the first element is greater than the second
|
||||||
//
|
//
|
||||||
// a.Greaterf(2, 1, "error message %s", "formatted")
|
// a.Greaterf(2, 1, "error message %s", "formatted")
|
||||||
// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1))
|
// a.Greaterf(float64(2), float64(1), "error message %s", "formatted")
|
||||||
// a.Greaterf("b", "a", "error message %s", "formatted")
|
// a.Greaterf("b", "a", "error message %s", "formatted")
|
||||||
func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
@ -448,7 +448,7 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri
|
|||||||
//
|
//
|
||||||
// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -472,7 +472,7 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s
|
|||||||
//
|
//
|
||||||
// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -480,6 +480,30 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url
|
|||||||
HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
|
HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCode asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPStatusCodef asserts that a specified handler returns a specified status code.
|
||||||
|
//
|
||||||
|
// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPSuccess asserts that a specified handler returns a success status code.
|
// HTTPSuccess asserts that a specified handler returns a success status code.
|
||||||
//
|
//
|
||||||
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
||||||
@ -516,7 +540,7 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{},
|
|||||||
|
|
||||||
// Implementsf asserts that an object is implemented by the specified interface.
|
// Implementsf asserts that an object is implemented by the specified interface.
|
||||||
//
|
//
|
||||||
// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
|
||||||
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
h.Helper()
|
h.Helper()
|
||||||
@ -707,7 +731,7 @@ func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, ar
|
|||||||
// Lessf asserts that the first element is less than the second
|
// Lessf asserts that the first element is less than the second
|
||||||
//
|
//
|
||||||
// a.Lessf(1, 2, "error message %s", "formatted")
|
// a.Lessf(1, 2, "error message %s", "formatted")
|
||||||
// a.Lessf(float64(1, "error message %s", "formatted"), float64(2))
|
// a.Lessf(float64(1), float64(2), "error message %s", "formatted")
|
||||||
// a.Lessf("a", "b", "error message %s", "formatted")
|
// a.Lessf("a", "b", "error message %s", "formatted")
|
||||||
func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
@ -885,6 +909,26 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr
|
|||||||
NotEqual(a.t, expected, actual, msgAndArgs...)
|
NotEqual(a.t, expected, actual, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotEqualValues asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// a.NotEqualValues(obj1, obj2)
|
||||||
|
func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
NotEqualValues(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotEqualValuesf asserts that two objects are not equal even when converted to the same type
|
||||||
|
//
|
||||||
|
// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted")
|
||||||
|
func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
NotEqualValuesf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEqualf asserts that the specified values are NOT equal.
|
// NotEqualf asserts that the specified values are NOT equal.
|
||||||
//
|
//
|
||||||
// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
|
// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
|
||||||
@ -951,7 +995,7 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in
|
|||||||
|
|
||||||
// NotRegexpf asserts that a specified regexp does not match a string.
|
// NotRegexpf asserts that a specified regexp does not match a string.
|
||||||
//
|
//
|
||||||
// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted")
|
||||||
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
|
||||||
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
@ -1103,7 +1147,7 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter
|
|||||||
|
|
||||||
// Regexpf asserts that a specified regexp matches a string.
|
// Regexpf asserts that a specified regexp matches a string.
|
||||||
//
|
//
|
||||||
// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted")
|
||||||
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
|
||||||
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
|
func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
7
vendor/github.com/stretchr/testify/suite/interfaces.go
generated
vendored
7
vendor/github.com/stretchr/testify/suite/interfaces.go
generated
vendored
@ -44,3 +44,10 @@ type BeforeTest interface {
|
|||||||
type AfterTest interface {
|
type AfterTest interface {
|
||||||
AfterTest(suiteName, testName string)
|
AfterTest(suiteName, testName string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithStats implements HandleStats, a function that will be executed
|
||||||
|
// when a test suite is finished. The stats contain information about
|
||||||
|
// the execution of that suite and its tests.
|
||||||
|
type WithStats interface {
|
||||||
|
HandleStats(suiteName string, stats *SuiteInformation)
|
||||||
|
}
|
||||||
|
46
vendor/github.com/stretchr/testify/suite/stats.go
generated
vendored
Normal file
46
vendor/github.com/stretchr/testify/suite/stats.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package suite
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// SuiteInformation stats stores stats for the whole suite execution.
|
||||||
|
type SuiteInformation struct {
|
||||||
|
Start, End time.Time
|
||||||
|
TestStats map[string]*TestInformation
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestInformation stores information about the execution of each test.
|
||||||
|
type TestInformation struct {
|
||||||
|
TestName string
|
||||||
|
Start, End time.Time
|
||||||
|
Passed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSuiteInformation() *SuiteInformation {
|
||||||
|
testStats := make(map[string]*TestInformation)
|
||||||
|
|
||||||
|
return &SuiteInformation{
|
||||||
|
TestStats: testStats,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SuiteInformation) start(testName string) {
|
||||||
|
s.TestStats[testName] = &TestInformation{
|
||||||
|
TestName: testName,
|
||||||
|
Start: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SuiteInformation) end(testName string, passed bool) {
|
||||||
|
s.TestStats[testName].End = time.Now()
|
||||||
|
s.TestStats[testName].Passed = passed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SuiteInformation) Passed() bool {
|
||||||
|
for _, stats := range s.TestStats {
|
||||||
|
if !stats.Passed {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
102
vendor/github.com/stretchr/testify/suite/suite.go
generated
vendored
102
vendor/github.com/stretchr/testify/suite/suite.go
generated
vendored
@ -7,8 +7,8 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -81,43 +81,68 @@ func (suite *Suite) Run(name string, subtest func()) bool {
|
|||||||
// Run takes a testing suite and runs all of the tests attached
|
// Run takes a testing suite and runs all of the tests attached
|
||||||
// to it.
|
// to it.
|
||||||
func Run(t *testing.T, suite TestingSuite) {
|
func Run(t *testing.T, suite TestingSuite) {
|
||||||
testsSync := &sync.WaitGroup{}
|
|
||||||
suite.SetT(t)
|
|
||||||
defer failOnPanic(t)
|
defer failOnPanic(t)
|
||||||
|
|
||||||
suiteSetupDone := false
|
suite.SetT(t)
|
||||||
|
|
||||||
|
var suiteSetupDone bool
|
||||||
|
|
||||||
|
var stats *SuiteInformation
|
||||||
|
if _, ok := suite.(WithStats); ok {
|
||||||
|
stats = newSuiteInformation()
|
||||||
|
}
|
||||||
|
|
||||||
methodFinder := reflect.TypeOf(suite)
|
|
||||||
tests := []testing.InternalTest{}
|
tests := []testing.InternalTest{}
|
||||||
for index := 0; index < methodFinder.NumMethod(); index++ {
|
methodFinder := reflect.TypeOf(suite)
|
||||||
method := methodFinder.Method(index)
|
suiteName := methodFinder.Elem().Name()
|
||||||
|
|
||||||
|
for i := 0; i < methodFinder.NumMethod(); i++ {
|
||||||
|
method := methodFinder.Method(i)
|
||||||
|
|
||||||
ok, err := methodFilter(method.Name)
|
ok, err := methodFilter(method.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
|
fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !suiteSetupDone {
|
if !suiteSetupDone {
|
||||||
|
if stats != nil {
|
||||||
|
stats.Start = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
|
if setupAllSuite, ok := suite.(SetupAllSuite); ok {
|
||||||
setupAllSuite.SetupSuite()
|
setupAllSuite.SetupSuite()
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
|
|
||||||
testsSync.Wait()
|
|
||||||
tearDownAllSuite.TearDownSuite()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
suiteSetupDone = true
|
suiteSetupDone = true
|
||||||
}
|
}
|
||||||
|
|
||||||
test := testing.InternalTest{
|
test := testing.InternalTest{
|
||||||
Name: method.Name,
|
Name: method.Name,
|
||||||
F: func(t *testing.T) {
|
F: func(t *testing.T) {
|
||||||
defer testsSync.Done()
|
|
||||||
parentT := suite.T()
|
parentT := suite.T()
|
||||||
suite.SetT(t)
|
suite.SetT(t)
|
||||||
defer failOnPanic(t)
|
defer failOnPanic(t)
|
||||||
|
defer func() {
|
||||||
|
if stats != nil {
|
||||||
|
passed := !t.Failed()
|
||||||
|
stats.end(method.Name, passed)
|
||||||
|
}
|
||||||
|
|
||||||
|
if afterTestSuite, ok := suite.(AfterTest); ok {
|
||||||
|
afterTestSuite.AfterTest(suiteName, method.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok {
|
||||||
|
tearDownTestSuite.TearDownTest()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.SetT(parentT)
|
||||||
|
}()
|
||||||
|
|
||||||
if setupTestSuite, ok := suite.(SetupTestSuite); ok {
|
if setupTestSuite, ok := suite.(SetupTestSuite); ok {
|
||||||
setupTestSuite.SetupTest()
|
setupTestSuite.SetupTest()
|
||||||
@ -125,25 +150,47 @@ func Run(t *testing.T, suite TestingSuite) {
|
|||||||
if beforeTestSuite, ok := suite.(BeforeTest); ok {
|
if beforeTestSuite, ok := suite.(BeforeTest); ok {
|
||||||
beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name)
|
beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name)
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if afterTestSuite, ok := suite.(AfterTest); ok {
|
if stats != nil {
|
||||||
afterTestSuite.AfterTest(methodFinder.Elem().Name(), method.Name)
|
stats.start(method.Name)
|
||||||
}
|
}
|
||||||
if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok {
|
|
||||||
tearDownTestSuite.TearDownTest()
|
|
||||||
}
|
|
||||||
suite.SetT(parentT)
|
|
||||||
}()
|
|
||||||
method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})
|
method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
tests = append(tests, test)
|
tests = append(tests, test)
|
||||||
testsSync.Add(1)
|
|
||||||
}
|
}
|
||||||
|
if suiteSetupDone {
|
||||||
|
defer func() {
|
||||||
|
if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok {
|
||||||
|
tearDownAllSuite.TearDownSuite()
|
||||||
|
}
|
||||||
|
|
||||||
|
if suiteWithStats, measureStats := suite.(WithStats); measureStats {
|
||||||
|
stats.End = time.Now()
|
||||||
|
suiteWithStats.HandleStats(suiteName, stats)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
runTests(t, tests)
|
runTests(t, tests)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filtering method according to set regular expression
|
||||||
|
// specified command-line argument -m
|
||||||
|
func methodFilter(name string) (bool, error) {
|
||||||
|
if ok, _ := regexp.MatchString("^Test", name); !ok {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return regexp.MatchString(*matchMethod, name)
|
||||||
|
}
|
||||||
|
|
||||||
func runTests(t testing.TB, tests []testing.InternalTest) {
|
func runTests(t testing.TB, tests []testing.InternalTest) {
|
||||||
|
if len(tests) == 0 {
|
||||||
|
t.Log("warning: no tests to run")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
r, ok := t.(runner)
|
r, ok := t.(runner)
|
||||||
if !ok { // backwards compatibility with Go 1.6 and below
|
if !ok { // backwards compatibility with Go 1.6 and below
|
||||||
if !testing.RunTests(allTestsFilter, tests) {
|
if !testing.RunTests(allTestsFilter, tests) {
|
||||||
@ -157,15 +204,6 @@ func runTests(t testing.TB, tests []testing.InternalTest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filtering method according to set regular expression
|
|
||||||
// specified command-line argument -m
|
|
||||||
func methodFilter(name string) (bool, error) {
|
|
||||||
if ok, _ := regexp.MatchString("^Test", name); !ok {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return regexp.MatchString(*matchMethod, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
type runner interface {
|
type runner interface {
|
||||||
Run(name string, f func(t *testing.T)) bool
|
Run(name string, f func(t *testing.T)) bool
|
||||||
}
|
}
|
||||||
|
4
vendor/gomod.garykim.dev/nc-talk/.drone.yml
vendored
4
vendor/gomod.garykim.dev/nc-talk/.drone.yml
vendored
@ -7,6 +7,10 @@ steps:
|
|||||||
image: golangci/golangci-lint:latest-alpine
|
image: golangci/golangci-lint:latest-alpine
|
||||||
commands:
|
commands:
|
||||||
- golangci-lint run
|
- golangci-lint run
|
||||||
|
- name: test
|
||||||
|
image: golang:1.13
|
||||||
|
commands:
|
||||||
|
- go test ./...
|
||||||
- name: build-test
|
- name: build-test
|
||||||
image: golang:1.13
|
image: golang:1.13
|
||||||
commands:
|
commands:
|
||||||
|
37
vendor/gomod.garykim.dev/nc-talk/CHANGELOG.md
vendored
37
vendor/gomod.garykim.dev/nc-talk/CHANGELOG.md
vendored
@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v0.1.1](https://github.com/gary-kim/go-nc-talk/tree/v0.1.1) - 2020-08-24
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/gary-kim/go-nc-talk/compare/v0.1.0...v0.1.1)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- ROS type should be of ROST type [\#12](https://github.com/gary-kim/go-nc-talk/pull/12) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
- Fix error when sending a message with no RCS data [\#10](https://github.com/gary-kim/go-nc-talk/pull/10) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
|
||||||
|
## [v0.1.0](https://github.com/gary-kim/go-nc-talk/tree/v0.1.0) - 2020-08-13
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/gary-kim/go-nc-talk/compare/v0.0.2...v0.1.0)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add TLSConfig [\#9](https://github.com/gary-kim/go-nc-talk/pull/9) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
- Add Software using this library in README [\#8](https://github.com/gary-kim/go-nc-talk/pull/8) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
- Add some basic tests [\#7](https://github.com/gary-kim/go-nc-talk/pull/7) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
- Add support for downloading files [\#1](https://github.com/gary-kim/go-nc-talk/pull/1) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Return error on blank token [\#6](https://github.com/gary-kim/go-nc-talk/pull/6) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
- Add v0.0.2 to changelog [\#4](https://github.com/gary-kim/go-nc-talk/pull/4) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
|
||||||
|
## [v0.0.2](https://github.com/gary-kim/go-nc-talk/tree/v0.0.2) - 2020-07-26
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/gary-kim/go-nc-talk/compare/v0.0.1...v0.0.2)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add installation instructions to README.md [\#2](https://github.com/gary-kim/go-nc-talk/pull/2) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix Capabilities Request [\#3](https://github.com/gary-kim/go-nc-talk/pull/3) ([@gary-kim](https://github.com/gary-kim))
|
||||||
|
|
||||||
## [v0.0.1](https://github.com/gary-kim/riotchat/tree/v0.0.1) - 2020-07-10
|
## [v0.0.1](https://github.com/gary-kim/riotchat/tree/v0.0.1) - 2020-07-10
|
||||||
|
|
||||||
* First release
|
* First release
|
||||||
|
5
vendor/gomod.garykim.dev/nc-talk/README.md
vendored
5
vendor/gomod.garykim.dev/nc-talk/README.md
vendored
@ -15,6 +15,11 @@ GO111MODULE=on go get gomod.garykim.dev/nc-talk
|
|||||||
|
|
||||||
Check out the documentation for the package [here](https://pkg.go.dev/gomod.garykim.dev/nc-talk).
|
Check out the documentation for the package [here](https://pkg.go.dev/gomod.garykim.dev/nc-talk).
|
||||||
|
|
||||||
|
|
||||||
|
### Software using this library
|
||||||
|
|
||||||
|
* [Matterbridge](https://github.com/42wim/matterbridge)
|
||||||
|
|
||||||
### License
|
### License
|
||||||
|
|
||||||
Copyright © 2020 Gary Kim <<gary@garykim.dev>>, All Rights Reserved
|
Copyright © 2020 Gary Kim <<gary@garykim.dev>>, All Rights Reserved
|
||||||
|
@ -18,3 +18,8 @@ const (
|
|||||||
// BaseEndpoint is the api endpoint for Nextcloud Talk
|
// BaseEndpoint is the api endpoint for Nextcloud Talk
|
||||||
BaseEndpoint = "/ocs/v2.php/apps/spreed/api/v1/"
|
BaseEndpoint = "/ocs/v2.php/apps/spreed/api/v1/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RemoteDavEndpoint returns the endpoint for the Dav API for Nextcloud
|
||||||
|
func RemoteDavEndpoint(username string, davType string) string {
|
||||||
|
return "/remote.php/dav/" + username + "/" + davType + "/"
|
||||||
|
}
|
||||||
|
5
vendor/gomod.garykim.dev/nc-talk/go.mod
vendored
5
vendor/gomod.garykim.dev/nc-talk/go.mod
vendored
@ -2,4 +2,7 @@ module gomod.garykim.dev/nc-talk
|
|||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require github.com/monaco-io/request v1.0.3
|
require (
|
||||||
|
github.com/monaco-io/request v1.0.4
|
||||||
|
github.com/stretchr/testify v1.6.1
|
||||||
|
)
|
||||||
|
13
vendor/gomod.garykim.dev/nc-talk/go.sum
vendored
13
vendor/gomod.garykim.dev/nc-talk/go.sum
vendored
@ -1,2 +1,15 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/monaco-io/request v1.0.3 h1:FsiIwXCCbHEyWx9A7lgg6JBTMHhHlEEsADsgAOvZ9HA=
|
github.com/monaco-io/request v1.0.3 h1:FsiIwXCCbHEyWx9A7lgg6JBTMHhHlEEsADsgAOvZ9HA=
|
||||||
github.com/monaco-io/request v1.0.3/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ=
|
github.com/monaco-io/request v1.0.3/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ=
|
||||||
|
github.com/monaco-io/request v1.0.4 h1:AbogA+IvPOWqyGZIFU7kSb8YS2Jv5Dnl5ncMj8cQV+o=
|
||||||
|
github.com/monaco-io/request v1.0.4/go.mod h1:EmggwHktBsbJmCgwZXqy7o0H1NNsAstQBWZrFVd3xtQ=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
4
vendor/gomod.garykim.dev/nc-talk/gonctalk.go
vendored
4
vendor/gomod.garykim.dev/nc-talk/gonctalk.go
vendored
@ -21,6 +21,8 @@ import (
|
|||||||
|
|
||||||
// NewUser returns a TalkUser instance
|
// NewUser returns a TalkUser instance
|
||||||
// The url should be the full URL of the Nextcloud instance (e.g. https://cloud.mydomain.me)
|
// The url should be the full URL of the Nextcloud instance (e.g. https://cloud.mydomain.me)
|
||||||
|
//
|
||||||
|
// Deprecated: Use user.NewUser instead for more options and error checks
|
||||||
func NewUser(url string, username string, password string) *user.TalkUser {
|
func NewUser(url string, username string, password string) *user.TalkUser {
|
||||||
return &user.TalkUser{
|
return &user.TalkUser{
|
||||||
NextcloudURL: url,
|
NextcloudURL: url,
|
||||||
@ -31,6 +33,8 @@ func NewUser(url string, username string, password string) *user.TalkUser {
|
|||||||
|
|
||||||
// NewRoom returns a new TalkRoom instance
|
// NewRoom returns a new TalkRoom instance
|
||||||
// Token should be the Nextcloud Room Token (e.g. "d6zoa2zs" if the room URL is https://cloud.mydomain.me/call/d6zoa2zs)
|
// Token should be the Nextcloud Room Token (e.g. "d6zoa2zs" if the room URL is https://cloud.mydomain.me/call/d6zoa2zs)
|
||||||
|
//
|
||||||
|
// Deprecated: Use room.NewRoom instead for extra error checks.
|
||||||
func NewRoom(tuser *user.TalkUser, token string) *room.TalkRoom {
|
func NewRoom(tuser *user.TalkUser, token string) *room.TalkRoom {
|
||||||
tr := &room.TalkRoom{
|
tr := &room.TalkRoom{
|
||||||
User: tuser,
|
User: tuser,
|
||||||
|
90
vendor/gomod.garykim.dev/nc-talk/ocs/message.go
vendored
90
vendor/gomod.garykim.dev/nc-talk/ocs/message.go
vendored
@ -14,6 +14,11 @@
|
|||||||
|
|
||||||
package ocs
|
package ocs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// MessageType describes what kind of message a returned Nextcloud Talk message is
|
// MessageType describes what kind of message a returned Nextcloud Talk message is
|
||||||
type MessageType string
|
type MessageType string
|
||||||
|
|
||||||
@ -37,16 +42,101 @@ type TalkRoomMessageData struct {
|
|||||||
SystemMessage string `json:"systemMessage"`
|
SystemMessage string `json:"systemMessage"`
|
||||||
Timestamp int `json:"timestamp"`
|
Timestamp int `json:"timestamp"`
|
||||||
MessageType MessageType `json:"messageType"`
|
MessageType MessageType `json:"messageType"`
|
||||||
|
MessageParameters map[string]RichObjectString `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// talkRoomMessageParameters is used to unmarshal only MessageParameters
|
||||||
|
type talkRoomMessageParameters struct {
|
||||||
|
MessageParameters map[string]RichObjectString `json:"messageParameters"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlainMessage returns the message string with placeholders replaced
|
||||||
|
//
|
||||||
|
// * User and group placeholders will be replaced with the name of the user or group respectively.
|
||||||
|
//
|
||||||
|
// * File placeholders will be replaced with the name of the file.
|
||||||
|
func (m *TalkRoomMessageData) PlainMessage() string {
|
||||||
|
tr := m.Message
|
||||||
|
for key, value := range m.MessageParameters {
|
||||||
|
tr = strings.ReplaceAll(tr, "{"+key+"}", value.Name)
|
||||||
|
}
|
||||||
|
return tr
|
||||||
}
|
}
|
||||||
|
|
||||||
// TalkRoomMessage describes an ocs response for a Talk room message
|
// TalkRoomMessage describes an ocs response for a Talk room message
|
||||||
type TalkRoomMessage struct {
|
type TalkRoomMessage struct {
|
||||||
|
OCS talkRoomMessage `json:"ocs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type talkRoomMessage struct {
|
||||||
ocs
|
ocs
|
||||||
TalkRoomMessage []TalkRoomMessageData `json:"data"`
|
TalkRoomMessage []TalkRoomMessageData `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TalkRoomMessageDataUnmarshal unmarshals given ocs request data and returns a TalkRoomMessageData
|
||||||
|
func TalkRoomMessageDataUnmarshal(data *[]byte) (*TalkRoomMessage, error) {
|
||||||
|
message := &TalkRoomMessage{}
|
||||||
|
err := json.Unmarshal(*data, message)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get RCS
|
||||||
|
var rcs struct {
|
||||||
|
OCS struct {
|
||||||
|
ocs
|
||||||
|
TalkRoomMessage []talkRoomMessageParameters `json:"data"`
|
||||||
|
} `json:"ocs"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(*data, &rcs)
|
||||||
|
// There is no RCS data
|
||||||
|
if err != nil {
|
||||||
|
for i := range message.OCS.TalkRoomMessage {
|
||||||
|
message.OCS.TalkRoomMessage[i].MessageParameters = map[string]RichObjectString{}
|
||||||
|
}
|
||||||
|
return message, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is RCS data
|
||||||
|
for i := range message.OCS.TalkRoomMessage {
|
||||||
|
message.OCS.TalkRoomMessage[i].MessageParameters = rcs.OCS.TalkRoomMessage[i].MessageParameters
|
||||||
|
}
|
||||||
|
return message, nil
|
||||||
|
}
|
||||||
|
|
||||||
// TalkRoomSentResponse describes an ocs response for what is returned when a message is sent
|
// TalkRoomSentResponse describes an ocs response for what is returned when a message is sent
|
||||||
type TalkRoomSentResponse struct {
|
type TalkRoomSentResponse struct {
|
||||||
|
OCS talkRoomSentResponse `json:"ocs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type talkRoomSentResponse struct {
|
||||||
ocs
|
ocs
|
||||||
TalkRoomMessage TalkRoomMessageData `json:"data"`
|
TalkRoomMessage TalkRoomMessageData `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TalkRoomSentResponseUnmarshal unmarshals given ocs request data and returns a TalkRoomMessageData
|
||||||
|
func TalkRoomSentResponseUnmarshal(data *[]byte) (*TalkRoomSentResponse, error) {
|
||||||
|
message := &TalkRoomSentResponse{}
|
||||||
|
err := json.Unmarshal(*data, message)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get RCS
|
||||||
|
var rcs struct {
|
||||||
|
OCS struct {
|
||||||
|
ocs
|
||||||
|
TalkRoomMessage talkRoomMessageParameters `json:"data"`
|
||||||
|
} `json:"ocs"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(*data, &rcs)
|
||||||
|
// There is no RCS data
|
||||||
|
if err != nil {
|
||||||
|
message.OCS.TalkRoomMessage.MessageParameters = map[string]RichObjectString{}
|
||||||
|
return message, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is RCS data
|
||||||
|
message.OCS.TalkRoomMessage.MessageParameters = rcs.OCS.TalkRoomMessage.MessageParameters
|
||||||
|
return message, nil
|
||||||
|
}
|
||||||
|
38
vendor/gomod.garykim.dev/nc-talk/ocs/ros.go
vendored
Normal file
38
vendor/gomod.garykim.dev/nc-talk/ocs/ros.go
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) 2020 Gary Kim <gary@garykim.dev>, All Rights Reserved
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// File describes Nextcloud's Rich Object Strings (https://github.com/nextcloud/server/issues/1706)
|
||||||
|
|
||||||
|
package ocs
|
||||||
|
|
||||||
|
// RichObjectString describes the content of placeholders in TalkRoomMessageData
|
||||||
|
type RichObjectString struct {
|
||||||
|
Type RichObjectStringType `json:"type"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Link string `json:"link"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RichObjectStringType describes what a rich object string is describing
|
||||||
|
type RichObjectStringType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ROSTypeUser describes a rich object string that is a user
|
||||||
|
ROSTypeUser RichObjectStringType = "user"
|
||||||
|
// ROSTypeGroup describes a rich object string that is a group
|
||||||
|
ROSTypeGroup RichObjectStringType = "group"
|
||||||
|
// ROSTypeFile describes a rich object string that is a file
|
||||||
|
ROSTypeFile RichObjectStringType = "file"
|
||||||
|
)
|
53
vendor/gomod.garykim.dev/nc-talk/room/room.go
vendored
53
vendor/gomod.garykim.dev/nc-talk/room/room.go
vendored
@ -16,7 +16,6 @@ package room
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"time"
|
"time"
|
||||||
@ -28,12 +27,38 @@ import (
|
|||||||
"gomod.garykim.dev/nc-talk/user"
|
"gomod.garykim.dev/nc-talk/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrEmptyToken is returned when the room token is empty
|
||||||
|
ErrEmptyToken = errors.New("given an empty token")
|
||||||
|
// ErrRoomNotFound is returned when a room with the given token could not be found
|
||||||
|
ErrRoomNotFound = errors.New("room could not be found")
|
||||||
|
// ErrNotModeratorInLobby is returned when the room is in lobby mode but the user is not a moderator
|
||||||
|
ErrNotModeratorInLobby = errors.New("room is in lobby mode but user is not a moderator")
|
||||||
|
// ErrUnexpectedReturnCode is returned when the server did not respond with an expected return code
|
||||||
|
ErrUnexpectedReturnCode = errors.New("unexpected return code")
|
||||||
|
)
|
||||||
|
|
||||||
// TalkRoom represents a room in Nextcloud Talk
|
// TalkRoom represents a room in Nextcloud Talk
|
||||||
type TalkRoom struct {
|
type TalkRoom struct {
|
||||||
User *user.TalkUser
|
User *user.TalkUser
|
||||||
Token string
|
Token string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTalkRoom returns a new TalkRoom instance
|
||||||
|
// Token should be the Nextcloud Room Token (e.g. "d6zoa2zs" if the room URL is https://cloud.mydomain.me/call/d6zoa2zs)
|
||||||
|
func NewTalkRoom(tuser *user.TalkUser, token string) (*TalkRoom, error) {
|
||||||
|
if token == "" {
|
||||||
|
return nil, ErrEmptyToken
|
||||||
|
}
|
||||||
|
if tuser == nil {
|
||||||
|
return nil, user.ErrUserIsNil
|
||||||
|
}
|
||||||
|
return &TalkRoom{
|
||||||
|
User: tuser,
|
||||||
|
Token: token,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SendMessage sends a message in the Talk room
|
// SendMessage sends a message in the Talk room
|
||||||
func (t *TalkRoom) SendMessage(msg string) (*ocs.TalkRoomMessageData, error) {
|
func (t *TalkRoom) SendMessage(msg string) (*ocs.TalkRoomMessageData, error) {
|
||||||
url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token
|
url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token
|
||||||
@ -51,18 +76,22 @@ func (t *TalkRoom) SendMessage(msg string) (*ocs.TalkRoomMessageData, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if res.StatusCode() != 201 {
|
if res.StatusCode() != 201 {
|
||||||
return nil, errors.New("unexpected return code")
|
return nil, ErrUnexpectedReturnCode
|
||||||
}
|
}
|
||||||
var msgInfo struct {
|
msgInfo, err := ocs.TalkRoomSentResponseUnmarshal(&res.Data)
|
||||||
OCS ocs.TalkRoomSentResponse `json:"ocs"`
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(res.Data, &msgInfo)
|
|
||||||
return &msgInfo.OCS.TalkRoomMessage, err
|
return &msgInfo.OCS.TalkRoomMessage, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiveMessages starts watching for new messages
|
// ReceiveMessages starts watching for new messages
|
||||||
func (t *TalkRoom) ReceiveMessages(ctx context.Context) (chan ocs.TalkRoomMessageData, error) {
|
func (t *TalkRoom) ReceiveMessages(ctx context.Context) (chan ocs.TalkRoomMessageData, error) {
|
||||||
c := make(chan ocs.TalkRoomMessageData)
|
c := make(chan ocs.TalkRoomMessageData)
|
||||||
|
err := t.TestConnection()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token
|
url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token
|
||||||
requestParam := map[string]string{
|
requestParam := map[string]string{
|
||||||
"lookIntoFuture": "1",
|
"lookIntoFuture": "1",
|
||||||
@ -99,14 +128,11 @@ func (t *TalkRoom) ReceiveMessages(ctx context.Context) (chan ocs.TalkRoomMessag
|
|||||||
}
|
}
|
||||||
if res.StatusCode == 200 {
|
if res.StatusCode == 200 {
|
||||||
lastKnown = res.Header.Get("X-Chat-Last-Given")
|
lastKnown = res.Header.Get("X-Chat-Last-Given")
|
||||||
var message struct {
|
|
||||||
OCS ocs.TalkRoomMessage `json:"ocs"`
|
|
||||||
}
|
|
||||||
data, err := ioutil.ReadAll(res.Body)
|
data, err := ioutil.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(data, &message)
|
message, err := ocs.TalkRoomMessageDataUnmarshal(&data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -121,6 +147,9 @@ func (t *TalkRoom) ReceiveMessages(ctx context.Context) (chan ocs.TalkRoomMessag
|
|||||||
|
|
||||||
// TestConnection tests the connection with the Nextcloud Talk instance and returns an error if it could not connect
|
// TestConnection tests the connection with the Nextcloud Talk instance and returns an error if it could not connect
|
||||||
func (t *TalkRoom) TestConnection() error {
|
func (t *TalkRoom) TestConnection() error {
|
||||||
|
if t.Token == "" {
|
||||||
|
return ErrEmptyToken
|
||||||
|
}
|
||||||
url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token
|
url := t.User.NextcloudURL + constants.BaseEndpoint + "/chat/" + t.Token
|
||||||
requestParam := map[string]string{
|
requestParam := map[string]string{
|
||||||
"lookIntoFuture": "0",
|
"lookIntoFuture": "0",
|
||||||
@ -142,9 +171,9 @@ func (t *TalkRoom) TestConnection() error {
|
|||||||
case 304:
|
case 304:
|
||||||
return nil
|
return nil
|
||||||
case 404:
|
case 404:
|
||||||
return errors.New("room could not be found")
|
return ErrRoomNotFound
|
||||||
case 412:
|
case 412:
|
||||||
return errors.New("room is in lobby mode but user is not a moderator")
|
return ErrNotModeratorInLobby
|
||||||
}
|
}
|
||||||
return errors.New("unknown return code")
|
return ErrUnexpectedReturnCode
|
||||||
}
|
}
|
||||||
|
46
vendor/gomod.garykim.dev/nc-talk/user/user.go
vendored
46
vendor/gomod.garykim.dev/nc-talk/user/user.go
vendored
@ -15,11 +15,14 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/monaco-io/request"
|
"github.com/monaco-io/request"
|
||||||
|
|
||||||
|
"gomod.garykim.dev/nc-talk/constants"
|
||||||
"gomod.garykim.dev/nc-talk/ocs"
|
"gomod.garykim.dev/nc-talk/ocs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,14 +30,25 @@ const (
|
|||||||
ocsCapabilitiesEndpoint = "/ocs/v2.php/cloud/capabilities"
|
ocsCapabilitiesEndpoint = "/ocs/v2.php/cloud/capabilities"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrUserIsNil is returned when a funciton is called with an nil user.
|
||||||
|
ErrUserIsNil = errors.New("user is nil")
|
||||||
|
)
|
||||||
|
|
||||||
// TalkUser represents a user of Nextcloud Talk
|
// TalkUser represents a user of Nextcloud Talk
|
||||||
type TalkUser struct {
|
type TalkUser struct {
|
||||||
User string
|
User string
|
||||||
Pass string
|
Pass string
|
||||||
NextcloudURL string
|
NextcloudURL string
|
||||||
|
Config *TalkUserConfig
|
||||||
capabilities *Capabilities
|
capabilities *Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TalkUserConfig is configuration options for TalkUsers
|
||||||
|
type TalkUserConfig struct {
|
||||||
|
TLSConfig *tls.Config
|
||||||
|
}
|
||||||
|
|
||||||
// Capabilities describes the capabilities that the Nextcloud Talk instance is capable of. Visit https://nextcloud-talk.readthedocs.io/en/latest/capabilities/ for more info.
|
// Capabilities describes the capabilities that the Nextcloud Talk instance is capable of. Visit https://nextcloud-talk.readthedocs.io/en/latest/capabilities/ for more info.
|
||||||
type Capabilities struct {
|
type Capabilities struct {
|
||||||
AttachmentsFolder string `ocscapability:"config => attachments => folder"`
|
AttachmentsFolder string `ocscapability:"config => attachments => folder"`
|
||||||
@ -70,6 +84,17 @@ type Capabilities struct {
|
|||||||
ChatReferenceID bool `ocscapability:"chat-reference-id"`
|
ChatReferenceID bool `ocscapability:"chat-reference-id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewUser returns a TalkUser instance
|
||||||
|
// The url should be the full URL of the Nextcloud instance (e.g. https://cloud.mydomain.me)
|
||||||
|
func NewUser(url string, username string, password string, config *TalkUserConfig) (*TalkUser, error) {
|
||||||
|
return &TalkUser{
|
||||||
|
NextcloudURL: url,
|
||||||
|
User: username,
|
||||||
|
Pass: password,
|
||||||
|
Config: config,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RequestClient returns a monaco-io that is preconfigured to make OCS API calls
|
// RequestClient returns a monaco-io that is preconfigured to make OCS API calls
|
||||||
func (t *TalkUser) RequestClient(client request.Client) *request.Client {
|
func (t *TalkUser) RequestClient(client request.Client) *request.Client {
|
||||||
if client.Header == nil {
|
if client.Header == nil {
|
||||||
@ -91,6 +116,11 @@ func (t *TalkUser) RequestClient(client request.Client) *request.Client {
|
|||||||
client.URL = t.NextcloudURL + "/" + client.URL
|
client.URL = t.NextcloudURL + "/" + client.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set TLS Config
|
||||||
|
if t.Config != nil {
|
||||||
|
client.TLSConfig = t.Config.TLSConfig
|
||||||
|
}
|
||||||
|
|
||||||
return &client
|
return &client
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,3 +196,19 @@ func sliceContains(s []string, search string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DownloadFile downloads the file at the given path
|
||||||
|
//
|
||||||
|
// Meant to be used with rich object string's path.
|
||||||
|
func (t *TalkUser) DownloadFile(path string) (data *[]byte, err error) {
|
||||||
|
url := t.NextcloudURL + constants.RemoteDavEndpoint(t.User, "files") + path
|
||||||
|
c := t.RequestClient(request.Client{
|
||||||
|
URL: url,
|
||||||
|
})
|
||||||
|
res, err := c.Do()
|
||||||
|
if err != nil || res.StatusCode() != 200 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data = &res.Data
|
||||||
|
return
|
||||||
|
}
|
||||||
|
16
vendor/gopkg.in/yaml.v3/.travis.yml
generated
vendored
Normal file
16
vendor/gopkg.in/yaml.v3/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- "1.4.x"
|
||||||
|
- "1.5.x"
|
||||||
|
- "1.6.x"
|
||||||
|
- "1.7.x"
|
||||||
|
- "1.8.x"
|
||||||
|
- "1.9.x"
|
||||||
|
- "1.10.x"
|
||||||
|
- "1.11.x"
|
||||||
|
- "1.12.x"
|
||||||
|
- "1.13.x"
|
||||||
|
- "tip"
|
||||||
|
|
||||||
|
go_import_path: gopkg.in/yaml.v3
|
50
vendor/gopkg.in/yaml.v3/LICENSE
generated
vendored
Normal file
50
vendor/gopkg.in/yaml.v3/LICENSE
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
This project is covered by two different licenses: MIT and Apache.
|
||||||
|
|
||||||
|
#### MIT License ####
|
||||||
|
|
||||||
|
The following files were ported to Go from C files of libyaml, and thus
|
||||||
|
are still covered by their original MIT license, with the additional
|
||||||
|
copyright staring in 2011 when the project was ported over:
|
||||||
|
|
||||||
|
apic.go emitterc.go parserc.go readerc.go scannerc.go
|
||||||
|
writerc.go yamlh.go yamlprivateh.go
|
||||||
|
|
||||||
|
Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
Copyright (c) 2006-2011 Kirill Simonov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
### Apache License ###
|
||||||
|
|
||||||
|
All the remaining project files are covered by the Apache license:
|
||||||
|
|
||||||
|
Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
13
vendor/gopkg.in/yaml.v3/NOTICE
generated
vendored
Normal file
13
vendor/gopkg.in/yaml.v3/NOTICE
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Copyright 2011-2016 Canonical Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
150
vendor/gopkg.in/yaml.v3/README.md
generated
vendored
Normal file
150
vendor/gopkg.in/yaml.v3/README.md
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# YAML support for the Go language
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
The yaml package enables Go programs to comfortably encode and decode YAML
|
||||||
|
values. It was developed within [Canonical](https://www.canonical.com) as
|
||||||
|
part of the [juju](https://juju.ubuntu.com) project, and is based on a
|
||||||
|
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
|
||||||
|
C library to parse and generate YAML data quickly and reliably.
|
||||||
|
|
||||||
|
Compatibility
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The yaml package supports most of YAML 1.2, but preserves some behavior
|
||||||
|
from 1.1 for backwards compatibility.
|
||||||
|
|
||||||
|
Specifically, as of v3 of the yaml package:
|
||||||
|
|
||||||
|
- YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being
|
||||||
|
decoded into a typed bool value. Otherwise they behave as a string. Booleans
|
||||||
|
in YAML 1.2 are _true/false_ only.
|
||||||
|
- Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_
|
||||||
|
as specified in YAML 1.2, because most parsers still use the old format.
|
||||||
|
Octals in the _0o777_ format are supported though, so new files work.
|
||||||
|
- Does not support base-60 floats. These are gone from YAML 1.2, and were
|
||||||
|
actually never supported by this package as it's clearly a poor choice.
|
||||||
|
|
||||||
|
and offers backwards
|
||||||
|
compatibility with YAML 1.1 in some cases.
|
||||||
|
1.2, including support for
|
||||||
|
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
|
||||||
|
implemented, and base-60 floats from YAML 1.1 are purposefully not
|
||||||
|
supported since they're a poor design and are gone in YAML 1.2.
|
||||||
|
|
||||||
|
Installation and usage
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The import path for the package is *gopkg.in/yaml.v3*.
|
||||||
|
|
||||||
|
To install it, run:
|
||||||
|
|
||||||
|
go get gopkg.in/yaml.v3
|
||||||
|
|
||||||
|
API documentation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
If opened in a browser, the import path itself leads to the API documentation:
|
||||||
|
|
||||||
|
- [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)
|
||||||
|
|
||||||
|
API stability
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in).
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
The yaml package is licensed under the MIT and Apache License 2.0 licenses.
|
||||||
|
Please see the LICENSE file for details.
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
```Go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var data = `
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d: [3, 4]
|
||||||
|
`
|
||||||
|
|
||||||
|
// Note: struct fields must be public in order for unmarshal to
|
||||||
|
// correctly populate the data.
|
||||||
|
type T struct {
|
||||||
|
A string
|
||||||
|
B struct {
|
||||||
|
RenamedC int `yaml:"c"`
|
||||||
|
D []int `yaml:",flow"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := T{}
|
||||||
|
|
||||||
|
err := yaml.Unmarshal([]byte(data), &t)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- t:\n%v\n\n", t)
|
||||||
|
|
||||||
|
d, err := yaml.Marshal(&t)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- t dump:\n%s\n\n", string(d))
|
||||||
|
|
||||||
|
m := make(map[interface{}]interface{})
|
||||||
|
|
||||||
|
err = yaml.Unmarshal([]byte(data), &m)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- m:\n%v\n\n", m)
|
||||||
|
|
||||||
|
d, err = yaml.Marshal(&m)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- m dump:\n%s\n\n", string(d))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This example will generate the following output:
|
||||||
|
|
||||||
|
```
|
||||||
|
--- t:
|
||||||
|
{Easy! {2 [3 4]}}
|
||||||
|
|
||||||
|
--- t dump:
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d: [3, 4]
|
||||||
|
|
||||||
|
|
||||||
|
--- m:
|
||||||
|
map[a:Easy! b:map[c:2 d:[3 4]]]
|
||||||
|
|
||||||
|
--- m dump:
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d:
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
```
|
||||||
|
|
746
vendor/gopkg.in/yaml.v3/apic.go
generated
vendored
Normal file
746
vendor/gopkg.in/yaml.v3/apic.go
generated
vendored
Normal file
@ -0,0 +1,746 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
// so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
|
||||||
|
//fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
|
||||||
|
|
||||||
|
// Check if we can move the queue at the beginning of the buffer.
|
||||||
|
if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
|
||||||
|
if parser.tokens_head != len(parser.tokens) {
|
||||||
|
copy(parser.tokens, parser.tokens[parser.tokens_head:])
|
||||||
|
}
|
||||||
|
parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
|
||||||
|
parser.tokens_head = 0
|
||||||
|
}
|
||||||
|
parser.tokens = append(parser.tokens, *token)
|
||||||
|
if pos < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
|
||||||
|
parser.tokens[parser.tokens_head+pos] = *token
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new parser object.
|
||||||
|
func yaml_parser_initialize(parser *yaml_parser_t) bool {
|
||||||
|
*parser = yaml_parser_t{
|
||||||
|
raw_buffer: make([]byte, 0, input_raw_buffer_size),
|
||||||
|
buffer: make([]byte, 0, input_buffer_size),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy a parser object.
|
||||||
|
func yaml_parser_delete(parser *yaml_parser_t) {
|
||||||
|
*parser = yaml_parser_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String read handler.
|
||||||
|
func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||||
|
if parser.input_pos == len(parser.input) {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
n = copy(buffer, parser.input[parser.input_pos:])
|
||||||
|
parser.input_pos += n
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader read handler.
|
||||||
|
func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||||
|
return parser.input_reader.Read(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a string input.
|
||||||
|
func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
|
||||||
|
if parser.read_handler != nil {
|
||||||
|
panic("must set the input source only once")
|
||||||
|
}
|
||||||
|
parser.read_handler = yaml_string_read_handler
|
||||||
|
parser.input = input
|
||||||
|
parser.input_pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a file input.
|
||||||
|
func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
|
||||||
|
if parser.read_handler != nil {
|
||||||
|
panic("must set the input source only once")
|
||||||
|
}
|
||||||
|
parser.read_handler = yaml_reader_read_handler
|
||||||
|
parser.input_reader = r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the source encoding.
|
||||||
|
func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
|
||||||
|
if parser.encoding != yaml_ANY_ENCODING {
|
||||||
|
panic("must set the encoding only once")
|
||||||
|
}
|
||||||
|
parser.encoding = encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new emitter object.
|
||||||
|
func yaml_emitter_initialize(emitter *yaml_emitter_t) {
|
||||||
|
*emitter = yaml_emitter_t{
|
||||||
|
buffer: make([]byte, output_buffer_size),
|
||||||
|
raw_buffer: make([]byte, 0, output_raw_buffer_size),
|
||||||
|
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
|
||||||
|
events: make([]yaml_event_t, 0, initial_queue_size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy an emitter object.
|
||||||
|
func yaml_emitter_delete(emitter *yaml_emitter_t) {
|
||||||
|
*emitter = yaml_emitter_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String write handler.
|
||||||
|
func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||||
|
*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// yaml_writer_write_handler uses emitter.output_writer to write the
|
||||||
|
// emitted text.
|
||||||
|
func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||||
|
_, err := emitter.output_writer.Write(buffer)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a string output.
|
||||||
|
func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
|
||||||
|
if emitter.write_handler != nil {
|
||||||
|
panic("must set the output target only once")
|
||||||
|
}
|
||||||
|
emitter.write_handler = yaml_string_write_handler
|
||||||
|
emitter.output_buffer = output_buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a file output.
|
||||||
|
func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
|
||||||
|
if emitter.write_handler != nil {
|
||||||
|
panic("must set the output target only once")
|
||||||
|
}
|
||||||
|
emitter.write_handler = yaml_writer_write_handler
|
||||||
|
emitter.output_writer = w
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the output encoding.
|
||||||
|
func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
|
||||||
|
if emitter.encoding != yaml_ANY_ENCODING {
|
||||||
|
panic("must set the output encoding only once")
|
||||||
|
}
|
||||||
|
emitter.encoding = encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the canonical output style.
|
||||||
|
func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
|
||||||
|
emitter.canonical = canonical
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the indentation increment.
|
||||||
|
func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
|
||||||
|
if indent < 2 || indent > 9 {
|
||||||
|
indent = 2
|
||||||
|
}
|
||||||
|
emitter.best_indent = indent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the preferred line width.
|
||||||
|
func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
|
||||||
|
if width < 0 {
|
||||||
|
width = -1
|
||||||
|
}
|
||||||
|
emitter.best_width = width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set if unescaped non-ASCII characters are allowed.
|
||||||
|
func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
|
||||||
|
emitter.unicode = unicode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the preferred line break character.
|
||||||
|
func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
|
||||||
|
emitter.line_break = line_break
|
||||||
|
}
|
||||||
|
|
||||||
|
///*
|
||||||
|
// * Destroy a token object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(void)
|
||||||
|
//yaml_token_delete(yaml_token_t *token)
|
||||||
|
//{
|
||||||
|
// assert(token); // Non-NULL token object expected.
|
||||||
|
//
|
||||||
|
// switch (token.type)
|
||||||
|
// {
|
||||||
|
// case YAML_TAG_DIRECTIVE_TOKEN:
|
||||||
|
// yaml_free(token.data.tag_directive.handle);
|
||||||
|
// yaml_free(token.data.tag_directive.prefix);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_ALIAS_TOKEN:
|
||||||
|
// yaml_free(token.data.alias.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_ANCHOR_TOKEN:
|
||||||
|
// yaml_free(token.data.anchor.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_TAG_TOKEN:
|
||||||
|
// yaml_free(token.data.tag.handle);
|
||||||
|
// yaml_free(token.data.tag.suffix);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_SCALAR_TOKEN:
|
||||||
|
// yaml_free(token.data.scalar.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// memset(token, 0, sizeof(yaml_token_t));
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Check if a string is a valid UTF-8 sequence.
|
||||||
|
// *
|
||||||
|
// * Check 'reader.c' for more details on UTF-8 encoding.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//static int
|
||||||
|
//yaml_check_utf8(yaml_char_t *start, size_t length)
|
||||||
|
//{
|
||||||
|
// yaml_char_t *end = start+length;
|
||||||
|
// yaml_char_t *pointer = start;
|
||||||
|
//
|
||||||
|
// while (pointer < end) {
|
||||||
|
// unsigned char octet;
|
||||||
|
// unsigned int width;
|
||||||
|
// unsigned int value;
|
||||||
|
// size_t k;
|
||||||
|
//
|
||||||
|
// octet = pointer[0];
|
||||||
|
// width = (octet & 0x80) == 0x00 ? 1 :
|
||||||
|
// (octet & 0xE0) == 0xC0 ? 2 :
|
||||||
|
// (octet & 0xF0) == 0xE0 ? 3 :
|
||||||
|
// (octet & 0xF8) == 0xF0 ? 4 : 0;
|
||||||
|
// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
|
||||||
|
// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
|
||||||
|
// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
|
||||||
|
// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
|
||||||
|
// if (!width) return 0;
|
||||||
|
// if (pointer+width > end) return 0;
|
||||||
|
// for (k = 1; k < width; k ++) {
|
||||||
|
// octet = pointer[k];
|
||||||
|
// if ((octet & 0xC0) != 0x80) return 0;
|
||||||
|
// value = (value << 6) + (octet & 0x3F);
|
||||||
|
// }
|
||||||
|
// if (!((width == 1) ||
|
||||||
|
// (width == 2 && value >= 0x80) ||
|
||||||
|
// (width == 3 && value >= 0x800) ||
|
||||||
|
// (width == 4 && value >= 0x10000))) return 0;
|
||||||
|
//
|
||||||
|
// pointer += width;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return 1;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
|
||||||
|
// Create STREAM-START.
|
||||||
|
func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_STREAM_START_EVENT,
|
||||||
|
encoding: encoding,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create STREAM-END.
|
||||||
|
func yaml_stream_end_event_initialize(event *yaml_event_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_STREAM_END_EVENT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create DOCUMENT-START.
|
||||||
|
func yaml_document_start_event_initialize(
|
||||||
|
event *yaml_event_t,
|
||||||
|
version_directive *yaml_version_directive_t,
|
||||||
|
tag_directives []yaml_tag_directive_t,
|
||||||
|
implicit bool,
|
||||||
|
) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_DOCUMENT_START_EVENT,
|
||||||
|
version_directive: version_directive,
|
||||||
|
tag_directives: tag_directives,
|
||||||
|
implicit: implicit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create DOCUMENT-END.
|
||||||
|
func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_DOCUMENT_END_EVENT,
|
||||||
|
implicit: implicit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create ALIAS.
|
||||||
|
func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_ALIAS_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SCALAR.
|
||||||
|
func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SCALAR_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
value: value,
|
||||||
|
implicit: plain_implicit,
|
||||||
|
quoted_implicit: quoted_implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SEQUENCE-START.
|
||||||
|
func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SEQUENCE_START_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
implicit: implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SEQUENCE-END.
|
||||||
|
func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SEQUENCE_END_EVENT,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create MAPPING-START.
|
||||||
|
func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_MAPPING_START_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
implicit: implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create MAPPING-END.
|
||||||
|
func yaml_mapping_end_event_initialize(event *yaml_event_t) {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_MAPPING_END_EVENT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy an event object.
|
||||||
|
func yaml_event_delete(event *yaml_event_t) {
|
||||||
|
*event = yaml_event_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
///*
|
||||||
|
// * Create a document object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_initialize(document *yaml_document_t,
|
||||||
|
// version_directive *yaml_version_directive_t,
|
||||||
|
// tag_directives_start *yaml_tag_directive_t,
|
||||||
|
// tag_directives_end *yaml_tag_directive_t,
|
||||||
|
// start_implicit int, end_implicit int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_t
|
||||||
|
// end *yaml_node_t
|
||||||
|
// top *yaml_node_t
|
||||||
|
// } nodes = { NULL, NULL, NULL }
|
||||||
|
// version_directive_copy *yaml_version_directive_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_tag_directive_t
|
||||||
|
// end *yaml_tag_directive_t
|
||||||
|
// top *yaml_tag_directive_t
|
||||||
|
// } tag_directives_copy = { NULL, NULL, NULL }
|
||||||
|
// value yaml_tag_directive_t = { NULL, NULL }
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
// assert((tag_directives_start && tag_directives_end) ||
|
||||||
|
// (tag_directives_start == tag_directives_end))
|
||||||
|
// // Valid tag directives are expected.
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// if (version_directive) {
|
||||||
|
// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
|
||||||
|
// if (!version_directive_copy) goto error
|
||||||
|
// version_directive_copy.major = version_directive.major
|
||||||
|
// version_directive_copy.minor = version_directive.minor
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (tag_directives_start != tag_directives_end) {
|
||||||
|
// tag_directive *yaml_tag_directive_t
|
||||||
|
// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
|
||||||
|
// goto error
|
||||||
|
// for (tag_directive = tag_directives_start
|
||||||
|
// tag_directive != tag_directives_end; tag_directive ++) {
|
||||||
|
// assert(tag_directive.handle)
|
||||||
|
// assert(tag_directive.prefix)
|
||||||
|
// if (!yaml_check_utf8(tag_directive.handle,
|
||||||
|
// strlen((char *)tag_directive.handle)))
|
||||||
|
// goto error
|
||||||
|
// if (!yaml_check_utf8(tag_directive.prefix,
|
||||||
|
// strlen((char *)tag_directive.prefix)))
|
||||||
|
// goto error
|
||||||
|
// value.handle = yaml_strdup(tag_directive.handle)
|
||||||
|
// value.prefix = yaml_strdup(tag_directive.prefix)
|
||||||
|
// if (!value.handle || !value.prefix) goto error
|
||||||
|
// if (!PUSH(&context, tag_directives_copy, value))
|
||||||
|
// goto error
|
||||||
|
// value.handle = NULL
|
||||||
|
// value.prefix = NULL
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
|
||||||
|
// tag_directives_copy.start, tag_directives_copy.top,
|
||||||
|
// start_implicit, end_implicit, mark, mark)
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, nodes)
|
||||||
|
// yaml_free(version_directive_copy)
|
||||||
|
// while (!STACK_EMPTY(&context, tag_directives_copy)) {
|
||||||
|
// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
|
||||||
|
// yaml_free(value.handle)
|
||||||
|
// yaml_free(value.prefix)
|
||||||
|
// }
|
||||||
|
// STACK_DEL(&context, tag_directives_copy)
|
||||||
|
// yaml_free(value.handle)
|
||||||
|
// yaml_free(value.prefix)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Destroy a document object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(void)
|
||||||
|
//yaml_document_delete(document *yaml_document_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// tag_directive *yaml_tag_directive_t
|
||||||
|
//
|
||||||
|
// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// while (!STACK_EMPTY(&context, document.nodes)) {
|
||||||
|
// node yaml_node_t = POP(&context, document.nodes)
|
||||||
|
// yaml_free(node.tag)
|
||||||
|
// switch (node.type) {
|
||||||
|
// case YAML_SCALAR_NODE:
|
||||||
|
// yaml_free(node.data.scalar.value)
|
||||||
|
// break
|
||||||
|
// case YAML_SEQUENCE_NODE:
|
||||||
|
// STACK_DEL(&context, node.data.sequence.items)
|
||||||
|
// break
|
||||||
|
// case YAML_MAPPING_NODE:
|
||||||
|
// STACK_DEL(&context, node.data.mapping.pairs)
|
||||||
|
// break
|
||||||
|
// default:
|
||||||
|
// assert(0) // Should not happen.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// STACK_DEL(&context, document.nodes)
|
||||||
|
//
|
||||||
|
// yaml_free(document.version_directive)
|
||||||
|
// for (tag_directive = document.tag_directives.start
|
||||||
|
// tag_directive != document.tag_directives.end
|
||||||
|
// tag_directive++) {
|
||||||
|
// yaml_free(tag_directive.handle)
|
||||||
|
// yaml_free(tag_directive.prefix)
|
||||||
|
// }
|
||||||
|
// yaml_free(document.tag_directives.start)
|
||||||
|
//
|
||||||
|
// memset(document, 0, sizeof(yaml_document_t))
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Get a document node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(yaml_node_t *)
|
||||||
|
//yaml_document_get_node(document *yaml_document_t, index int)
|
||||||
|
//{
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
|
||||||
|
// return document.nodes.start + index - 1
|
||||||
|
// }
|
||||||
|
// return NULL
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Get the root object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(yaml_node_t *)
|
||||||
|
//yaml_document_get_root_node(document *yaml_document_t)
|
||||||
|
//{
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (document.nodes.top != document.nodes.start) {
|
||||||
|
// return document.nodes.start
|
||||||
|
// }
|
||||||
|
// return NULL
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a scalar node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_scalar(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, value *yaml_char_t, length int,
|
||||||
|
// style yaml_scalar_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// value_copy *yaml_char_t = NULL
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
// assert(value) // Non-NULL value is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (length < 0) {
|
||||||
|
// length = strlen((char *)value)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(value, length)) goto error
|
||||||
|
// value_copy = yaml_malloc(length+1)
|
||||||
|
// if (!value_copy) goto error
|
||||||
|
// memcpy(value_copy, value, length)
|
||||||
|
// value_copy[length] = '\0'
|
||||||
|
//
|
||||||
|
// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
// yaml_free(value_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a sequence node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_sequence(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, style yaml_sequence_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_item_t
|
||||||
|
// end *yaml_node_item_t
|
||||||
|
// top *yaml_node_item_t
|
||||||
|
// } items = { NULL, NULL, NULL }
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
|
||||||
|
// style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, items)
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a mapping node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_mapping(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, style yaml_mapping_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_pair_t
|
||||||
|
// end *yaml_node_pair_t
|
||||||
|
// top *yaml_node_pair_t
|
||||||
|
// } pairs = { NULL, NULL, NULL }
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
|
||||||
|
// style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, pairs)
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Append an item to a sequence node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_append_sequence_item(document *yaml_document_t,
|
||||||
|
// sequence int, item int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document is required.
|
||||||
|
// assert(sequence > 0
|
||||||
|
// && document.nodes.start + sequence <= document.nodes.top)
|
||||||
|
// // Valid sequence id is required.
|
||||||
|
// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
|
||||||
|
// // A sequence node is required.
|
||||||
|
// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
|
||||||
|
// // Valid item id is required.
|
||||||
|
//
|
||||||
|
// if (!PUSH(&context,
|
||||||
|
// document.nodes.start[sequence-1].data.sequence.items, item))
|
||||||
|
// return 0
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Append a pair of a key and a value to a mapping node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_append_mapping_pair(document *yaml_document_t,
|
||||||
|
// mapping int, key int, value int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
//
|
||||||
|
// pair yaml_node_pair_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document is required.
|
||||||
|
// assert(mapping > 0
|
||||||
|
// && document.nodes.start + mapping <= document.nodes.top)
|
||||||
|
// // Valid mapping id is required.
|
||||||
|
// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
|
||||||
|
// // A mapping node is required.
|
||||||
|
// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
|
||||||
|
// // Valid key id is required.
|
||||||
|
// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
|
||||||
|
// // Valid value id is required.
|
||||||
|
//
|
||||||
|
// pair.key = key
|
||||||
|
// pair.value = value
|
||||||
|
//
|
||||||
|
// if (!PUSH(&context,
|
||||||
|
// document.nodes.start[mapping-1].data.mapping.pairs, pair))
|
||||||
|
// return 0
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
931
vendor/gopkg.in/yaml.v3/decode.go
generated
vendored
Normal file
931
vendor/gopkg.in/yaml.v3/decode.go
generated
vendored
Normal file
@ -0,0 +1,931 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Parser, produces a node tree out of a libyaml event stream.
|
||||||
|
|
||||||
|
type parser struct {
|
||||||
|
parser yaml_parser_t
|
||||||
|
event yaml_event_t
|
||||||
|
doc *Node
|
||||||
|
anchors map[string]*Node
|
||||||
|
doneInit bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newParser(b []byte) *parser {
|
||||||
|
p := parser{}
|
||||||
|
if !yaml_parser_initialize(&p.parser) {
|
||||||
|
panic("failed to initialize YAML emitter")
|
||||||
|
}
|
||||||
|
if len(b) == 0 {
|
||||||
|
b = []byte{'\n'}
|
||||||
|
}
|
||||||
|
yaml_parser_set_input_string(&p.parser, b)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
func newParserFromReader(r io.Reader) *parser {
|
||||||
|
p := parser{}
|
||||||
|
if !yaml_parser_initialize(&p.parser) {
|
||||||
|
panic("failed to initialize YAML emitter")
|
||||||
|
}
|
||||||
|
yaml_parser_set_input_reader(&p.parser, r)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) init() {
|
||||||
|
if p.doneInit {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.anchors = make(map[string]*Node)
|
||||||
|
p.expect(yaml_STREAM_START_EVENT)
|
||||||
|
p.doneInit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) destroy() {
|
||||||
|
if p.event.typ != yaml_NO_EVENT {
|
||||||
|
yaml_event_delete(&p.event)
|
||||||
|
}
|
||||||
|
yaml_parser_delete(&p.parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
// expect consumes an event from the event stream and
|
||||||
|
// checks that it's of the expected type.
|
||||||
|
func (p *parser) expect(e yaml_event_type_t) {
|
||||||
|
if p.event.typ == yaml_NO_EVENT {
|
||||||
|
if !yaml_parser_parse(&p.parser, &p.event) {
|
||||||
|
p.fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.event.typ == yaml_STREAM_END_EVENT {
|
||||||
|
failf("attempted to go past the end of stream; corrupted value?")
|
||||||
|
}
|
||||||
|
if p.event.typ != e {
|
||||||
|
p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
|
||||||
|
p.fail()
|
||||||
|
}
|
||||||
|
yaml_event_delete(&p.event)
|
||||||
|
p.event.typ = yaml_NO_EVENT
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek peeks at the next event in the event stream,
|
||||||
|
// puts the results into p.event and returns the event type.
|
||||||
|
func (p *parser) peek() yaml_event_type_t {
|
||||||
|
if p.event.typ != yaml_NO_EVENT {
|
||||||
|
return p.event.typ
|
||||||
|
}
|
||||||
|
if !yaml_parser_parse(&p.parser, &p.event) {
|
||||||
|
p.fail()
|
||||||
|
}
|
||||||
|
return p.event.typ
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) fail() {
|
||||||
|
var where string
|
||||||
|
var line int
|
||||||
|
if p.parser.problem_mark.line != 0 {
|
||||||
|
line = p.parser.problem_mark.line
|
||||||
|
// Scanner errors don't iterate line before returning error
|
||||||
|
if p.parser.error == yaml_SCANNER_ERROR {
|
||||||
|
line++
|
||||||
|
}
|
||||||
|
} else if p.parser.context_mark.line != 0 {
|
||||||
|
line = p.parser.context_mark.line
|
||||||
|
}
|
||||||
|
if line != 0 {
|
||||||
|
where = "line " + strconv.Itoa(line) + ": "
|
||||||
|
}
|
||||||
|
var msg string
|
||||||
|
if len(p.parser.problem) > 0 {
|
||||||
|
msg = p.parser.problem
|
||||||
|
} else {
|
||||||
|
msg = "unknown problem parsing YAML content"
|
||||||
|
}
|
||||||
|
failf("%s%s", where, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) anchor(n *Node, anchor []byte) {
|
||||||
|
if anchor != nil {
|
||||||
|
n.Anchor = string(anchor)
|
||||||
|
p.anchors[n.Anchor] = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) parse() *Node {
|
||||||
|
p.init()
|
||||||
|
switch p.peek() {
|
||||||
|
case yaml_SCALAR_EVENT:
|
||||||
|
return p.scalar()
|
||||||
|
case yaml_ALIAS_EVENT:
|
||||||
|
return p.alias()
|
||||||
|
case yaml_MAPPING_START_EVENT:
|
||||||
|
return p.mapping()
|
||||||
|
case yaml_SEQUENCE_START_EVENT:
|
||||||
|
return p.sequence()
|
||||||
|
case yaml_DOCUMENT_START_EVENT:
|
||||||
|
return p.document()
|
||||||
|
case yaml_STREAM_END_EVENT:
|
||||||
|
// Happens when attempting to decode an empty buffer.
|
||||||
|
return nil
|
||||||
|
case yaml_TAIL_COMMENT_EVENT:
|
||||||
|
panic("internal error: unexpected tail comment event (please report)")
|
||||||
|
default:
|
||||||
|
panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
|
||||||
|
var style Style
|
||||||
|
if tag != "" && tag != "!" {
|
||||||
|
tag = shortTag(tag)
|
||||||
|
style = TaggedStyle
|
||||||
|
} else if defaultTag != "" {
|
||||||
|
tag = defaultTag
|
||||||
|
} else if kind == ScalarNode {
|
||||||
|
tag, _ = resolve("", value)
|
||||||
|
}
|
||||||
|
return &Node{
|
||||||
|
Kind: kind,
|
||||||
|
Tag: tag,
|
||||||
|
Value: value,
|
||||||
|
Style: style,
|
||||||
|
Line: p.event.start_mark.line + 1,
|
||||||
|
Column: p.event.start_mark.column + 1,
|
||||||
|
HeadComment: string(p.event.head_comment),
|
||||||
|
LineComment: string(p.event.line_comment),
|
||||||
|
FootComment: string(p.event.foot_comment),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) parseChild(parent *Node) *Node {
|
||||||
|
child := p.parse()
|
||||||
|
parent.Content = append(parent.Content, child)
|
||||||
|
return child
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) document() *Node {
|
||||||
|
n := p.node(DocumentNode, "", "", "")
|
||||||
|
p.doc = n
|
||||||
|
p.expect(yaml_DOCUMENT_START_EVENT)
|
||||||
|
p.parseChild(n)
|
||||||
|
if p.peek() == yaml_DOCUMENT_END_EVENT {
|
||||||
|
n.FootComment = string(p.event.foot_comment)
|
||||||
|
}
|
||||||
|
p.expect(yaml_DOCUMENT_END_EVENT)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) alias() *Node {
|
||||||
|
n := p.node(AliasNode, "", "", string(p.event.anchor))
|
||||||
|
n.Alias = p.anchors[n.Value]
|
||||||
|
if n.Alias == nil {
|
||||||
|
failf("unknown anchor '%s' referenced", n.Value)
|
||||||
|
}
|
||||||
|
p.expect(yaml_ALIAS_EVENT)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) scalar() *Node {
|
||||||
|
var parsedStyle = p.event.scalar_style()
|
||||||
|
var nodeStyle Style
|
||||||
|
switch {
|
||||||
|
case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
|
||||||
|
nodeStyle = DoubleQuotedStyle
|
||||||
|
case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
|
||||||
|
nodeStyle = SingleQuotedStyle
|
||||||
|
case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
|
||||||
|
nodeStyle = LiteralStyle
|
||||||
|
case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
|
||||||
|
nodeStyle = FoldedStyle
|
||||||
|
}
|
||||||
|
var nodeValue = string(p.event.value)
|
||||||
|
var nodeTag = string(p.event.tag)
|
||||||
|
var defaultTag string
|
||||||
|
if nodeStyle == 0 {
|
||||||
|
if nodeValue == "<<" {
|
||||||
|
defaultTag = mergeTag
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
defaultTag = strTag
|
||||||
|
}
|
||||||
|
n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
|
||||||
|
n.Style |= nodeStyle
|
||||||
|
p.anchor(n, p.event.anchor)
|
||||||
|
p.expect(yaml_SCALAR_EVENT)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) sequence() *Node {
|
||||||
|
n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
|
||||||
|
if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
|
||||||
|
n.Style |= FlowStyle
|
||||||
|
}
|
||||||
|
p.anchor(n, p.event.anchor)
|
||||||
|
p.expect(yaml_SEQUENCE_START_EVENT)
|
||||||
|
for p.peek() != yaml_SEQUENCE_END_EVENT {
|
||||||
|
p.parseChild(n)
|
||||||
|
}
|
||||||
|
n.LineComment = string(p.event.line_comment)
|
||||||
|
n.FootComment = string(p.event.foot_comment)
|
||||||
|
p.expect(yaml_SEQUENCE_END_EVENT)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) mapping() *Node {
|
||||||
|
n := p.node(MappingNode, mapTag, string(p.event.tag), "")
|
||||||
|
block := true
|
||||||
|
if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
|
||||||
|
block = false
|
||||||
|
n.Style |= FlowStyle
|
||||||
|
}
|
||||||
|
p.anchor(n, p.event.anchor)
|
||||||
|
p.expect(yaml_MAPPING_START_EVENT)
|
||||||
|
for p.peek() != yaml_MAPPING_END_EVENT {
|
||||||
|
k := p.parseChild(n)
|
||||||
|
if block && k.FootComment != "" {
|
||||||
|
// Must be a foot comment for the prior value when being dedented.
|
||||||
|
if len(n.Content) > 2 {
|
||||||
|
n.Content[len(n.Content)-3].FootComment = k.FootComment
|
||||||
|
k.FootComment = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v := p.parseChild(n)
|
||||||
|
if k.FootComment == "" && v.FootComment != "" {
|
||||||
|
k.FootComment = v.FootComment
|
||||||
|
v.FootComment = ""
|
||||||
|
}
|
||||||
|
if p.peek() == yaml_TAIL_COMMENT_EVENT {
|
||||||
|
if k.FootComment == "" {
|
||||||
|
k.FootComment = string(p.event.foot_comment)
|
||||||
|
}
|
||||||
|
p.expect(yaml_TAIL_COMMENT_EVENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n.LineComment = string(p.event.line_comment)
|
||||||
|
n.FootComment = string(p.event.foot_comment)
|
||||||
|
if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
|
||||||
|
n.Content[len(n.Content)-2].FootComment = n.FootComment
|
||||||
|
n.FootComment = ""
|
||||||
|
}
|
||||||
|
p.expect(yaml_MAPPING_END_EVENT)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Decoder, unmarshals a node into a provided value.
|
||||||
|
|
||||||
|
type decoder struct {
|
||||||
|
doc *Node
|
||||||
|
aliases map[*Node]bool
|
||||||
|
terrors []string
|
||||||
|
|
||||||
|
stringMapType reflect.Type
|
||||||
|
generalMapType reflect.Type
|
||||||
|
|
||||||
|
knownFields bool
|
||||||
|
uniqueKeys bool
|
||||||
|
decodeCount int
|
||||||
|
aliasCount int
|
||||||
|
aliasDepth int
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
nodeType = reflect.TypeOf(Node{})
|
||||||
|
durationType = reflect.TypeOf(time.Duration(0))
|
||||||
|
stringMapType = reflect.TypeOf(map[string]interface{}{})
|
||||||
|
generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
|
||||||
|
ifaceType = generalMapType.Elem()
|
||||||
|
timeType = reflect.TypeOf(time.Time{})
|
||||||
|
ptrTimeType = reflect.TypeOf(&time.Time{})
|
||||||
|
)
|
||||||
|
|
||||||
|
func newDecoder() *decoder {
|
||||||
|
d := &decoder{
|
||||||
|
stringMapType: stringMapType,
|
||||||
|
generalMapType: generalMapType,
|
||||||
|
uniqueKeys: true,
|
||||||
|
}
|
||||||
|
d.aliases = make(map[*Node]bool)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
|
||||||
|
if n.Tag != "" {
|
||||||
|
tag = n.Tag
|
||||||
|
}
|
||||||
|
value := n.Value
|
||||||
|
if tag != seqTag && tag != mapTag {
|
||||||
|
if len(value) > 10 {
|
||||||
|
value = " `" + value[:7] + "...`"
|
||||||
|
} else {
|
||||||
|
value = " `" + value + "`"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
|
||||||
|
err := u.UnmarshalYAML(n)
|
||||||
|
if e, ok := err.(*TypeError); ok {
|
||||||
|
d.terrors = append(d.terrors, e.Errors...)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
|
||||||
|
terrlen := len(d.terrors)
|
||||||
|
err := u.UnmarshalYAML(func(v interface{}) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
d.unmarshal(n, reflect.ValueOf(v))
|
||||||
|
if len(d.terrors) > terrlen {
|
||||||
|
issues := d.terrors[terrlen:]
|
||||||
|
d.terrors = d.terrors[:terrlen]
|
||||||
|
return &TypeError{issues}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if e, ok := err.(*TypeError); ok {
|
||||||
|
d.terrors = append(d.terrors, e.Errors...)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
|
||||||
|
// if a value is found to implement it.
|
||||||
|
// It returns the initialized and dereferenced out value, whether
|
||||||
|
// unmarshalling was already done by UnmarshalYAML, and if so whether
|
||||||
|
// its types unmarshalled appropriately.
|
||||||
|
//
|
||||||
|
// If n holds a null value, prepare returns before doing anything.
|
||||||
|
func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
|
||||||
|
if n.ShortTag() == nullTag {
|
||||||
|
return out, false, false
|
||||||
|
}
|
||||||
|
again := true
|
||||||
|
for again {
|
||||||
|
again = false
|
||||||
|
if out.Kind() == reflect.Ptr {
|
||||||
|
if out.IsNil() {
|
||||||
|
out.Set(reflect.New(out.Type().Elem()))
|
||||||
|
}
|
||||||
|
out = out.Elem()
|
||||||
|
again = true
|
||||||
|
}
|
||||||
|
if out.CanAddr() {
|
||||||
|
outi := out.Addr().Interface()
|
||||||
|
if u, ok := outi.(Unmarshaler); ok {
|
||||||
|
good = d.callUnmarshaler(n, u)
|
||||||
|
return out, true, good
|
||||||
|
}
|
||||||
|
if u, ok := outi.(obsoleteUnmarshaler); ok {
|
||||||
|
good = d.callObsoleteUnmarshaler(n, u)
|
||||||
|
return out, true, good
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
|
||||||
|
if n.ShortTag() == nullTag {
|
||||||
|
return reflect.Value{}
|
||||||
|
}
|
||||||
|
for _, num := range index {
|
||||||
|
for {
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
if v.IsNil() {
|
||||||
|
v.Set(reflect.New(v.Type().Elem()))
|
||||||
|
}
|
||||||
|
v = v.Elem()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v = v.Field(num)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 400,000 decode operations is ~500kb of dense object declarations, or
|
||||||
|
// ~5kb of dense object declarations with 10000% alias expansion
|
||||||
|
alias_ratio_range_low = 400000
|
||||||
|
|
||||||
|
// 4,000,000 decode operations is ~5MB of dense object declarations, or
|
||||||
|
// ~4.5MB of dense object declarations with 10% alias expansion
|
||||||
|
alias_ratio_range_high = 4000000
|
||||||
|
|
||||||
|
// alias_ratio_range is the range over which we scale allowed alias ratios
|
||||||
|
alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
|
||||||
|
)
|
||||||
|
|
||||||
|
func allowedAliasRatio(decodeCount int) float64 {
|
||||||
|
switch {
|
||||||
|
case decodeCount <= alias_ratio_range_low:
|
||||||
|
// allow 99% to come from alias expansion for small-to-medium documents
|
||||||
|
return 0.99
|
||||||
|
case decodeCount >= alias_ratio_range_high:
|
||||||
|
// allow 10% to come from alias expansion for very large documents
|
||||||
|
return 0.10
|
||||||
|
default:
|
||||||
|
// scale smoothly from 99% down to 10% over the range.
|
||||||
|
// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
|
||||||
|
// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
|
||||||
|
return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
|
||||||
|
d.decodeCount++
|
||||||
|
if d.aliasDepth > 0 {
|
||||||
|
d.aliasCount++
|
||||||
|
}
|
||||||
|
if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
|
||||||
|
failf("document contains excessive aliasing")
|
||||||
|
}
|
||||||
|
if out.Type() == nodeType {
|
||||||
|
out.Set(reflect.ValueOf(n).Elem())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
switch n.Kind {
|
||||||
|
case DocumentNode:
|
||||||
|
return d.document(n, out)
|
||||||
|
case AliasNode:
|
||||||
|
return d.alias(n, out)
|
||||||
|
}
|
||||||
|
out, unmarshaled, good := d.prepare(n, out)
|
||||||
|
if unmarshaled {
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
switch n.Kind {
|
||||||
|
case ScalarNode:
|
||||||
|
good = d.scalar(n, out)
|
||||||
|
case MappingNode:
|
||||||
|
good = d.mapping(n, out)
|
||||||
|
case SequenceNode:
|
||||||
|
good = d.sequence(n, out)
|
||||||
|
default:
|
||||||
|
panic("internal error: unknown node kind: " + strconv.Itoa(int(n.Kind)))
|
||||||
|
}
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
|
||||||
|
if len(n.Content) == 1 {
|
||||||
|
d.doc = n
|
||||||
|
d.unmarshal(n.Content[0], out)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
|
||||||
|
if d.aliases[n] {
|
||||||
|
// TODO this could actually be allowed in some circumstances.
|
||||||
|
failf("anchor '%s' value contains itself", n.Value)
|
||||||
|
}
|
||||||
|
d.aliases[n] = true
|
||||||
|
d.aliasDepth++
|
||||||
|
good = d.unmarshal(n.Alias, out)
|
||||||
|
d.aliasDepth--
|
||||||
|
delete(d.aliases, n)
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroValue reflect.Value
|
||||||
|
|
||||||
|
func resetMap(out reflect.Value) {
|
||||||
|
for _, k := range out.MapKeys() {
|
||||||
|
out.SetMapIndex(k, zeroValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) scalar(n *Node, out reflect.Value) bool {
|
||||||
|
var tag string
|
||||||
|
var resolved interface{}
|
||||||
|
if n.indicatedString() {
|
||||||
|
tag = strTag
|
||||||
|
resolved = n.Value
|
||||||
|
} else {
|
||||||
|
tag, resolved = resolve(n.Tag, n.Value)
|
||||||
|
if tag == binaryTag {
|
||||||
|
data, err := base64.StdEncoding.DecodeString(resolved.(string))
|
||||||
|
if err != nil {
|
||||||
|
failf("!!binary value contains invalid base64 data")
|
||||||
|
}
|
||||||
|
resolved = string(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if resolved == nil {
|
||||||
|
if out.CanAddr() {
|
||||||
|
switch out.Kind() {
|
||||||
|
case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
|
||||||
|
out.Set(reflect.Zero(out.Type()))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
|
||||||
|
// We've resolved to exactly the type we want, so use that.
|
||||||
|
out.Set(resolvedv)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Perhaps we can use the value as a TextUnmarshaler to
|
||||||
|
// set its value.
|
||||||
|
if out.CanAddr() {
|
||||||
|
u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
|
||||||
|
if ok {
|
||||||
|
var text []byte
|
||||||
|
if tag == binaryTag {
|
||||||
|
text = []byte(resolved.(string))
|
||||||
|
} else {
|
||||||
|
// We let any value be unmarshaled into TextUnmarshaler.
|
||||||
|
// That might be more lax than we'd like, but the
|
||||||
|
// TextUnmarshaler itself should bowl out any dubious values.
|
||||||
|
text = []byte(n.Value)
|
||||||
|
}
|
||||||
|
err := u.UnmarshalText(text)
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch out.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
if tag == binaryTag {
|
||||||
|
out.SetString(resolved.(string))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
out.SetString(n.Value)
|
||||||
|
return true
|
||||||
|
case reflect.Interface:
|
||||||
|
out.Set(reflect.ValueOf(resolved))
|
||||||
|
return true
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
// This used to work in v2, but it's very unfriendly.
|
||||||
|
isDuration := out.Type() == durationType
|
||||||
|
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case int:
|
||||||
|
if !isDuration && !out.OverflowInt(int64(resolved)) {
|
||||||
|
out.SetInt(int64(resolved))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case int64:
|
||||||
|
if !isDuration && !out.OverflowInt(resolved) {
|
||||||
|
out.SetInt(resolved)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case uint64:
|
||||||
|
if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
|
||||||
|
out.SetInt(int64(resolved))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
|
||||||
|
out.SetInt(int64(resolved))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
if out.Type() == durationType {
|
||||||
|
d, err := time.ParseDuration(resolved)
|
||||||
|
if err == nil {
|
||||||
|
out.SetInt(int64(d))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case int:
|
||||||
|
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case int64:
|
||||||
|
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case uint64:
|
||||||
|
if !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Bool:
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case bool:
|
||||||
|
out.SetBool(resolved)
|
||||||
|
return true
|
||||||
|
case string:
|
||||||
|
// This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
|
||||||
|
// It only works if explicitly attempting to unmarshal into a typed bool value.
|
||||||
|
switch resolved {
|
||||||
|
case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
|
||||||
|
out.SetBool(true)
|
||||||
|
return true
|
||||||
|
case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
|
||||||
|
out.SetBool(false)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case int:
|
||||||
|
out.SetFloat(float64(resolved))
|
||||||
|
return true
|
||||||
|
case int64:
|
||||||
|
out.SetFloat(float64(resolved))
|
||||||
|
return true
|
||||||
|
case uint64:
|
||||||
|
out.SetFloat(float64(resolved))
|
||||||
|
return true
|
||||||
|
case float64:
|
||||||
|
out.SetFloat(resolved)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
|
||||||
|
out.Set(resolvedv)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case reflect.Ptr:
|
||||||
|
panic("yaml internal error: please report the issue")
|
||||||
|
}
|
||||||
|
d.terror(n, tag, out)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func settableValueOf(i interface{}) reflect.Value {
|
||||||
|
v := reflect.ValueOf(i)
|
||||||
|
sv := reflect.New(v.Type()).Elem()
|
||||||
|
sv.Set(v)
|
||||||
|
return sv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
|
||||||
|
l := len(n.Content)
|
||||||
|
|
||||||
|
var iface reflect.Value
|
||||||
|
switch out.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
out.Set(reflect.MakeSlice(out.Type(), l, l))
|
||||||
|
case reflect.Array:
|
||||||
|
if l != out.Len() {
|
||||||
|
failf("invalid array: want %d elements but got %d", out.Len(), l)
|
||||||
|
}
|
||||||
|
case reflect.Interface:
|
||||||
|
// No type hints. Will have to use a generic sequence.
|
||||||
|
iface = out
|
||||||
|
out = settableValueOf(make([]interface{}, l))
|
||||||
|
default:
|
||||||
|
d.terror(n, seqTag, out)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
et := out.Type().Elem()
|
||||||
|
|
||||||
|
j := 0
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
e := reflect.New(et).Elem()
|
||||||
|
if ok := d.unmarshal(n.Content[i], e); ok {
|
||||||
|
out.Index(j).Set(e)
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if out.Kind() != reflect.Array {
|
||||||
|
out.Set(out.Slice(0, j))
|
||||||
|
}
|
||||||
|
if iface.IsValid() {
|
||||||
|
iface.Set(out)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
|
||||||
|
l := len(n.Content)
|
||||||
|
if d.uniqueKeys {
|
||||||
|
nerrs := len(d.terrors)
|
||||||
|
for i := 0; i < l; i += 2 {
|
||||||
|
ni := n.Content[i]
|
||||||
|
for j := i + 2; j < l; j += 2 {
|
||||||
|
nj := n.Content[j]
|
||||||
|
if ni.Kind == nj.Kind && ni.Value == nj.Value {
|
||||||
|
d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(d.terrors) > nerrs {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch out.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
return d.mappingStruct(n, out)
|
||||||
|
case reflect.Map:
|
||||||
|
// okay
|
||||||
|
case reflect.Interface:
|
||||||
|
iface := out
|
||||||
|
if isStringMap(n) {
|
||||||
|
out = reflect.MakeMap(d.stringMapType)
|
||||||
|
} else {
|
||||||
|
out = reflect.MakeMap(d.generalMapType)
|
||||||
|
}
|
||||||
|
iface.Set(out)
|
||||||
|
default:
|
||||||
|
d.terror(n, mapTag, out)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
outt := out.Type()
|
||||||
|
kt := outt.Key()
|
||||||
|
et := outt.Elem()
|
||||||
|
|
||||||
|
stringMapType := d.stringMapType
|
||||||
|
generalMapType := d.generalMapType
|
||||||
|
if outt.Elem() == ifaceType {
|
||||||
|
if outt.Key().Kind() == reflect.String {
|
||||||
|
d.stringMapType = outt
|
||||||
|
} else if outt.Key() == ifaceType {
|
||||||
|
d.generalMapType = outt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if out.IsNil() {
|
||||||
|
out.Set(reflect.MakeMap(outt))
|
||||||
|
}
|
||||||
|
for i := 0; i < l; i += 2 {
|
||||||
|
if isMerge(n.Content[i]) {
|
||||||
|
d.merge(n.Content[i+1], out)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
k := reflect.New(kt).Elem()
|
||||||
|
if d.unmarshal(n.Content[i], k) {
|
||||||
|
kkind := k.Kind()
|
||||||
|
if kkind == reflect.Interface {
|
||||||
|
kkind = k.Elem().Kind()
|
||||||
|
}
|
||||||
|
if kkind == reflect.Map || kkind == reflect.Slice {
|
||||||
|
failf("invalid map key: %#v", k.Interface())
|
||||||
|
}
|
||||||
|
e := reflect.New(et).Elem()
|
||||||
|
if d.unmarshal(n.Content[i+1], e) {
|
||||||
|
out.SetMapIndex(k, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.stringMapType = stringMapType
|
||||||
|
d.generalMapType = generalMapType
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isStringMap(n *Node) bool {
|
||||||
|
if n.Kind != MappingNode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
l := len(n.Content)
|
||||||
|
for i := 0; i < l; i += 2 {
|
||||||
|
if n.Content[i].ShortTag() != strTag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
|
||||||
|
sinfo, err := getStructInfo(out.Type())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var inlineMap reflect.Value
|
||||||
|
var elemType reflect.Type
|
||||||
|
if sinfo.InlineMap != -1 {
|
||||||
|
inlineMap = out.Field(sinfo.InlineMap)
|
||||||
|
inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
|
||||||
|
elemType = inlineMap.Type().Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, index := range sinfo.InlineUnmarshalers {
|
||||||
|
field := d.fieldByIndex(n, out, index)
|
||||||
|
d.prepare(n, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
var doneFields []bool
|
||||||
|
if d.uniqueKeys {
|
||||||
|
doneFields = make([]bool, len(sinfo.FieldsList))
|
||||||
|
}
|
||||||
|
name := settableValueOf("")
|
||||||
|
l := len(n.Content)
|
||||||
|
for i := 0; i < l; i += 2 {
|
||||||
|
ni := n.Content[i]
|
||||||
|
if isMerge(ni) {
|
||||||
|
d.merge(n.Content[i+1], out)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !d.unmarshal(ni, name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info, ok := sinfo.FieldsMap[name.String()]; ok {
|
||||||
|
if d.uniqueKeys {
|
||||||
|
if doneFields[info.Id] {
|
||||||
|
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
doneFields[info.Id] = true
|
||||||
|
}
|
||||||
|
var field reflect.Value
|
||||||
|
if info.Inline == nil {
|
||||||
|
field = out.Field(info.Num)
|
||||||
|
} else {
|
||||||
|
field = d.fieldByIndex(n, out, info.Inline)
|
||||||
|
}
|
||||||
|
d.unmarshal(n.Content[i+1], field)
|
||||||
|
} else if sinfo.InlineMap != -1 {
|
||||||
|
if inlineMap.IsNil() {
|
||||||
|
inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
|
||||||
|
}
|
||||||
|
value := reflect.New(elemType).Elem()
|
||||||
|
d.unmarshal(n.Content[i+1], value)
|
||||||
|
inlineMap.SetMapIndex(name, value)
|
||||||
|
} else if d.knownFields {
|
||||||
|
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func failWantMap() {
|
||||||
|
failf("map merge requires map or sequence of maps as the value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) merge(n *Node, out reflect.Value) {
|
||||||
|
switch n.Kind {
|
||||||
|
case MappingNode:
|
||||||
|
d.unmarshal(n, out)
|
||||||
|
case AliasNode:
|
||||||
|
if n.Alias != nil && n.Alias.Kind != MappingNode {
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
d.unmarshal(n, out)
|
||||||
|
case SequenceNode:
|
||||||
|
// Step backwards as earlier nodes take precedence.
|
||||||
|
for i := len(n.Content) - 1; i >= 0; i-- {
|
||||||
|
ni := n.Content[i]
|
||||||
|
if ni.Kind == AliasNode {
|
||||||
|
if ni.Alias != nil && ni.Alias.Kind != MappingNode {
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
} else if ni.Kind != MappingNode {
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
d.unmarshal(ni, out)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isMerge(n *Node) bool {
|
||||||
|
return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
|
||||||
|
}
|
1992
vendor/gopkg.in/yaml.v3/emitterc.go
generated
vendored
Normal file
1992
vendor/gopkg.in/yaml.v3/emitterc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
561
vendor/gopkg.in/yaml.v3/encode.go
generated
vendored
Normal file
561
vendor/gopkg.in/yaml.v3/encode.go
generated
vendored
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
type encoder struct {
|
||||||
|
emitter yaml_emitter_t
|
||||||
|
event yaml_event_t
|
||||||
|
out []byte
|
||||||
|
flow bool
|
||||||
|
indent int
|
||||||
|
doneInit bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEncoder() *encoder {
|
||||||
|
e := &encoder{}
|
||||||
|
yaml_emitter_initialize(&e.emitter)
|
||||||
|
yaml_emitter_set_output_string(&e.emitter, &e.out)
|
||||||
|
yaml_emitter_set_unicode(&e.emitter, true)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEncoderWithWriter(w io.Writer) *encoder {
|
||||||
|
e := &encoder{}
|
||||||
|
yaml_emitter_initialize(&e.emitter)
|
||||||
|
yaml_emitter_set_output_writer(&e.emitter, w)
|
||||||
|
yaml_emitter_set_unicode(&e.emitter, true)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) init() {
|
||||||
|
if e.doneInit {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if e.indent == 0 {
|
||||||
|
e.indent = 4
|
||||||
|
}
|
||||||
|
e.emitter.best_indent = e.indent
|
||||||
|
yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
|
||||||
|
e.emit()
|
||||||
|
e.doneInit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) finish() {
|
||||||
|
e.emitter.open_ended = false
|
||||||
|
yaml_stream_end_event_initialize(&e.event)
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) destroy() {
|
||||||
|
yaml_emitter_delete(&e.emitter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) emit() {
|
||||||
|
// This will internally delete the e.event value.
|
||||||
|
e.must(yaml_emitter_emit(&e.emitter, &e.event))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) must(ok bool) {
|
||||||
|
if !ok {
|
||||||
|
msg := e.emitter.problem
|
||||||
|
if msg == "" {
|
||||||
|
msg = "unknown problem generating YAML content"
|
||||||
|
}
|
||||||
|
failf("%s", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) marshalDoc(tag string, in reflect.Value) {
|
||||||
|
e.init()
|
||||||
|
var node *Node
|
||||||
|
if in.IsValid() {
|
||||||
|
node, _ = in.Interface().(*Node)
|
||||||
|
}
|
||||||
|
if node != nil && node.Kind == DocumentNode {
|
||||||
|
e.nodev(in)
|
||||||
|
} else {
|
||||||
|
yaml_document_start_event_initialize(&e.event, nil, nil, true)
|
||||||
|
e.emit()
|
||||||
|
e.marshal(tag, in)
|
||||||
|
yaml_document_end_event_initialize(&e.event, true)
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||||
|
tag = shortTag(tag)
|
||||||
|
if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
iface := in.Interface()
|
||||||
|
switch value := iface.(type) {
|
||||||
|
case *Node:
|
||||||
|
e.nodev(in)
|
||||||
|
return
|
||||||
|
case time.Time:
|
||||||
|
e.timev(tag, in)
|
||||||
|
return
|
||||||
|
case *time.Time:
|
||||||
|
e.timev(tag, in.Elem())
|
||||||
|
return
|
||||||
|
case time.Duration:
|
||||||
|
e.stringv(tag, reflect.ValueOf(value.String()))
|
||||||
|
return
|
||||||
|
case Marshaler:
|
||||||
|
v, err := value.MarshalYAML()
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
if v == nil {
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.marshal(tag, reflect.ValueOf(v))
|
||||||
|
return
|
||||||
|
case encoding.TextMarshaler:
|
||||||
|
text, err := value.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
in = reflect.ValueOf(string(text))
|
||||||
|
case nil:
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch in.Kind() {
|
||||||
|
case reflect.Interface:
|
||||||
|
e.marshal(tag, in.Elem())
|
||||||
|
case reflect.Map:
|
||||||
|
e.mapv(tag, in)
|
||||||
|
case reflect.Ptr:
|
||||||
|
e.marshal(tag, in.Elem())
|
||||||
|
case reflect.Struct:
|
||||||
|
e.structv(tag, in)
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
e.slicev(tag, in)
|
||||||
|
case reflect.String:
|
||||||
|
e.stringv(tag, in)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
e.intv(tag, in)
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
e.uintv(tag, in)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
e.floatv(tag, in)
|
||||||
|
case reflect.Bool:
|
||||||
|
e.boolv(tag, in)
|
||||||
|
default:
|
||||||
|
panic("cannot marshal type: " + in.Type().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) mapv(tag string, in reflect.Value) {
|
||||||
|
e.mappingv(tag, func() {
|
||||||
|
keys := keyList(in.MapKeys())
|
||||||
|
sort.Sort(keys)
|
||||||
|
for _, k := range keys {
|
||||||
|
e.marshal("", k)
|
||||||
|
e.marshal("", in.MapIndex(k))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
|
||||||
|
for _, num := range index {
|
||||||
|
for {
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
if v.IsNil() {
|
||||||
|
return reflect.Value{}
|
||||||
|
}
|
||||||
|
v = v.Elem()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v = v.Field(num)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) structv(tag string, in reflect.Value) {
|
||||||
|
sinfo, err := getStructInfo(in.Type())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
e.mappingv(tag, func() {
|
||||||
|
for _, info := range sinfo.FieldsList {
|
||||||
|
var value reflect.Value
|
||||||
|
if info.Inline == nil {
|
||||||
|
value = in.Field(info.Num)
|
||||||
|
} else {
|
||||||
|
value = e.fieldByIndex(in, info.Inline)
|
||||||
|
if !value.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if info.OmitEmpty && isZero(value) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
e.marshal("", reflect.ValueOf(info.Key))
|
||||||
|
e.flow = info.Flow
|
||||||
|
e.marshal("", value)
|
||||||
|
}
|
||||||
|
if sinfo.InlineMap >= 0 {
|
||||||
|
m := in.Field(sinfo.InlineMap)
|
||||||
|
if m.Len() > 0 {
|
||||||
|
e.flow = false
|
||||||
|
keys := keyList(m.MapKeys())
|
||||||
|
sort.Sort(keys)
|
||||||
|
for _, k := range keys {
|
||||||
|
if _, found := sinfo.FieldsMap[k.String()]; found {
|
||||||
|
panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
|
||||||
|
}
|
||||||
|
e.marshal("", k)
|
||||||
|
e.flow = false
|
||||||
|
e.marshal("", m.MapIndex(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) mappingv(tag string, f func()) {
|
||||||
|
implicit := tag == ""
|
||||||
|
style := yaml_BLOCK_MAPPING_STYLE
|
||||||
|
if e.flow {
|
||||||
|
e.flow = false
|
||||||
|
style = yaml_FLOW_MAPPING_STYLE
|
||||||
|
}
|
||||||
|
yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
|
||||||
|
e.emit()
|
||||||
|
f()
|
||||||
|
yaml_mapping_end_event_initialize(&e.event)
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) slicev(tag string, in reflect.Value) {
|
||||||
|
implicit := tag == ""
|
||||||
|
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||||
|
if e.flow {
|
||||||
|
e.flow = false
|
||||||
|
style = yaml_FLOW_SEQUENCE_STYLE
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
|
||||||
|
e.emit()
|
||||||
|
n := in.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
e.marshal("", in.Index(i))
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_end_event_initialize(&e.event))
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
|
||||||
|
//
|
||||||
|
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
|
||||||
|
// in YAML 1.2 and by this package, but these should be marshalled quoted for
|
||||||
|
// the time being for compatibility with other parsers.
|
||||||
|
func isBase60Float(s string) (result bool) {
|
||||||
|
// Fast path.
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c := s[0]
|
||||||
|
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Do the full match.
|
||||||
|
return base60float.MatchString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// From http://yaml.org/type/float.html, except the regular expression there
|
||||||
|
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
|
||||||
|
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
|
||||||
|
|
||||||
|
// isOldBool returns whether s is bool notation as defined in YAML 1.1.
|
||||||
|
//
|
||||||
|
// We continue to force strings that YAML 1.1 would interpret as booleans to be
|
||||||
|
// rendered as quotes strings so that the marshalled output valid for YAML 1.1
|
||||||
|
// parsing.
|
||||||
|
func isOldBool(s string) (result bool) {
|
||||||
|
switch s {
|
||||||
|
case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
|
||||||
|
"n", "N", "no", "No", "NO", "off", "Off", "OFF":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) stringv(tag string, in reflect.Value) {
|
||||||
|
var style yaml_scalar_style_t
|
||||||
|
s := in.String()
|
||||||
|
canUsePlain := true
|
||||||
|
switch {
|
||||||
|
case !utf8.ValidString(s):
|
||||||
|
if tag == binaryTag {
|
||||||
|
failf("explicitly tagged !!binary data must be base64-encoded")
|
||||||
|
}
|
||||||
|
if tag != "" {
|
||||||
|
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
|
||||||
|
}
|
||||||
|
// It can't be encoded directly as YAML so use a binary tag
|
||||||
|
// and encode it as base64.
|
||||||
|
tag = binaryTag
|
||||||
|
s = encodeBase64(s)
|
||||||
|
case tag == "":
|
||||||
|
// Check to see if it would resolve to a specific
|
||||||
|
// tag when encoded unquoted. If it doesn't,
|
||||||
|
// there's no need to quote it.
|
||||||
|
rtag, _ := resolve("", s)
|
||||||
|
canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
|
||||||
|
}
|
||||||
|
// Note: it's possible for user code to emit invalid YAML
|
||||||
|
// if they explicitly specify a tag and a string containing
|
||||||
|
// text that's incompatible with that tag.
|
||||||
|
switch {
|
||||||
|
case strings.Contains(s, "\n"):
|
||||||
|
if e.flow {
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
} else {
|
||||||
|
style = yaml_LITERAL_SCALAR_STYLE
|
||||||
|
}
|
||||||
|
case canUsePlain:
|
||||||
|
style = yaml_PLAIN_SCALAR_STYLE
|
||||||
|
default:
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) boolv(tag string, in reflect.Value) {
|
||||||
|
var s string
|
||||||
|
if in.Bool() {
|
||||||
|
s = "true"
|
||||||
|
} else {
|
||||||
|
s = "false"
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) intv(tag string, in reflect.Value) {
|
||||||
|
s := strconv.FormatInt(in.Int(), 10)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uintv(tag string, in reflect.Value) {
|
||||||
|
s := strconv.FormatUint(in.Uint(), 10)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) timev(tag string, in reflect.Value) {
|
||||||
|
t := in.Interface().(time.Time)
|
||||||
|
s := t.Format(time.RFC3339Nano)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) floatv(tag string, in reflect.Value) {
|
||||||
|
// Issue #352: When formatting, use the precision of the underlying value
|
||||||
|
precision := 64
|
||||||
|
if in.Kind() == reflect.Float32 {
|
||||||
|
precision = 32
|
||||||
|
}
|
||||||
|
|
||||||
|
s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
|
||||||
|
switch s {
|
||||||
|
case "+Inf":
|
||||||
|
s = ".inf"
|
||||||
|
case "-Inf":
|
||||||
|
s = "-.inf"
|
||||||
|
case "NaN":
|
||||||
|
s = ".nan"
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) nilv() {
|
||||||
|
e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
|
||||||
|
// TODO Kill this function. Replace all initialize calls by their underlining Go literals.
|
||||||
|
implicit := tag == ""
|
||||||
|
if !implicit {
|
||||||
|
tag = longTag(tag)
|
||||||
|
}
|
||||||
|
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
|
||||||
|
e.event.head_comment = head
|
||||||
|
e.event.line_comment = line
|
||||||
|
e.event.foot_comment = foot
|
||||||
|
e.event.tail_comment = tail
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) nodev(in reflect.Value) {
|
||||||
|
e.node(in.Interface().(*Node), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) node(node *Node, tail string) {
|
||||||
|
// If the tag was not explicitly requested, and dropping it won't change the
|
||||||
|
// implicit tag of the value, don't include it in the presentation.
|
||||||
|
var tag = node.Tag
|
||||||
|
var stag = shortTag(tag)
|
||||||
|
var rtag string
|
||||||
|
var forceQuoting bool
|
||||||
|
if tag != "" && node.Style&TaggedStyle == 0 {
|
||||||
|
if node.Kind == ScalarNode {
|
||||||
|
if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
|
||||||
|
tag = ""
|
||||||
|
} else {
|
||||||
|
rtag, _ = resolve("", node.Value)
|
||||||
|
if rtag == stag {
|
||||||
|
tag = ""
|
||||||
|
} else if stag == strTag {
|
||||||
|
tag = ""
|
||||||
|
forceQuoting = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch node.Kind {
|
||||||
|
case MappingNode:
|
||||||
|
rtag = mapTag
|
||||||
|
case SequenceNode:
|
||||||
|
rtag = seqTag
|
||||||
|
}
|
||||||
|
if rtag == stag {
|
||||||
|
tag = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch node.Kind {
|
||||||
|
case DocumentNode:
|
||||||
|
yaml_document_start_event_initialize(&e.event, nil, nil, true)
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.emit()
|
||||||
|
for _, node := range node.Content {
|
||||||
|
e.node(node, "")
|
||||||
|
}
|
||||||
|
yaml_document_end_event_initialize(&e.event, true)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case SequenceNode:
|
||||||
|
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||||
|
if node.Style&FlowStyle != 0 {
|
||||||
|
style = yaml_FLOW_SEQUENCE_STYLE
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(tag), tag == "", style))
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.emit()
|
||||||
|
for _, node := range node.Content {
|
||||||
|
e.node(node, "")
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_end_event_initialize(&e.event))
|
||||||
|
e.event.line_comment = []byte(node.LineComment)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case MappingNode:
|
||||||
|
style := yaml_BLOCK_MAPPING_STYLE
|
||||||
|
if node.Style&FlowStyle != 0 {
|
||||||
|
style = yaml_FLOW_MAPPING_STYLE
|
||||||
|
}
|
||||||
|
yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(tag), tag == "", style)
|
||||||
|
e.event.tail_comment = []byte(tail)
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
// The tail logic below moves the foot comment of prior keys to the following key,
|
||||||
|
// since the value for each key may be a nested structure and the foot needs to be
|
||||||
|
// processed only the entirety of the value is streamed. The last tail is processed
|
||||||
|
// with the mapping end event.
|
||||||
|
var tail string
|
||||||
|
for i := 0; i+1 < len(node.Content); i += 2 {
|
||||||
|
k := node.Content[i]
|
||||||
|
foot := k.FootComment
|
||||||
|
if foot != "" {
|
||||||
|
kopy := *k
|
||||||
|
kopy.FootComment = ""
|
||||||
|
k = &kopy
|
||||||
|
}
|
||||||
|
e.node(k, tail)
|
||||||
|
tail = foot
|
||||||
|
|
||||||
|
v := node.Content[i+1]
|
||||||
|
e.node(v, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
yaml_mapping_end_event_initialize(&e.event)
|
||||||
|
e.event.tail_comment = []byte(tail)
|
||||||
|
e.event.line_comment = []byte(node.LineComment)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case AliasNode:
|
||||||
|
yaml_alias_event_initialize(&e.event, []byte(node.Value))
|
||||||
|
e.event.head_comment = []byte(node.HeadComment)
|
||||||
|
e.event.line_comment = []byte(node.LineComment)
|
||||||
|
e.event.foot_comment = []byte(node.FootComment)
|
||||||
|
e.emit()
|
||||||
|
|
||||||
|
case ScalarNode:
|
||||||
|
value := node.Value
|
||||||
|
if !utf8.ValidString(value) {
|
||||||
|
if tag == binaryTag {
|
||||||
|
failf("explicitly tagged !!binary data must be base64-encoded")
|
||||||
|
}
|
||||||
|
if tag != "" {
|
||||||
|
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
|
||||||
|
}
|
||||||
|
// It can't be encoded directly as YAML so use a binary tag
|
||||||
|
// and encode it as base64.
|
||||||
|
tag = binaryTag
|
||||||
|
value = encodeBase64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
style := yaml_PLAIN_SCALAR_STYLE
|
||||||
|
switch {
|
||||||
|
case node.Style&DoubleQuotedStyle != 0:
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
case node.Style&SingleQuotedStyle != 0:
|
||||||
|
style = yaml_SINGLE_QUOTED_SCALAR_STYLE
|
||||||
|
case node.Style&LiteralStyle != 0:
|
||||||
|
style = yaml_LITERAL_SCALAR_STYLE
|
||||||
|
case node.Style&FoldedStyle != 0:
|
||||||
|
style = yaml_FOLDED_SCALAR_STYLE
|
||||||
|
case strings.Contains(value, "\n"):
|
||||||
|
style = yaml_LITERAL_SCALAR_STYLE
|
||||||
|
case forceQuoting:
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
}
|
||||||
|
|
||||||
|
e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
|
||||||
|
}
|
||||||
|
}
|
5
vendor/gopkg.in/yaml.v3/go.mod
generated
vendored
Normal file
5
vendor/gopkg.in/yaml.v3/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
require (
|
||||||
|
"gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
|
||||||
|
)
|
1229
vendor/gopkg.in/yaml.v3/parserc.go
generated
vendored
Normal file
1229
vendor/gopkg.in/yaml.v3/parserc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
434
vendor/gopkg.in/yaml.v3/readerc.go
generated
vendored
Normal file
434
vendor/gopkg.in/yaml.v3/readerc.go
generated
vendored
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
// so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set the reader error and return 0.
|
||||||
|
func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
|
||||||
|
parser.error = yaml_READER_ERROR
|
||||||
|
parser.problem = problem
|
||||||
|
parser.problem_offset = offset
|
||||||
|
parser.problem_value = value
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte order marks.
|
||||||
|
const (
|
||||||
|
bom_UTF8 = "\xef\xbb\xbf"
|
||||||
|
bom_UTF16LE = "\xff\xfe"
|
||||||
|
bom_UTF16BE = "\xfe\xff"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Determine the input stream encoding by checking the BOM symbol. If no BOM is
|
||||||
|
// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
|
||||||
|
func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
|
||||||
|
// Ensure that we had enough bytes in the raw buffer.
|
||||||
|
for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
|
||||||
|
if !yaml_parser_update_raw_buffer(parser) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the encoding.
|
||||||
|
buf := parser.raw_buffer
|
||||||
|
pos := parser.raw_buffer_pos
|
||||||
|
avail := len(buf) - pos
|
||||||
|
if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
|
||||||
|
parser.encoding = yaml_UTF16LE_ENCODING
|
||||||
|
parser.raw_buffer_pos += 2
|
||||||
|
parser.offset += 2
|
||||||
|
} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
|
||||||
|
parser.encoding = yaml_UTF16BE_ENCODING
|
||||||
|
parser.raw_buffer_pos += 2
|
||||||
|
parser.offset += 2
|
||||||
|
} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
|
||||||
|
parser.encoding = yaml_UTF8_ENCODING
|
||||||
|
parser.raw_buffer_pos += 3
|
||||||
|
parser.offset += 3
|
||||||
|
} else {
|
||||||
|
parser.encoding = yaml_UTF8_ENCODING
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the raw buffer.
|
||||||
|
func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
|
||||||
|
size_read := 0
|
||||||
|
|
||||||
|
// Return if the raw buffer is full.
|
||||||
|
if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return on EOF.
|
||||||
|
if parser.eof {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the remaining bytes in the raw buffer to the beginning.
|
||||||
|
if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
|
||||||
|
copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
|
||||||
|
}
|
||||||
|
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
|
||||||
|
parser.raw_buffer_pos = 0
|
||||||
|
|
||||||
|
// Call the read handler to fill the buffer.
|
||||||
|
size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
|
||||||
|
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
|
||||||
|
if err == io.EOF {
|
||||||
|
parser.eof = true
|
||||||
|
} else if err != nil {
|
||||||
|
return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the buffer contains at least `length` characters.
|
||||||
|
// Return true on success, false on failure.
|
||||||
|
//
|
||||||
|
// The length is supposed to be significantly less that the buffer size.
|
||||||
|
func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
|
||||||
|
if parser.read_handler == nil {
|
||||||
|
panic("read handler must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Go] This function was changed to guarantee the requested length size at EOF.
|
||||||
|
// The fact we need to do this is pretty awful, but the description above implies
|
||||||
|
// for that to be the case, and there are tests
|
||||||
|
|
||||||
|
// If the EOF flag is set and the raw buffer is empty, do nothing.
|
||||||
|
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||||
|
// [Go] ACTUALLY! Read the documentation of this function above.
|
||||||
|
// This is just broken. To return true, we need to have the
|
||||||
|
// given length in the buffer. Not doing that means every single
|
||||||
|
// check that calls this function to make sure the buffer has a
|
||||||
|
// given length is Go) panicking; or C) accessing invalid memory.
|
||||||
|
//return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return if the buffer contains enough characters.
|
||||||
|
if parser.unread >= length {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the input encoding if it is not known yet.
|
||||||
|
if parser.encoding == yaml_ANY_ENCODING {
|
||||||
|
if !yaml_parser_determine_encoding(parser) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the unread characters to the beginning of the buffer.
|
||||||
|
buffer_len := len(parser.buffer)
|
||||||
|
if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
|
||||||
|
copy(parser.buffer, parser.buffer[parser.buffer_pos:])
|
||||||
|
buffer_len -= parser.buffer_pos
|
||||||
|
parser.buffer_pos = 0
|
||||||
|
} else if parser.buffer_pos == buffer_len {
|
||||||
|
buffer_len = 0
|
||||||
|
parser.buffer_pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the whole buffer for writing, and cut it before returning.
|
||||||
|
parser.buffer = parser.buffer[:cap(parser.buffer)]
|
||||||
|
|
||||||
|
// Fill the buffer until it has enough characters.
|
||||||
|
first := true
|
||||||
|
for parser.unread < length {
|
||||||
|
|
||||||
|
// Fill the raw buffer if necessary.
|
||||||
|
if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||||
|
if !yaml_parser_update_raw_buffer(parser) {
|
||||||
|
parser.buffer = parser.buffer[:buffer_len]
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = false
|
||||||
|
|
||||||
|
// Decode the raw buffer.
|
||||||
|
inner:
|
||||||
|
for parser.raw_buffer_pos != len(parser.raw_buffer) {
|
||||||
|
var value rune
|
||||||
|
var width int
|
||||||
|
|
||||||
|
raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
|
||||||
|
|
||||||
|
// Decode the next character.
|
||||||
|
switch parser.encoding {
|
||||||
|
case yaml_UTF8_ENCODING:
|
||||||
|
// Decode a UTF-8 character. Check RFC 3629
|
||||||
|
// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
|
||||||
|
//
|
||||||
|
// The following table (taken from the RFC) is used for
|
||||||
|
// decoding.
|
||||||
|
//
|
||||||
|
// Char. number range | UTF-8 octet sequence
|
||||||
|
// (hexadecimal) | (binary)
|
||||||
|
// --------------------+------------------------------------
|
||||||
|
// 0000 0000-0000 007F | 0xxxxxxx
|
||||||
|
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||||
|
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
//
|
||||||
|
// Additionally, the characters in the range 0xD800-0xDFFF
|
||||||
|
// are prohibited as they are reserved for use with UTF-16
|
||||||
|
// surrogate pairs.
|
||||||
|
|
||||||
|
// Determine the length of the UTF-8 sequence.
|
||||||
|
octet := parser.raw_buffer[parser.raw_buffer_pos]
|
||||||
|
switch {
|
||||||
|
case octet&0x80 == 0x00:
|
||||||
|
width = 1
|
||||||
|
case octet&0xE0 == 0xC0:
|
||||||
|
width = 2
|
||||||
|
case octet&0xF0 == 0xE0:
|
||||||
|
width = 3
|
||||||
|
case octet&0xF8 == 0xF0:
|
||||||
|
width = 4
|
||||||
|
default:
|
||||||
|
// The leading octet is invalid.
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid leading UTF-8 octet",
|
||||||
|
parser.offset, int(octet))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the raw buffer contains an incomplete character.
|
||||||
|
if width > raw_unread {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-8 octet sequence",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the leading octet.
|
||||||
|
switch {
|
||||||
|
case octet&0x80 == 0x00:
|
||||||
|
value = rune(octet & 0x7F)
|
||||||
|
case octet&0xE0 == 0xC0:
|
||||||
|
value = rune(octet & 0x1F)
|
||||||
|
case octet&0xF0 == 0xE0:
|
||||||
|
value = rune(octet & 0x0F)
|
||||||
|
case octet&0xF8 == 0xF0:
|
||||||
|
value = rune(octet & 0x07)
|
||||||
|
default:
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check and decode the trailing octets.
|
||||||
|
for k := 1; k < width; k++ {
|
||||||
|
octet = parser.raw_buffer[parser.raw_buffer_pos+k]
|
||||||
|
|
||||||
|
// Check if the octet is valid.
|
||||||
|
if (octet & 0xC0) != 0x80 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid trailing UTF-8 octet",
|
||||||
|
parser.offset+k, int(octet))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the octet.
|
||||||
|
value = (value << 6) + rune(octet&0x3F)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the length of the sequence against the value.
|
||||||
|
switch {
|
||||||
|
case width == 1:
|
||||||
|
case width == 2 && value >= 0x80:
|
||||||
|
case width == 3 && value >= 0x800:
|
||||||
|
case width == 4 && value >= 0x10000:
|
||||||
|
default:
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid length of a UTF-8 sequence",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the range of the value.
|
||||||
|
if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid Unicode character",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
|
||||||
|
var low, high int
|
||||||
|
if parser.encoding == yaml_UTF16LE_ENCODING {
|
||||||
|
low, high = 0, 1
|
||||||
|
} else {
|
||||||
|
low, high = 1, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// The UTF-16 encoding is not as simple as one might
|
||||||
|
// naively think. Check RFC 2781
|
||||||
|
// (http://www.ietf.org/rfc/rfc2781.txt).
|
||||||
|
//
|
||||||
|
// Normally, two subsequent bytes describe a Unicode
|
||||||
|
// character. However a special technique (called a
|
||||||
|
// surrogate pair) is used for specifying character
|
||||||
|
// values larger than 0xFFFF.
|
||||||
|
//
|
||||||
|
// A surrogate pair consists of two pseudo-characters:
|
||||||
|
// high surrogate area (0xD800-0xDBFF)
|
||||||
|
// low surrogate area (0xDC00-0xDFFF)
|
||||||
|
//
|
||||||
|
// The following formulas are used for decoding
|
||||||
|
// and encoding characters using surrogate pairs:
|
||||||
|
//
|
||||||
|
// U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
|
||||||
|
// U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
|
||||||
|
// W1 = 110110yyyyyyyyyy
|
||||||
|
// W2 = 110111xxxxxxxxxx
|
||||||
|
//
|
||||||
|
// where U is the character value, W1 is the high surrogate
|
||||||
|
// area, W2 is the low surrogate area.
|
||||||
|
|
||||||
|
// Check for incomplete UTF-16 character.
|
||||||
|
if raw_unread < 2 {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-16 character",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the character.
|
||||||
|
value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
|
||||||
|
(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
|
||||||
|
|
||||||
|
// Check for unexpected low surrogate area.
|
||||||
|
if value&0xFC00 == 0xDC00 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"unexpected low surrogate area",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a high surrogate area.
|
||||||
|
if value&0xFC00 == 0xD800 {
|
||||||
|
width = 4
|
||||||
|
|
||||||
|
// Check for incomplete surrogate pair.
|
||||||
|
if raw_unread < 4 {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-16 surrogate pair",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next character.
|
||||||
|
value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
|
||||||
|
(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
|
||||||
|
|
||||||
|
// Check for a low surrogate area.
|
||||||
|
if value2&0xFC00 != 0xDC00 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"expected low surrogate area",
|
||||||
|
parser.offset+2, int(value2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the value of the surrogate pair.
|
||||||
|
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
|
||||||
|
} else {
|
||||||
|
width = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("impossible")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is in the allowed range:
|
||||||
|
// #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
|
||||||
|
// | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
|
||||||
|
// | [#x10000-#x10FFFF] (32 bit)
|
||||||
|
switch {
|
||||||
|
case value == 0x09:
|
||||||
|
case value == 0x0A:
|
||||||
|
case value == 0x0D:
|
||||||
|
case value >= 0x20 && value <= 0x7E:
|
||||||
|
case value == 0x85:
|
||||||
|
case value >= 0xA0 && value <= 0xD7FF:
|
||||||
|
case value >= 0xE000 && value <= 0xFFFD:
|
||||||
|
case value >= 0x10000 && value <= 0x10FFFF:
|
||||||
|
default:
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"control characters are not allowed",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the raw pointers.
|
||||||
|
parser.raw_buffer_pos += width
|
||||||
|
parser.offset += width
|
||||||
|
|
||||||
|
// Finally put the character into the buffer.
|
||||||
|
if value <= 0x7F {
|
||||||
|
// 0000 0000-0000 007F . 0xxxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(value)
|
||||||
|
buffer_len += 1
|
||||||
|
} else if value <= 0x7FF {
|
||||||
|
// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
|
||||||
|
buffer_len += 2
|
||||||
|
} else if value <= 0xFFFF {
|
||||||
|
// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
|
||||||
|
buffer_len += 3
|
||||||
|
} else {
|
||||||
|
// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
|
||||||
|
buffer_len += 4
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.unread++
|
||||||
|
}
|
||||||
|
|
||||||
|
// On EOF, put NUL into the buffer and return.
|
||||||
|
if parser.eof {
|
||||||
|
parser.buffer[buffer_len] = 0
|
||||||
|
buffer_len++
|
||||||
|
parser.unread++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// [Go] Read the documentation of this function above. To return true,
|
||||||
|
// we need to have the given length in the buffer. Not doing that means
|
||||||
|
// every single check that calls this function to make sure the buffer
|
||||||
|
// has a given length is Go) panicking; or C) accessing invalid memory.
|
||||||
|
// This happens here due to the EOF above breaking early.
|
||||||
|
for buffer_len < length {
|
||||||
|
parser.buffer[buffer_len] = 0
|
||||||
|
buffer_len++
|
||||||
|
}
|
||||||
|
parser.buffer = parser.buffer[:buffer_len]
|
||||||
|
return true
|
||||||
|
}
|
326
vendor/gopkg.in/yaml.v3/resolve.go
generated
vendored
Normal file
326
vendor/gopkg.in/yaml.v3/resolve.go
generated
vendored
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"math"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type resolveMapItem struct {
|
||||||
|
value interface{}
|
||||||
|
tag string
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolveTable = make([]byte, 256)
|
||||||
|
var resolveMap = make(map[string]resolveMapItem)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
t := resolveTable
|
||||||
|
t[int('+')] = 'S' // Sign
|
||||||
|
t[int('-')] = 'S'
|
||||||
|
for _, c := range "0123456789" {
|
||||||
|
t[int(c)] = 'D' // Digit
|
||||||
|
}
|
||||||
|
for _, c := range "yYnNtTfFoO~" {
|
||||||
|
t[int(c)] = 'M' // In map
|
||||||
|
}
|
||||||
|
t[int('.')] = '.' // Float (potentially in map)
|
||||||
|
|
||||||
|
var resolveMapList = []struct {
|
||||||
|
v interface{}
|
||||||
|
tag string
|
||||||
|
l []string
|
||||||
|
}{
|
||||||
|
{true, boolTag, []string{"true", "True", "TRUE"}},
|
||||||
|
{false, boolTag, []string{"false", "False", "FALSE"}},
|
||||||
|
{nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
|
||||||
|
{math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
|
||||||
|
{math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
|
||||||
|
{math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
|
||||||
|
{math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
|
||||||
|
{"<<", mergeTag, []string{"<<"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
m := resolveMap
|
||||||
|
for _, item := range resolveMapList {
|
||||||
|
for _, s := range item.l {
|
||||||
|
m[s] = resolveMapItem{item.v, item.tag}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
nullTag = "!!null"
|
||||||
|
boolTag = "!!bool"
|
||||||
|
strTag = "!!str"
|
||||||
|
intTag = "!!int"
|
||||||
|
floatTag = "!!float"
|
||||||
|
timestampTag = "!!timestamp"
|
||||||
|
seqTag = "!!seq"
|
||||||
|
mapTag = "!!map"
|
||||||
|
binaryTag = "!!binary"
|
||||||
|
mergeTag = "!!merge"
|
||||||
|
)
|
||||||
|
|
||||||
|
var longTags = make(map[string]string)
|
||||||
|
var shortTags = make(map[string]string)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
|
||||||
|
ltag := longTag(stag)
|
||||||
|
longTags[stag] = ltag
|
||||||
|
shortTags[ltag] = stag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const longTagPrefix = "tag:yaml.org,2002:"
|
||||||
|
|
||||||
|
func shortTag(tag string) string {
|
||||||
|
if strings.HasPrefix(tag, longTagPrefix) {
|
||||||
|
if stag, ok := shortTags[tag]; ok {
|
||||||
|
return stag
|
||||||
|
}
|
||||||
|
return "!!" + tag[len(longTagPrefix):]
|
||||||
|
}
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func longTag(tag string) string {
|
||||||
|
if strings.HasPrefix(tag, "!!") {
|
||||||
|
if ltag, ok := longTags[tag]; ok {
|
||||||
|
return ltag
|
||||||
|
}
|
||||||
|
return longTagPrefix + tag[2:]
|
||||||
|
}
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolvableTag(tag string) bool {
|
||||||
|
switch tag {
|
||||||
|
case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
|
||||||
|
|
||||||
|
func resolve(tag string, in string) (rtag string, out interface{}) {
|
||||||
|
tag = shortTag(tag)
|
||||||
|
if !resolvableTag(tag) {
|
||||||
|
return tag, in
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
switch tag {
|
||||||
|
case "", rtag, strTag, binaryTag:
|
||||||
|
return
|
||||||
|
case floatTag:
|
||||||
|
if rtag == intTag {
|
||||||
|
switch v := out.(type) {
|
||||||
|
case int64:
|
||||||
|
rtag = floatTag
|
||||||
|
out = float64(v)
|
||||||
|
return
|
||||||
|
case int:
|
||||||
|
rtag = floatTag
|
||||||
|
out = float64(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Any data is accepted as a !!str or !!binary.
|
||||||
|
// Otherwise, the prefix is enough of a hint about what it might be.
|
||||||
|
hint := byte('N')
|
||||||
|
if in != "" {
|
||||||
|
hint = resolveTable[in[0]]
|
||||||
|
}
|
||||||
|
if hint != 0 && tag != strTag && tag != binaryTag {
|
||||||
|
// Handle things we can lookup in a map.
|
||||||
|
if item, ok := resolveMap[in]; ok {
|
||||||
|
return item.tag, item.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
|
||||||
|
// are purposefully unsupported here. They're still quoted on
|
||||||
|
// the way out for compatibility with other parser, though.
|
||||||
|
|
||||||
|
switch hint {
|
||||||
|
case 'M':
|
||||||
|
// We've already checked the map above.
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
// Not in the map, so maybe a normal float.
|
||||||
|
floatv, err := strconv.ParseFloat(in, 64)
|
||||||
|
if err == nil {
|
||||||
|
return floatTag, floatv
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'D', 'S':
|
||||||
|
// Int, float, or timestamp.
|
||||||
|
// Only try values as a timestamp if the value is unquoted or there's an explicit
|
||||||
|
// !!timestamp tag.
|
||||||
|
if tag == "" || tag == timestampTag {
|
||||||
|
t, ok := parseTimestamp(in)
|
||||||
|
if ok {
|
||||||
|
return timestampTag, t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plain := strings.Replace(in, "_", "", -1)
|
||||||
|
intv, err := strconv.ParseInt(plain, 0, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain, 0, 64)
|
||||||
|
if err == nil {
|
||||||
|
return intTag, uintv
|
||||||
|
}
|
||||||
|
if yamlStyleFloat.MatchString(plain) {
|
||||||
|
floatv, err := strconv.ParseFloat(plain, 64)
|
||||||
|
if err == nil {
|
||||||
|
return floatTag, floatv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(plain, "0b") {
|
||||||
|
intv, err := strconv.ParseInt(plain[2:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain[2:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
return intTag, uintv
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(plain, "-0b") {
|
||||||
|
intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
if true || intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Octals as introduced in version 1.2 of the spec.
|
||||||
|
// Octals from the 1.1 spec, spelled as 0777, are still
|
||||||
|
// decoded by default in v3 as well for compatibility.
|
||||||
|
// May be dropped in v4 depending on how usage evolves.
|
||||||
|
if strings.HasPrefix(plain, "0o") {
|
||||||
|
intv, err := strconv.ParseInt(plain[2:], 8, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain[2:], 8, 64)
|
||||||
|
if err == nil {
|
||||||
|
return intTag, uintv
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(plain, "-0o") {
|
||||||
|
intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
|
||||||
|
if err == nil {
|
||||||
|
if true || intv == int64(int(intv)) {
|
||||||
|
return intTag, int(intv)
|
||||||
|
} else {
|
||||||
|
return intTag, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strTag, in
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeBase64 encodes s as base64 that is broken up into multiple lines
|
||||||
|
// as appropriate for the resulting length.
|
||||||
|
func encodeBase64(s string) string {
|
||||||
|
const lineLen = 70
|
||||||
|
encLen := base64.StdEncoding.EncodedLen(len(s))
|
||||||
|
lines := encLen/lineLen + 1
|
||||||
|
buf := make([]byte, encLen*2+lines)
|
||||||
|
in := buf[0:encLen]
|
||||||
|
out := buf[encLen:]
|
||||||
|
base64.StdEncoding.Encode(in, []byte(s))
|
||||||
|
k := 0
|
||||||
|
for i := 0; i < len(in); i += lineLen {
|
||||||
|
j := i + lineLen
|
||||||
|
if j > len(in) {
|
||||||
|
j = len(in)
|
||||||
|
}
|
||||||
|
k += copy(out[k:], in[i:j])
|
||||||
|
if lines > 1 {
|
||||||
|
out[k] = '\n'
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(out[:k])
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a subset of the formats allowed by the regular expression
|
||||||
|
// defined at http://yaml.org/type/timestamp.html.
|
||||||
|
var allowedTimestampFormats = []string{
|
||||||
|
"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
|
||||||
|
"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
|
||||||
|
"2006-1-2 15:4:5.999999999", // space separated with no time zone
|
||||||
|
"2006-1-2", // date only
|
||||||
|
// Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
|
||||||
|
// from the set of examples.
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseTimestamp parses s as a timestamp string and
|
||||||
|
// returns the timestamp and reports whether it succeeded.
|
||||||
|
// Timestamp formats are defined at http://yaml.org/type/timestamp.html
|
||||||
|
func parseTimestamp(s string) (time.Time, bool) {
|
||||||
|
// TODO write code to check all the formats supported by
|
||||||
|
// http://yaml.org/type/timestamp.html instead of using time.Parse.
|
||||||
|
|
||||||
|
// Quick check: all date formats start with YYYY-.
|
||||||
|
i := 0
|
||||||
|
for ; i < len(s); i++ {
|
||||||
|
if c := s[i]; c < '0' || c > '9' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i != 4 || i == len(s) || s[i] != '-' {
|
||||||
|
return time.Time{}, false
|
||||||
|
}
|
||||||
|
for _, format := range allowedTimestampFormats {
|
||||||
|
if t, err := time.Parse(format, s); err == nil {
|
||||||
|
return t, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return time.Time{}, false
|
||||||
|
}
|
3025
vendor/gopkg.in/yaml.v3/scannerc.go
generated
vendored
Normal file
3025
vendor/gopkg.in/yaml.v3/scannerc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
134
vendor/gopkg.in/yaml.v3/sorter.go
generated
vendored
Normal file
134
vendor/gopkg.in/yaml.v3/sorter.go
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type keyList []reflect.Value
|
||||||
|
|
||||||
|
func (l keyList) Len() int { return len(l) }
|
||||||
|
func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||||
|
func (l keyList) Less(i, j int) bool {
|
||||||
|
a := l[i]
|
||||||
|
b := l[j]
|
||||||
|
ak := a.Kind()
|
||||||
|
bk := b.Kind()
|
||||||
|
for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
|
||||||
|
a = a.Elem()
|
||||||
|
ak = a.Kind()
|
||||||
|
}
|
||||||
|
for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
|
||||||
|
b = b.Elem()
|
||||||
|
bk = b.Kind()
|
||||||
|
}
|
||||||
|
af, aok := keyFloat(a)
|
||||||
|
bf, bok := keyFloat(b)
|
||||||
|
if aok && bok {
|
||||||
|
if af != bf {
|
||||||
|
return af < bf
|
||||||
|
}
|
||||||
|
if ak != bk {
|
||||||
|
return ak < bk
|
||||||
|
}
|
||||||
|
return numLess(a, b)
|
||||||
|
}
|
||||||
|
if ak != reflect.String || bk != reflect.String {
|
||||||
|
return ak < bk
|
||||||
|
}
|
||||||
|
ar, br := []rune(a.String()), []rune(b.String())
|
||||||
|
digits := false
|
||||||
|
for i := 0; i < len(ar) && i < len(br); i++ {
|
||||||
|
if ar[i] == br[i] {
|
||||||
|
digits = unicode.IsDigit(ar[i])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
al := unicode.IsLetter(ar[i])
|
||||||
|
bl := unicode.IsLetter(br[i])
|
||||||
|
if al && bl {
|
||||||
|
return ar[i] < br[i]
|
||||||
|
}
|
||||||
|
if al || bl {
|
||||||
|
if digits {
|
||||||
|
return al
|
||||||
|
} else {
|
||||||
|
return bl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ai, bi int
|
||||||
|
var an, bn int64
|
||||||
|
if ar[i] == '0' || br[i] == '0' {
|
||||||
|
for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
|
||||||
|
if ar[j] != '0' {
|
||||||
|
an = 1
|
||||||
|
bn = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
|
||||||
|
an = an*10 + int64(ar[ai]-'0')
|
||||||
|
}
|
||||||
|
for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
|
||||||
|
bn = bn*10 + int64(br[bi]-'0')
|
||||||
|
}
|
||||||
|
if an != bn {
|
||||||
|
return an < bn
|
||||||
|
}
|
||||||
|
if ai != bi {
|
||||||
|
return ai < bi
|
||||||
|
}
|
||||||
|
return ar[i] < br[i]
|
||||||
|
}
|
||||||
|
return len(ar) < len(br)
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyFloat returns a float value for v if it is a number/bool
|
||||||
|
// and whether it is a number/bool or not.
|
||||||
|
func keyFloat(v reflect.Value) (f float64, ok bool) {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return float64(v.Int()), true
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float(), true
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return float64(v.Uint()), true
|
||||||
|
case reflect.Bool:
|
||||||
|
if v.Bool() {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// numLess returns whether a < b.
|
||||||
|
// a and b must necessarily have the same kind.
|
||||||
|
func numLess(a, b reflect.Value) bool {
|
||||||
|
switch a.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return a.Int() < b.Int()
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return a.Float() < b.Float()
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return a.Uint() < b.Uint()
|
||||||
|
case reflect.Bool:
|
||||||
|
return !a.Bool() && b.Bool()
|
||||||
|
}
|
||||||
|
panic("not a number")
|
||||||
|
}
|
48
vendor/gopkg.in/yaml.v3/writerc.go
generated
vendored
Normal file
48
vendor/gopkg.in/yaml.v3/writerc.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
// so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
// Set the writer error and return false.
|
||||||
|
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
|
||||||
|
emitter.error = yaml_WRITER_ERROR
|
||||||
|
emitter.problem = problem
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the output buffer.
|
||||||
|
func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
|
||||||
|
if emitter.write_handler == nil {
|
||||||
|
panic("write handler not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the buffer is empty.
|
||||||
|
if emitter.buffer_pos == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
|
||||||
|
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||||
|
}
|
||||||
|
emitter.buffer_pos = 0
|
||||||
|
return true
|
||||||
|
}
|
662
vendor/gopkg.in/yaml.v3/yaml.go
generated
vendored
Normal file
662
vendor/gopkg.in/yaml.v3/yaml.go
generated
vendored
Normal file
@ -0,0 +1,662 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package yaml implements YAML support for the Go language.
|
||||||
|
//
|
||||||
|
// Source code and other details for the project are available at GitHub:
|
||||||
|
//
|
||||||
|
// https://github.com/go-yaml/yaml
|
||||||
|
//
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The Unmarshaler interface may be implemented by types to customize their
|
||||||
|
// behavior when being unmarshaled from a YAML document.
|
||||||
|
type Unmarshaler interface {
|
||||||
|
UnmarshalYAML(value *Node) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type obsoleteUnmarshaler interface {
|
||||||
|
UnmarshalYAML(unmarshal func(interface{}) error) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Marshaler interface may be implemented by types to customize their
|
||||||
|
// behavior when being marshaled into a YAML document. The returned value
|
||||||
|
// is marshaled in place of the original value implementing Marshaler.
|
||||||
|
//
|
||||||
|
// If an error is returned by MarshalYAML, the marshaling procedure stops
|
||||||
|
// and returns with the provided error.
|
||||||
|
type Marshaler interface {
|
||||||
|
MarshalYAML() (interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal decodes the first document found within the in byte slice
|
||||||
|
// and assigns decoded values into the out value.
|
||||||
|
//
|
||||||
|
// Maps and pointers (to a struct, string, int, etc) are accepted as out
|
||||||
|
// values. If an internal pointer within a struct is not initialized,
|
||||||
|
// the yaml package will initialize it if necessary for unmarshalling
|
||||||
|
// the provided data. The out parameter must not be nil.
|
||||||
|
//
|
||||||
|
// The type of the decoded values should be compatible with the respective
|
||||||
|
// values in out. If one or more values cannot be decoded due to a type
|
||||||
|
// mismatches, decoding continues partially until the end of the YAML
|
||||||
|
// content, and a *yaml.TypeError is returned with details for all
|
||||||
|
// missed values.
|
||||||
|
//
|
||||||
|
// Struct fields are only unmarshalled if they are exported (have an
|
||||||
|
// upper case first letter), and are unmarshalled using the field name
|
||||||
|
// lowercased as the default key. Custom keys may be defined via the
|
||||||
|
// "yaml" name in the field tag: the content preceding the first comma
|
||||||
|
// is used as the key, and the following comma-separated options are
|
||||||
|
// used to tweak the marshalling process (see Marshal).
|
||||||
|
// Conflicting names result in a runtime error.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// type T struct {
|
||||||
|
// F int `yaml:"a,omitempty"`
|
||||||
|
// B int
|
||||||
|
// }
|
||||||
|
// var t T
|
||||||
|
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||||
|
//
|
||||||
|
// See the documentation of Marshal for the format of tags and a list of
|
||||||
|
// supported tag options.
|
||||||
|
//
|
||||||
|
func Unmarshal(in []byte, out interface{}) (err error) {
|
||||||
|
return unmarshal(in, out, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Decorder reads and decodes YAML values from an input stream.
|
||||||
|
type Decoder struct {
|
||||||
|
parser *parser
|
||||||
|
knownFields bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDecoder returns a new decoder that reads from r.
|
||||||
|
//
|
||||||
|
// The decoder introduces its own buffering and may read
|
||||||
|
// data from r beyond the YAML values requested.
|
||||||
|
func NewDecoder(r io.Reader) *Decoder {
|
||||||
|
return &Decoder{
|
||||||
|
parser: newParserFromReader(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KnownFields ensures that the keys in decoded mappings to
|
||||||
|
// exist as fields in the struct being decoded into.
|
||||||
|
func (dec *Decoder) KnownFields(enable bool) {
|
||||||
|
dec.knownFields = enable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode reads the next YAML-encoded value from its input
|
||||||
|
// and stores it in the value pointed to by v.
|
||||||
|
//
|
||||||
|
// See the documentation for Unmarshal for details about the
|
||||||
|
// conversion of YAML into a Go value.
|
||||||
|
func (dec *Decoder) Decode(v interface{}) (err error) {
|
||||||
|
d := newDecoder()
|
||||||
|
d.knownFields = dec.knownFields
|
||||||
|
defer handleErr(&err)
|
||||||
|
node := dec.parser.parse()
|
||||||
|
if node == nil {
|
||||||
|
return io.EOF
|
||||||
|
}
|
||||||
|
out := reflect.ValueOf(v)
|
||||||
|
if out.Kind() == reflect.Ptr && !out.IsNil() {
|
||||||
|
out = out.Elem()
|
||||||
|
}
|
||||||
|
d.unmarshal(node, out)
|
||||||
|
if len(d.terrors) > 0 {
|
||||||
|
return &TypeError{d.terrors}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes the node and stores its data into the value pointed to by v.
|
||||||
|
//
|
||||||
|
// See the documentation for Unmarshal for details about the
|
||||||
|
// conversion of YAML into a Go value.
|
||||||
|
func (n *Node) Decode(v interface{}) (err error) {
|
||||||
|
d := newDecoder()
|
||||||
|
defer handleErr(&err)
|
||||||
|
out := reflect.ValueOf(v)
|
||||||
|
if out.Kind() == reflect.Ptr && !out.IsNil() {
|
||||||
|
out = out.Elem()
|
||||||
|
}
|
||||||
|
d.unmarshal(n, out)
|
||||||
|
if len(d.terrors) > 0 {
|
||||||
|
return &TypeError{d.terrors}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshal(in []byte, out interface{}, strict bool) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
d := newDecoder()
|
||||||
|
p := newParser(in)
|
||||||
|
defer p.destroy()
|
||||||
|
node := p.parse()
|
||||||
|
if node != nil {
|
||||||
|
v := reflect.ValueOf(out)
|
||||||
|
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
d.unmarshal(node, v)
|
||||||
|
}
|
||||||
|
if len(d.terrors) > 0 {
|
||||||
|
return &TypeError{d.terrors}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal serializes the value provided into a YAML document. The structure
|
||||||
|
// of the generated document will reflect the structure of the value itself.
|
||||||
|
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
|
||||||
|
//
|
||||||
|
// Struct fields are only marshalled if they are exported (have an upper case
|
||||||
|
// first letter), and are marshalled using the field name lowercased as the
|
||||||
|
// default key. Custom keys may be defined via the "yaml" name in the field
|
||||||
|
// tag: the content preceding the first comma is used as the key, and the
|
||||||
|
// following comma-separated options are used to tweak the marshalling process.
|
||||||
|
// Conflicting names result in a runtime error.
|
||||||
|
//
|
||||||
|
// The field tag format accepted is:
|
||||||
|
//
|
||||||
|
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||||
|
//
|
||||||
|
// The following flags are currently supported:
|
||||||
|
//
|
||||||
|
// omitempty Only include the field if it's not set to the zero
|
||||||
|
// value for the type or to empty slices or maps.
|
||||||
|
// Zero valued structs will be omitted if all their public
|
||||||
|
// fields are zero, unless they implement an IsZero
|
||||||
|
// method (see the IsZeroer interface type), in which
|
||||||
|
// case the field will be included if that method returns true.
|
||||||
|
//
|
||||||
|
// flow Marshal using a flow style (useful for structs,
|
||||||
|
// sequences and maps).
|
||||||
|
//
|
||||||
|
// inline Inline the field, which must be a struct or a map,
|
||||||
|
// causing all of its fields or keys to be processed as if
|
||||||
|
// they were part of the outer struct. For maps, keys must
|
||||||
|
// not conflict with the yaml keys of other struct fields.
|
||||||
|
//
|
||||||
|
// In addition, if the key is "-", the field is ignored.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// type T struct {
|
||||||
|
// F int `yaml:"a,omitempty"`
|
||||||
|
// B int
|
||||||
|
// }
|
||||||
|
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||||
|
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||||
|
//
|
||||||
|
func Marshal(in interface{}) (out []byte, err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e := newEncoder()
|
||||||
|
defer e.destroy()
|
||||||
|
e.marshalDoc("", reflect.ValueOf(in))
|
||||||
|
e.finish()
|
||||||
|
out = e.out
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Encoder writes YAML values to an output stream.
|
||||||
|
type Encoder struct {
|
||||||
|
encoder *encoder
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEncoder returns a new encoder that writes to w.
|
||||||
|
// The Encoder should be closed after use to flush all data
|
||||||
|
// to w.
|
||||||
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
|
return &Encoder{
|
||||||
|
encoder: newEncoderWithWriter(w),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode writes the YAML encoding of v to the stream.
|
||||||
|
// If multiple items are encoded to the stream, the
|
||||||
|
// second and subsequent document will be preceded
|
||||||
|
// with a "---" document separator, but the first will not.
|
||||||
|
//
|
||||||
|
// See the documentation for Marshal for details about the conversion of Go
|
||||||
|
// values to YAML.
|
||||||
|
func (e *Encoder) Encode(v interface{}) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e.encoder.marshalDoc("", reflect.ValueOf(v))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIndent changes the used indentation used when encoding.
|
||||||
|
func (e *Encoder) SetIndent(spaces int) {
|
||||||
|
if spaces < 0 {
|
||||||
|
panic("yaml: cannot indent to a negative number of spaces")
|
||||||
|
}
|
||||||
|
e.encoder.indent = spaces
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the encoder by writing any remaining data.
|
||||||
|
// It does not write a stream terminating string "...".
|
||||||
|
func (e *Encoder) Close() (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e.encoder.finish()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleErr(err *error) {
|
||||||
|
if v := recover(); v != nil {
|
||||||
|
if e, ok := v.(yamlError); ok {
|
||||||
|
*err = e.err
|
||||||
|
} else {
|
||||||
|
panic(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type yamlError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func fail(err error) {
|
||||||
|
panic(yamlError{err})
|
||||||
|
}
|
||||||
|
|
||||||
|
func failf(format string, args ...interface{}) {
|
||||||
|
panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// A TypeError is returned by Unmarshal when one or more fields in
|
||||||
|
// the YAML document cannot be properly decoded into the requested
|
||||||
|
// types. When this error is returned, the value is still
|
||||||
|
// unmarshaled partially.
|
||||||
|
type TypeError struct {
|
||||||
|
Errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TypeError) Error() string {
|
||||||
|
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Kind uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
DocumentNode Kind = 1 << iota
|
||||||
|
SequenceNode
|
||||||
|
MappingNode
|
||||||
|
ScalarNode
|
||||||
|
AliasNode
|
||||||
|
)
|
||||||
|
|
||||||
|
type Style uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
TaggedStyle Style = 1 << iota
|
||||||
|
DoubleQuotedStyle
|
||||||
|
SingleQuotedStyle
|
||||||
|
LiteralStyle
|
||||||
|
FoldedStyle
|
||||||
|
FlowStyle
|
||||||
|
)
|
||||||
|
|
||||||
|
// Node represents an element in the YAML document hierarchy. While documents
|
||||||
|
// are typically encoded and decoded into higher level types, such as structs
|
||||||
|
// and maps, Node is an intermediate representation that allows detailed
|
||||||
|
// control over the content being decoded or encoded.
|
||||||
|
//
|
||||||
|
// Values that make use of the Node type interact with the yaml package in the
|
||||||
|
// same way any other type would do, by encoding and decoding yaml data
|
||||||
|
// directly or indirectly into them.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// var person struct {
|
||||||
|
// Name string
|
||||||
|
// Address yaml.Node
|
||||||
|
// }
|
||||||
|
// err := yaml.Unmarshal(data, &person)
|
||||||
|
//
|
||||||
|
// Or by itself:
|
||||||
|
//
|
||||||
|
// var person Node
|
||||||
|
// err := yaml.Unmarshal(data, &person)
|
||||||
|
//
|
||||||
|
type Node struct {
|
||||||
|
// Kind defines whether the node is a document, a mapping, a sequence,
|
||||||
|
// a scalar value, or an alias to another node. The specific data type of
|
||||||
|
// scalar nodes may be obtained via the ShortTag and LongTag methods.
|
||||||
|
Kind Kind
|
||||||
|
|
||||||
|
// Style allows customizing the apperance of the node in the tree.
|
||||||
|
Style Style
|
||||||
|
|
||||||
|
// Tag holds the YAML tag defining the data type for the value.
|
||||||
|
// When decoding, this field will always be set to the resolved tag,
|
||||||
|
// even when it wasn't explicitly provided in the YAML content.
|
||||||
|
// When encoding, if this field is unset the value type will be
|
||||||
|
// implied from the node properties, and if it is set, it will only
|
||||||
|
// be serialized into the representation if TaggedStyle is used or
|
||||||
|
// the implicit tag diverges from the provided one.
|
||||||
|
Tag string
|
||||||
|
|
||||||
|
// Value holds the unescaped and unquoted represenation of the value.
|
||||||
|
Value string
|
||||||
|
|
||||||
|
// Anchor holds the anchor name for this node, which allows aliases to point to it.
|
||||||
|
Anchor string
|
||||||
|
|
||||||
|
// Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
|
||||||
|
Alias *Node
|
||||||
|
|
||||||
|
// Content holds contained nodes for documents, mappings, and sequences.
|
||||||
|
Content []*Node
|
||||||
|
|
||||||
|
// HeadComment holds any comments in the lines preceding the node and
|
||||||
|
// not separated by an empty line.
|
||||||
|
HeadComment string
|
||||||
|
|
||||||
|
// LineComment holds any comments at the end of the line where the node is in.
|
||||||
|
LineComment string
|
||||||
|
|
||||||
|
// FootComment holds any comments following the node and before empty lines.
|
||||||
|
FootComment string
|
||||||
|
|
||||||
|
// Line and Column hold the node position in the decoded YAML text.
|
||||||
|
// These fields are not respected when encoding the node.
|
||||||
|
Line int
|
||||||
|
Column int
|
||||||
|
}
|
||||||
|
|
||||||
|
// LongTag returns the long form of the tag that indicates the data type for
|
||||||
|
// the node. If the Tag field isn't explicitly defined, one will be computed
|
||||||
|
// based on the node properties.
|
||||||
|
func (n *Node) LongTag() string {
|
||||||
|
return longTag(n.ShortTag())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShortTag returns the short form of the YAML tag that indicates data type for
|
||||||
|
// the node. If the Tag field isn't explicitly defined, one will be computed
|
||||||
|
// based on the node properties.
|
||||||
|
func (n *Node) ShortTag() string {
|
||||||
|
if n.indicatedString() {
|
||||||
|
return strTag
|
||||||
|
}
|
||||||
|
if n.Tag == "" || n.Tag == "!" {
|
||||||
|
switch n.Kind {
|
||||||
|
case MappingNode:
|
||||||
|
return mapTag
|
||||||
|
case SequenceNode:
|
||||||
|
return seqTag
|
||||||
|
case AliasNode:
|
||||||
|
if n.Alias != nil {
|
||||||
|
return n.Alias.ShortTag()
|
||||||
|
}
|
||||||
|
case ScalarNode:
|
||||||
|
tag, _ := resolve("", n.Value)
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return shortTag(n.Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) indicatedString() bool {
|
||||||
|
return n.Kind == ScalarNode &&
|
||||||
|
(shortTag(n.Tag) == strTag ||
|
||||||
|
(n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetString is a convenience function that sets the node to a string value
|
||||||
|
// and defines its style in a pleasant way depending on its content.
|
||||||
|
func (n *Node) SetString(s string) {
|
||||||
|
n.Kind = ScalarNode
|
||||||
|
if utf8.ValidString(s) {
|
||||||
|
n.Value = s
|
||||||
|
n.Tag = strTag
|
||||||
|
} else {
|
||||||
|
n.Value = encodeBase64(s)
|
||||||
|
n.Tag = binaryTag
|
||||||
|
}
|
||||||
|
if strings.Contains(n.Value, "\n") {
|
||||||
|
n.Style = LiteralStyle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Maintain a mapping of keys to structure field indexes
|
||||||
|
|
||||||
|
// The code in this section was copied from mgo/bson.
|
||||||
|
|
||||||
|
// structInfo holds details for the serialization of fields of
|
||||||
|
// a given struct.
|
||||||
|
type structInfo struct {
|
||||||
|
FieldsMap map[string]fieldInfo
|
||||||
|
FieldsList []fieldInfo
|
||||||
|
|
||||||
|
// InlineMap is the number of the field in the struct that
|
||||||
|
// contains an ,inline map, or -1 if there's none.
|
||||||
|
InlineMap int
|
||||||
|
|
||||||
|
// InlineUnmarshalers holds indexes to inlined fields that
|
||||||
|
// contain unmarshaler values.
|
||||||
|
InlineUnmarshalers [][]int
|
||||||
|
}
|
||||||
|
|
||||||
|
type fieldInfo struct {
|
||||||
|
Key string
|
||||||
|
Num int
|
||||||
|
OmitEmpty bool
|
||||||
|
Flow bool
|
||||||
|
// Id holds the unique field identifier, so we can cheaply
|
||||||
|
// check for field duplicates without maintaining an extra map.
|
||||||
|
Id int
|
||||||
|
|
||||||
|
// Inline holds the field index if the field is part of an inlined struct.
|
||||||
|
Inline []int
|
||||||
|
}
|
||||||
|
|
||||||
|
var structMap = make(map[reflect.Type]*structInfo)
|
||||||
|
var fieldMapMutex sync.RWMutex
|
||||||
|
var unmarshalerType reflect.Type
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var v Unmarshaler
|
||||||
|
unmarshalerType = reflect.ValueOf(&v).Elem().Type()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||||
|
fieldMapMutex.RLock()
|
||||||
|
sinfo, found := structMap[st]
|
||||||
|
fieldMapMutex.RUnlock()
|
||||||
|
if found {
|
||||||
|
return sinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
n := st.NumField()
|
||||||
|
fieldsMap := make(map[string]fieldInfo)
|
||||||
|
fieldsList := make([]fieldInfo, 0, n)
|
||||||
|
inlineMap := -1
|
||||||
|
inlineUnmarshalers := [][]int(nil)
|
||||||
|
for i := 0; i != n; i++ {
|
||||||
|
field := st.Field(i)
|
||||||
|
if field.PkgPath != "" && !field.Anonymous {
|
||||||
|
continue // Private field
|
||||||
|
}
|
||||||
|
|
||||||
|
info := fieldInfo{Num: i}
|
||||||
|
|
||||||
|
tag := field.Tag.Get("yaml")
|
||||||
|
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
|
||||||
|
tag = string(field.Tag)
|
||||||
|
}
|
||||||
|
if tag == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
inline := false
|
||||||
|
fields := strings.Split(tag, ",")
|
||||||
|
if len(fields) > 1 {
|
||||||
|
for _, flag := range fields[1:] {
|
||||||
|
switch flag {
|
||||||
|
case "omitempty":
|
||||||
|
info.OmitEmpty = true
|
||||||
|
case "flow":
|
||||||
|
info.Flow = true
|
||||||
|
case "inline":
|
||||||
|
inline = true
|
||||||
|
default:
|
||||||
|
return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tag = fields[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if inline {
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
if inlineMap >= 0 {
|
||||||
|
return nil, errors.New("multiple ,inline maps in struct " + st.String())
|
||||||
|
}
|
||||||
|
if field.Type.Key() != reflect.TypeOf("") {
|
||||||
|
return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
|
||||||
|
}
|
||||||
|
inlineMap = info.Num
|
||||||
|
case reflect.Struct, reflect.Ptr:
|
||||||
|
ftype := field.Type
|
||||||
|
for ftype.Kind() == reflect.Ptr {
|
||||||
|
ftype = ftype.Elem()
|
||||||
|
}
|
||||||
|
if ftype.Kind() != reflect.Struct {
|
||||||
|
return nil, errors.New("option ,inline may only be used on a struct or map field")
|
||||||
|
}
|
||||||
|
if reflect.PtrTo(ftype).Implements(unmarshalerType) {
|
||||||
|
inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
|
||||||
|
} else {
|
||||||
|
sinfo, err := getStructInfo(ftype)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, index := range sinfo.InlineUnmarshalers {
|
||||||
|
inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
|
||||||
|
}
|
||||||
|
for _, finfo := range sinfo.FieldsList {
|
||||||
|
if _, found := fieldsMap[finfo.Key]; found {
|
||||||
|
msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
|
||||||
|
return nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
if finfo.Inline == nil {
|
||||||
|
finfo.Inline = []int{i, finfo.Num}
|
||||||
|
} else {
|
||||||
|
finfo.Inline = append([]int{i}, finfo.Inline...)
|
||||||
|
}
|
||||||
|
finfo.Id = len(fieldsList)
|
||||||
|
fieldsMap[finfo.Key] = finfo
|
||||||
|
fieldsList = append(fieldsList, finfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("option ,inline may only be used on a struct or map field")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag != "" {
|
||||||
|
info.Key = tag
|
||||||
|
} else {
|
||||||
|
info.Key = strings.ToLower(field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, found = fieldsMap[info.Key]; found {
|
||||||
|
msg := "duplicated key '" + info.Key + "' in struct " + st.String()
|
||||||
|
return nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Id = len(fieldsList)
|
||||||
|
fieldsList = append(fieldsList, info)
|
||||||
|
fieldsMap[info.Key] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
sinfo = &structInfo{
|
||||||
|
FieldsMap: fieldsMap,
|
||||||
|
FieldsList: fieldsList,
|
||||||
|
InlineMap: inlineMap,
|
||||||
|
InlineUnmarshalers: inlineUnmarshalers,
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldMapMutex.Lock()
|
||||||
|
structMap[st] = sinfo
|
||||||
|
fieldMapMutex.Unlock()
|
||||||
|
return sinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZeroer is used to check whether an object is zero to
|
||||||
|
// determine whether it should be omitted when marshaling
|
||||||
|
// with the omitempty flag. One notable implementation
|
||||||
|
// is time.Time.
|
||||||
|
type IsZeroer interface {
|
||||||
|
IsZero() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func isZero(v reflect.Value) bool {
|
||||||
|
kind := v.Kind()
|
||||||
|
if z, ok := v.Interface().(IsZeroer); ok {
|
||||||
|
if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return z.IsZero()
|
||||||
|
}
|
||||||
|
switch kind {
|
||||||
|
case reflect.String:
|
||||||
|
return len(v.String()) == 0
|
||||||
|
case reflect.Interface, reflect.Ptr:
|
||||||
|
return v.IsNil()
|
||||||
|
case reflect.Slice:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Map:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return v.Int() == 0
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float() == 0
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return v.Uint() == 0
|
||||||
|
case reflect.Bool:
|
||||||
|
return !v.Bool()
|
||||||
|
case reflect.Struct:
|
||||||
|
vt := v.Type()
|
||||||
|
for i := v.NumField() - 1; i >= 0; i-- {
|
||||||
|
if vt.Field(i).PkgPath != "" {
|
||||||
|
continue // Private field
|
||||||
|
}
|
||||||
|
if !isZero(v.Field(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
805
vendor/gopkg.in/yaml.v3/yamlh.go
generated
vendored
Normal file
805
vendor/gopkg.in/yaml.v3/yamlh.go
generated
vendored
Normal file
@ -0,0 +1,805 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
// so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The version directive data.
|
||||||
|
type yaml_version_directive_t struct {
|
||||||
|
major int8 // The major version number.
|
||||||
|
minor int8 // The minor version number.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The tag directive data.
|
||||||
|
type yaml_tag_directive_t struct {
|
||||||
|
handle []byte // The tag handle.
|
||||||
|
prefix []byte // The tag prefix.
|
||||||
|
}
|
||||||
|
|
||||||
|
type yaml_encoding_t int
|
||||||
|
|
||||||
|
// The stream encoding.
|
||||||
|
const (
|
||||||
|
// Let the parser choose the encoding.
|
||||||
|
yaml_ANY_ENCODING yaml_encoding_t = iota
|
||||||
|
|
||||||
|
yaml_UTF8_ENCODING // The default UTF-8 encoding.
|
||||||
|
yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
|
||||||
|
yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_break_t int
|
||||||
|
|
||||||
|
// Line break types.
|
||||||
|
const (
|
||||||
|
// Let the parser choose the break type.
|
||||||
|
yaml_ANY_BREAK yaml_break_t = iota
|
||||||
|
|
||||||
|
yaml_CR_BREAK // Use CR for line breaks (Mac style).
|
||||||
|
yaml_LN_BREAK // Use LN for line breaks (Unix style).
|
||||||
|
yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_error_type_t int
|
||||||
|
|
||||||
|
// Many bad things could happen with the parser and emitter.
|
||||||
|
const (
|
||||||
|
// No error is produced.
|
||||||
|
yaml_NO_ERROR yaml_error_type_t = iota
|
||||||
|
|
||||||
|
yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
|
||||||
|
yaml_READER_ERROR // Cannot read or decode the input stream.
|
||||||
|
yaml_SCANNER_ERROR // Cannot scan the input stream.
|
||||||
|
yaml_PARSER_ERROR // Cannot parse the input stream.
|
||||||
|
yaml_COMPOSER_ERROR // Cannot compose a YAML document.
|
||||||
|
yaml_WRITER_ERROR // Cannot write to the output stream.
|
||||||
|
yaml_EMITTER_ERROR // Cannot emit a YAML stream.
|
||||||
|
)
|
||||||
|
|
||||||
|
// The pointer position.
|
||||||
|
type yaml_mark_t struct {
|
||||||
|
index int // The position index.
|
||||||
|
line int // The position line.
|
||||||
|
column int // The position column.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node Styles
|
||||||
|
|
||||||
|
type yaml_style_t int8
|
||||||
|
|
||||||
|
type yaml_scalar_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Scalar styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
|
||||||
|
|
||||||
|
yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style.
|
||||||
|
yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
|
||||||
|
yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
|
||||||
|
yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
|
||||||
|
yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_sequence_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Sequence styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
|
||||||
|
|
||||||
|
yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
|
||||||
|
yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_mapping_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Mapping styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
|
||||||
|
|
||||||
|
yaml_BLOCK_MAPPING_STYLE // The block mapping style.
|
||||||
|
yaml_FLOW_MAPPING_STYLE // The flow mapping style.
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tokens
|
||||||
|
|
||||||
|
type yaml_token_type_t int
|
||||||
|
|
||||||
|
// Token types.
|
||||||
|
const (
|
||||||
|
// An empty token.
|
||||||
|
yaml_NO_TOKEN yaml_token_type_t = iota
|
||||||
|
|
||||||
|
yaml_STREAM_START_TOKEN // A STREAM-START token.
|
||||||
|
yaml_STREAM_END_TOKEN // A STREAM-END token.
|
||||||
|
|
||||||
|
yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
|
||||||
|
yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
|
||||||
|
yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
|
||||||
|
yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
|
||||||
|
|
||||||
|
yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
|
||||||
|
yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
|
||||||
|
yaml_BLOCK_END_TOKEN // A BLOCK-END token.
|
||||||
|
|
||||||
|
yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
|
||||||
|
yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
|
||||||
|
yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
|
||||||
|
yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
|
||||||
|
|
||||||
|
yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
|
||||||
|
yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
|
||||||
|
yaml_KEY_TOKEN // A KEY token.
|
||||||
|
yaml_VALUE_TOKEN // A VALUE token.
|
||||||
|
|
||||||
|
yaml_ALIAS_TOKEN // An ALIAS token.
|
||||||
|
yaml_ANCHOR_TOKEN // An ANCHOR token.
|
||||||
|
yaml_TAG_TOKEN // A TAG token.
|
||||||
|
yaml_SCALAR_TOKEN // A SCALAR token.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (tt yaml_token_type_t) String() string {
|
||||||
|
switch tt {
|
||||||
|
case yaml_NO_TOKEN:
|
||||||
|
return "yaml_NO_TOKEN"
|
||||||
|
case yaml_STREAM_START_TOKEN:
|
||||||
|
return "yaml_STREAM_START_TOKEN"
|
||||||
|
case yaml_STREAM_END_TOKEN:
|
||||||
|
return "yaml_STREAM_END_TOKEN"
|
||||||
|
case yaml_VERSION_DIRECTIVE_TOKEN:
|
||||||
|
return "yaml_VERSION_DIRECTIVE_TOKEN"
|
||||||
|
case yaml_TAG_DIRECTIVE_TOKEN:
|
||||||
|
return "yaml_TAG_DIRECTIVE_TOKEN"
|
||||||
|
case yaml_DOCUMENT_START_TOKEN:
|
||||||
|
return "yaml_DOCUMENT_START_TOKEN"
|
||||||
|
case yaml_DOCUMENT_END_TOKEN:
|
||||||
|
return "yaml_DOCUMENT_END_TOKEN"
|
||||||
|
case yaml_BLOCK_SEQUENCE_START_TOKEN:
|
||||||
|
return "yaml_BLOCK_SEQUENCE_START_TOKEN"
|
||||||
|
case yaml_BLOCK_MAPPING_START_TOKEN:
|
||||||
|
return "yaml_BLOCK_MAPPING_START_TOKEN"
|
||||||
|
case yaml_BLOCK_END_TOKEN:
|
||||||
|
return "yaml_BLOCK_END_TOKEN"
|
||||||
|
case yaml_FLOW_SEQUENCE_START_TOKEN:
|
||||||
|
return "yaml_FLOW_SEQUENCE_START_TOKEN"
|
||||||
|
case yaml_FLOW_SEQUENCE_END_TOKEN:
|
||||||
|
return "yaml_FLOW_SEQUENCE_END_TOKEN"
|
||||||
|
case yaml_FLOW_MAPPING_START_TOKEN:
|
||||||
|
return "yaml_FLOW_MAPPING_START_TOKEN"
|
||||||
|
case yaml_FLOW_MAPPING_END_TOKEN:
|
||||||
|
return "yaml_FLOW_MAPPING_END_TOKEN"
|
||||||
|
case yaml_BLOCK_ENTRY_TOKEN:
|
||||||
|
return "yaml_BLOCK_ENTRY_TOKEN"
|
||||||
|
case yaml_FLOW_ENTRY_TOKEN:
|
||||||
|
return "yaml_FLOW_ENTRY_TOKEN"
|
||||||
|
case yaml_KEY_TOKEN:
|
||||||
|
return "yaml_KEY_TOKEN"
|
||||||
|
case yaml_VALUE_TOKEN:
|
||||||
|
return "yaml_VALUE_TOKEN"
|
||||||
|
case yaml_ALIAS_TOKEN:
|
||||||
|
return "yaml_ALIAS_TOKEN"
|
||||||
|
case yaml_ANCHOR_TOKEN:
|
||||||
|
return "yaml_ANCHOR_TOKEN"
|
||||||
|
case yaml_TAG_TOKEN:
|
||||||
|
return "yaml_TAG_TOKEN"
|
||||||
|
case yaml_SCALAR_TOKEN:
|
||||||
|
return "yaml_SCALAR_TOKEN"
|
||||||
|
}
|
||||||
|
return "<unknown token>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The token structure.
|
||||||
|
type yaml_token_t struct {
|
||||||
|
// The token type.
|
||||||
|
typ yaml_token_type_t
|
||||||
|
|
||||||
|
// The start/end of the token.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The stream encoding (for yaml_STREAM_START_TOKEN).
|
||||||
|
encoding yaml_encoding_t
|
||||||
|
|
||||||
|
// The alias/anchor/scalar value or tag/tag directive handle
|
||||||
|
// (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
|
||||||
|
value []byte
|
||||||
|
|
||||||
|
// The tag suffix (for yaml_TAG_TOKEN).
|
||||||
|
suffix []byte
|
||||||
|
|
||||||
|
// The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
|
||||||
|
prefix []byte
|
||||||
|
|
||||||
|
// The scalar style (for yaml_SCALAR_TOKEN).
|
||||||
|
style yaml_scalar_style_t
|
||||||
|
|
||||||
|
// The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
|
||||||
|
major, minor int8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Events
|
||||||
|
|
||||||
|
type yaml_event_type_t int8
|
||||||
|
|
||||||
|
// Event types.
|
||||||
|
const (
|
||||||
|
// An empty event.
|
||||||
|
yaml_NO_EVENT yaml_event_type_t = iota
|
||||||
|
|
||||||
|
yaml_STREAM_START_EVENT // A STREAM-START event.
|
||||||
|
yaml_STREAM_END_EVENT // A STREAM-END event.
|
||||||
|
yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
|
||||||
|
yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
|
||||||
|
yaml_ALIAS_EVENT // An ALIAS event.
|
||||||
|
yaml_SCALAR_EVENT // A SCALAR event.
|
||||||
|
yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
|
||||||
|
yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
|
||||||
|
yaml_MAPPING_START_EVENT // A MAPPING-START event.
|
||||||
|
yaml_MAPPING_END_EVENT // A MAPPING-END event.
|
||||||
|
yaml_TAIL_COMMENT_EVENT
|
||||||
|
)
|
||||||
|
|
||||||
|
var eventStrings = []string{
|
||||||
|
yaml_NO_EVENT: "none",
|
||||||
|
yaml_STREAM_START_EVENT: "stream start",
|
||||||
|
yaml_STREAM_END_EVENT: "stream end",
|
||||||
|
yaml_DOCUMENT_START_EVENT: "document start",
|
||||||
|
yaml_DOCUMENT_END_EVENT: "document end",
|
||||||
|
yaml_ALIAS_EVENT: "alias",
|
||||||
|
yaml_SCALAR_EVENT: "scalar",
|
||||||
|
yaml_SEQUENCE_START_EVENT: "sequence start",
|
||||||
|
yaml_SEQUENCE_END_EVENT: "sequence end",
|
||||||
|
yaml_MAPPING_START_EVENT: "mapping start",
|
||||||
|
yaml_MAPPING_END_EVENT: "mapping end",
|
||||||
|
yaml_TAIL_COMMENT_EVENT: "tail comment",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e yaml_event_type_t) String() string {
|
||||||
|
if e < 0 || int(e) >= len(eventStrings) {
|
||||||
|
return fmt.Sprintf("unknown event %d", e)
|
||||||
|
}
|
||||||
|
return eventStrings[e]
|
||||||
|
}
|
||||||
|
|
||||||
|
// The event structure.
|
||||||
|
type yaml_event_t struct {
|
||||||
|
|
||||||
|
// The event type.
|
||||||
|
typ yaml_event_type_t
|
||||||
|
|
||||||
|
// The start and end of the event.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The document encoding (for yaml_STREAM_START_EVENT).
|
||||||
|
encoding yaml_encoding_t
|
||||||
|
|
||||||
|
// The version directive (for yaml_DOCUMENT_START_EVENT).
|
||||||
|
version_directive *yaml_version_directive_t
|
||||||
|
|
||||||
|
// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
|
||||||
|
tag_directives []yaml_tag_directive_t
|
||||||
|
|
||||||
|
// The comments
|
||||||
|
head_comment []byte
|
||||||
|
line_comment []byte
|
||||||
|
foot_comment []byte
|
||||||
|
tail_comment []byte
|
||||||
|
|
||||||
|
// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
|
||||||
|
anchor []byte
|
||||||
|
|
||||||
|
// The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||||
|
tag []byte
|
||||||
|
|
||||||
|
// The scalar value (for yaml_SCALAR_EVENT).
|
||||||
|
value []byte
|
||||||
|
|
||||||
|
// Is the document start/end indicator implicit, or the tag optional?
|
||||||
|
// (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
|
||||||
|
implicit bool
|
||||||
|
|
||||||
|
// Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
|
||||||
|
quoted_implicit bool
|
||||||
|
|
||||||
|
// The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||||
|
style yaml_style_t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
|
||||||
|
func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
|
||||||
|
func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
|
||||||
|
|
||||||
|
// Nodes
|
||||||
|
|
||||||
|
const (
|
||||||
|
yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
|
||||||
|
yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
|
||||||
|
yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
|
||||||
|
yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
|
||||||
|
yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
|
||||||
|
yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
|
||||||
|
|
||||||
|
yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
|
||||||
|
yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
|
||||||
|
|
||||||
|
// Not in original libyaml.
|
||||||
|
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
|
||||||
|
yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
|
||||||
|
|
||||||
|
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
|
||||||
|
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
|
||||||
|
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_node_type_t int
|
||||||
|
|
||||||
|
// Node types.
|
||||||
|
const (
|
||||||
|
// An empty node.
|
||||||
|
yaml_NO_NODE yaml_node_type_t = iota
|
||||||
|
|
||||||
|
yaml_SCALAR_NODE // A scalar node.
|
||||||
|
yaml_SEQUENCE_NODE // A sequence node.
|
||||||
|
yaml_MAPPING_NODE // A mapping node.
|
||||||
|
)
|
||||||
|
|
||||||
|
// An element of a sequence node.
|
||||||
|
type yaml_node_item_t int
|
||||||
|
|
||||||
|
// An element of a mapping node.
|
||||||
|
type yaml_node_pair_t struct {
|
||||||
|
key int // The key of the element.
|
||||||
|
value int // The value of the element.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The node structure.
|
||||||
|
type yaml_node_t struct {
|
||||||
|
typ yaml_node_type_t // The node type.
|
||||||
|
tag []byte // The node tag.
|
||||||
|
|
||||||
|
// The node data.
|
||||||
|
|
||||||
|
// The scalar parameters (for yaml_SCALAR_NODE).
|
||||||
|
scalar struct {
|
||||||
|
value []byte // The scalar value.
|
||||||
|
length int // The length of the scalar value.
|
||||||
|
style yaml_scalar_style_t // The scalar style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sequence parameters (for YAML_SEQUENCE_NODE).
|
||||||
|
sequence struct {
|
||||||
|
items_data []yaml_node_item_t // The stack of sequence items.
|
||||||
|
style yaml_sequence_style_t // The sequence style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The mapping parameters (for yaml_MAPPING_NODE).
|
||||||
|
mapping struct {
|
||||||
|
pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
|
||||||
|
pairs_start *yaml_node_pair_t // The beginning of the stack.
|
||||||
|
pairs_end *yaml_node_pair_t // The end of the stack.
|
||||||
|
pairs_top *yaml_node_pair_t // The top of the stack.
|
||||||
|
style yaml_mapping_style_t // The mapping style.
|
||||||
|
}
|
||||||
|
|
||||||
|
start_mark yaml_mark_t // The beginning of the node.
|
||||||
|
end_mark yaml_mark_t // The end of the node.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// The document structure.
|
||||||
|
type yaml_document_t struct {
|
||||||
|
|
||||||
|
// The document nodes.
|
||||||
|
nodes []yaml_node_t
|
||||||
|
|
||||||
|
// The version directive.
|
||||||
|
version_directive *yaml_version_directive_t
|
||||||
|
|
||||||
|
// The list of tag directives.
|
||||||
|
tag_directives_data []yaml_tag_directive_t
|
||||||
|
tag_directives_start int // The beginning of the tag directives list.
|
||||||
|
tag_directives_end int // The end of the tag directives list.
|
||||||
|
|
||||||
|
start_implicit int // Is the document start indicator implicit?
|
||||||
|
end_implicit int // Is the document end indicator implicit?
|
||||||
|
|
||||||
|
// The start/end of the document.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
}
|
||||||
|
|
||||||
|
// The prototype of a read handler.
|
||||||
|
//
|
||||||
|
// The read handler is called when the parser needs to read more bytes from the
|
||||||
|
// source. The handler should write not more than size bytes to the buffer.
|
||||||
|
// The number of written bytes should be set to the size_read variable.
|
||||||
|
//
|
||||||
|
// [in,out] data A pointer to an application data specified by
|
||||||
|
// yaml_parser_set_input().
|
||||||
|
// [out] buffer The buffer to write the data from the source.
|
||||||
|
// [in] size The size of the buffer.
|
||||||
|
// [out] size_read The actual number of bytes read from the source.
|
||||||
|
//
|
||||||
|
// On success, the handler should return 1. If the handler failed,
|
||||||
|
// the returned value should be 0. On EOF, the handler should set the
|
||||||
|
// size_read to 0 and return 1.
|
||||||
|
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
|
||||||
|
|
||||||
|
// This structure holds information about a potential simple key.
|
||||||
|
type yaml_simple_key_t struct {
|
||||||
|
possible bool // Is a simple key possible?
|
||||||
|
required bool // Is a simple key required?
|
||||||
|
token_number int // The number of the token.
|
||||||
|
mark yaml_mark_t // The position mark.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The states of the parser.
|
||||||
|
type yaml_parser_state_t int
|
||||||
|
|
||||||
|
const (
|
||||||
|
yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
|
||||||
|
|
||||||
|
yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
|
||||||
|
yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
|
||||||
|
yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||||
|
yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||||
|
yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
|
||||||
|
yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
|
||||||
|
yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
|
||||||
|
yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
|
||||||
|
yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
|
||||||
|
yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
|
||||||
|
yaml_PARSE_END_STATE // Expect nothing.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps yaml_parser_state_t) String() string {
|
||||||
|
switch ps {
|
||||||
|
case yaml_PARSE_STREAM_START_STATE:
|
||||||
|
return "yaml_PARSE_STREAM_START_STATE"
|
||||||
|
case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
|
||||||
|
return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_START_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_START_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_CONTENT_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_END_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_END_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_NODE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_NODE_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_NODE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_NODE_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
|
||||||
|
case yaml_PARSE_END_STATE:
|
||||||
|
return "yaml_PARSE_END_STATE"
|
||||||
|
}
|
||||||
|
return "<unknown parser state>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// This structure holds aliases data.
|
||||||
|
type yaml_alias_data_t struct {
|
||||||
|
anchor []byte // The anchor.
|
||||||
|
index int // The node id.
|
||||||
|
mark yaml_mark_t // The anchor mark.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The parser structure.
|
||||||
|
//
|
||||||
|
// All members are internal. Manage the structure using the
|
||||||
|
// yaml_parser_ family of functions.
|
||||||
|
type yaml_parser_t struct {
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
|
||||||
|
error yaml_error_type_t // Error type.
|
||||||
|
|
||||||
|
problem string // Error description.
|
||||||
|
|
||||||
|
// The byte about which the problem occurred.
|
||||||
|
problem_offset int
|
||||||
|
problem_value int
|
||||||
|
problem_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The error context.
|
||||||
|
context string
|
||||||
|
context_mark yaml_mark_t
|
||||||
|
|
||||||
|
// Reader stuff
|
||||||
|
|
||||||
|
read_handler yaml_read_handler_t // Read handler.
|
||||||
|
|
||||||
|
input_reader io.Reader // File input data.
|
||||||
|
input []byte // String input data.
|
||||||
|
input_pos int
|
||||||
|
|
||||||
|
eof bool // EOF flag
|
||||||
|
|
||||||
|
buffer []byte // The working buffer.
|
||||||
|
buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
unread int // The number of unread characters in the buffer.
|
||||||
|
|
||||||
|
newlines int // The number of line breaks since last non-break/non-blank character
|
||||||
|
|
||||||
|
raw_buffer []byte // The raw buffer.
|
||||||
|
raw_buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
encoding yaml_encoding_t // The input encoding.
|
||||||
|
|
||||||
|
offset int // The offset of the current position (in bytes).
|
||||||
|
mark yaml_mark_t // The mark of the current position.
|
||||||
|
|
||||||
|
// Comments
|
||||||
|
|
||||||
|
head_comment []byte // The current head comments
|
||||||
|
line_comment []byte // The current line comments
|
||||||
|
foot_comment []byte // The current foot comments
|
||||||
|
tail_comment []byte // Foot comment that happens at the end of a block.
|
||||||
|
stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
|
||||||
|
|
||||||
|
comments []yaml_comment_t // The folded comments for all parsed tokens
|
||||||
|
comments_head int
|
||||||
|
|
||||||
|
// Scanner stuff
|
||||||
|
|
||||||
|
stream_start_produced bool // Have we started to scan the input stream?
|
||||||
|
stream_end_produced bool // Have we reached the end of the input stream?
|
||||||
|
|
||||||
|
flow_level int // The number of unclosed '[' and '{' indicators.
|
||||||
|
|
||||||
|
tokens []yaml_token_t // The tokens queue.
|
||||||
|
tokens_head int // The head of the tokens queue.
|
||||||
|
tokens_parsed int // The number of tokens fetched from the queue.
|
||||||
|
token_available bool // Does the tokens queue contain a token ready for dequeueing.
|
||||||
|
|
||||||
|
indent int // The current indentation level.
|
||||||
|
indents []int // The indentation levels stack.
|
||||||
|
|
||||||
|
simple_key_allowed bool // May a simple key occur at the current position?
|
||||||
|
simple_keys []yaml_simple_key_t // The stack of simple keys.
|
||||||
|
simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
|
||||||
|
|
||||||
|
// Parser stuff
|
||||||
|
|
||||||
|
state yaml_parser_state_t // The current parser state.
|
||||||
|
states []yaml_parser_state_t // The parser states stack.
|
||||||
|
marks []yaml_mark_t // The stack of marks.
|
||||||
|
tag_directives []yaml_tag_directive_t // The list of TAG directives.
|
||||||
|
|
||||||
|
// Dumper stuff
|
||||||
|
|
||||||
|
aliases []yaml_alias_data_t // The alias data.
|
||||||
|
|
||||||
|
document *yaml_document_t // The currently parsed document.
|
||||||
|
}
|
||||||
|
|
||||||
|
type yaml_comment_t struct {
|
||||||
|
|
||||||
|
scan_mark yaml_mark_t // Position where scanning for comments started
|
||||||
|
token_mark yaml_mark_t // Position after which tokens will be associated with this comment
|
||||||
|
start_mark yaml_mark_t // Position of '#' comment mark
|
||||||
|
end_mark yaml_mark_t // Position where comment terminated
|
||||||
|
|
||||||
|
head []byte
|
||||||
|
line []byte
|
||||||
|
foot []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emitter Definitions
|
||||||
|
|
||||||
|
// The prototype of a write handler.
|
||||||
|
//
|
||||||
|
// The write handler is called when the emitter needs to flush the accumulated
|
||||||
|
// characters to the output. The handler should write @a size bytes of the
|
||||||
|
// @a buffer to the output.
|
||||||
|
//
|
||||||
|
// @param[in,out] data A pointer to an application data specified by
|
||||||
|
// yaml_emitter_set_output().
|
||||||
|
// @param[in] buffer The buffer with bytes to be written.
|
||||||
|
// @param[in] size The size of the buffer.
|
||||||
|
//
|
||||||
|
// @returns On success, the handler should return @c 1. If the handler failed,
|
||||||
|
// the returned value should be @c 0.
|
||||||
|
//
|
||||||
|
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
||||||
|
|
||||||
|
type yaml_emitter_state_t int
|
||||||
|
|
||||||
|
// The emitter states.
|
||||||
|
const (
|
||||||
|
// Expect STREAM-START.
|
||||||
|
yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
|
||||||
|
|
||||||
|
yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
|
||||||
|
yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
|
||||||
|
yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||||
|
yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out
|
||||||
|
yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||||
|
yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
|
||||||
|
yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
|
||||||
|
yaml_EMIT_END_STATE // Expect nothing.
|
||||||
|
)
|
||||||
|
|
||||||
|
// The emitter structure.
|
||||||
|
//
|
||||||
|
// All members are internal. Manage the structure using the @c yaml_emitter_
|
||||||
|
// family of functions.
|
||||||
|
type yaml_emitter_t struct {
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
|
||||||
|
error yaml_error_type_t // Error type.
|
||||||
|
problem string // Error description.
|
||||||
|
|
||||||
|
// Writer stuff
|
||||||
|
|
||||||
|
write_handler yaml_write_handler_t // Write handler.
|
||||||
|
|
||||||
|
output_buffer *[]byte // String output data.
|
||||||
|
output_writer io.Writer // File output data.
|
||||||
|
|
||||||
|
buffer []byte // The working buffer.
|
||||||
|
buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
raw_buffer []byte // The raw buffer.
|
||||||
|
raw_buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
encoding yaml_encoding_t // The stream encoding.
|
||||||
|
|
||||||
|
// Emitter stuff
|
||||||
|
|
||||||
|
canonical bool // If the output is in the canonical style?
|
||||||
|
best_indent int // The number of indentation spaces.
|
||||||
|
best_width int // The preferred width of the output lines.
|
||||||
|
unicode bool // Allow unescaped non-ASCII characters?
|
||||||
|
line_break yaml_break_t // The preferred line break.
|
||||||
|
|
||||||
|
state yaml_emitter_state_t // The current emitter state.
|
||||||
|
states []yaml_emitter_state_t // The stack of states.
|
||||||
|
|
||||||
|
events []yaml_event_t // The event queue.
|
||||||
|
events_head int // The head of the event queue.
|
||||||
|
|
||||||
|
indents []int // The stack of indentation levels.
|
||||||
|
|
||||||
|
tag_directives []yaml_tag_directive_t // The list of tag directives.
|
||||||
|
|
||||||
|
indent int // The current indentation level.
|
||||||
|
|
||||||
|
flow_level int // The current flow level.
|
||||||
|
|
||||||
|
root_context bool // Is it the document root context?
|
||||||
|
sequence_context bool // Is it a sequence context?
|
||||||
|
mapping_context bool // Is it a mapping context?
|
||||||
|
simple_key_context bool // Is it a simple mapping key context?
|
||||||
|
|
||||||
|
line int // The current line.
|
||||||
|
column int // The current column.
|
||||||
|
whitespace bool // If the last character was a whitespace?
|
||||||
|
indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
|
||||||
|
open_ended bool // If an explicit document end is required?
|
||||||
|
|
||||||
|
space_above bool // Is there's an empty line above?
|
||||||
|
foot_indent int // The indent used to write the foot comment above, or -1 if none.
|
||||||
|
|
||||||
|
// Anchor analysis.
|
||||||
|
anchor_data struct {
|
||||||
|
anchor []byte // The anchor value.
|
||||||
|
alias bool // Is it an alias?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag analysis.
|
||||||
|
tag_data struct {
|
||||||
|
handle []byte // The tag handle.
|
||||||
|
suffix []byte // The tag suffix.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scalar analysis.
|
||||||
|
scalar_data struct {
|
||||||
|
value []byte // The scalar value.
|
||||||
|
multiline bool // Does the scalar contain line breaks?
|
||||||
|
flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
|
||||||
|
block_plain_allowed bool // Can the scalar be expressed in the block plain style?
|
||||||
|
single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
|
||||||
|
block_allowed bool // Can the scalar be expressed in the literal or folded styles?
|
||||||
|
style yaml_scalar_style_t // The output style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comments
|
||||||
|
head_comment []byte
|
||||||
|
line_comment []byte
|
||||||
|
foot_comment []byte
|
||||||
|
tail_comment []byte
|
||||||
|
|
||||||
|
// Dumper stuff
|
||||||
|
|
||||||
|
opened bool // If the stream was already opened?
|
||||||
|
closed bool // If the stream was already closed?
|
||||||
|
|
||||||
|
// The information associated with the document nodes.
|
||||||
|
anchors *struct {
|
||||||
|
references int // The number of references.
|
||||||
|
anchor int // The anchor id.
|
||||||
|
serialized bool // If the node has been emitted?
|
||||||
|
}
|
||||||
|
|
||||||
|
last_anchor_id int // The last assigned anchor id.
|
||||||
|
|
||||||
|
document *yaml_document_t // The currently emitted document.
|
||||||
|
}
|
198
vendor/gopkg.in/yaml.v3/yamlprivateh.go
generated
vendored
Normal file
198
vendor/gopkg.in/yaml.v3/yamlprivateh.go
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2011-2019 Canonical Ltd
|
||||||
|
// Copyright (c) 2006-2010 Kirill Simonov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
// of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
// so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
const (
|
||||||
|
// The size of the input raw buffer.
|
||||||
|
input_raw_buffer_size = 512
|
||||||
|
|
||||||
|
// The size of the input buffer.
|
||||||
|
// It should be possible to decode the whole raw buffer.
|
||||||
|
input_buffer_size = input_raw_buffer_size * 3
|
||||||
|
|
||||||
|
// The size of the output buffer.
|
||||||
|
output_buffer_size = 128
|
||||||
|
|
||||||
|
// The size of the output raw buffer.
|
||||||
|
// It should be possible to encode the whole output buffer.
|
||||||
|
output_raw_buffer_size = (output_buffer_size*2 + 2)
|
||||||
|
|
||||||
|
// The size of other stacks and queues.
|
||||||
|
initial_stack_size = 16
|
||||||
|
initial_queue_size = 16
|
||||||
|
initial_string_size = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the character at the specified position is an alphabetical
|
||||||
|
// character, a digit, '_', or '-'.
|
||||||
|
func is_alpha(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a digit.
|
||||||
|
func is_digit(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value of a digit.
|
||||||
|
func as_digit(b []byte, i int) int {
|
||||||
|
return int(b[i]) - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a hex-digit.
|
||||||
|
func is_hex(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value of a hex-digit.
|
||||||
|
func as_hex(b []byte, i int) int {
|
||||||
|
bi := b[i]
|
||||||
|
if bi >= 'A' && bi <= 'F' {
|
||||||
|
return int(bi) - 'A' + 10
|
||||||
|
}
|
||||||
|
if bi >= 'a' && bi <= 'f' {
|
||||||
|
return int(bi) - 'a' + 10
|
||||||
|
}
|
||||||
|
return int(bi) - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is ASCII.
|
||||||
|
func is_ascii(b []byte, i int) bool {
|
||||||
|
return b[i] <= 0x7F
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the start of the buffer can be printed unescaped.
|
||||||
|
func is_printable(b []byte, i int) bool {
|
||||||
|
return ((b[i] == 0x0A) || // . == #x0A
|
||||||
|
(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
|
||||||
|
(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
|
||||||
|
(b[i] > 0xC2 && b[i] < 0xED) ||
|
||||||
|
(b[i] == 0xED && b[i+1] < 0xA0) ||
|
||||||
|
(b[i] == 0xEE) ||
|
||||||
|
(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
|
||||||
|
!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
|
||||||
|
!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is NUL.
|
||||||
|
func is_z(b []byte, i int) bool {
|
||||||
|
return b[i] == 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the beginning of the buffer is a BOM.
|
||||||
|
func is_bom(b []byte, i int) bool {
|
||||||
|
return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is space.
|
||||||
|
func is_space(b []byte, i int) bool {
|
||||||
|
return b[i] == ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is tab.
|
||||||
|
func is_tab(b []byte, i int) bool {
|
||||||
|
return b[i] == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is blank (space or tab).
|
||||||
|
func is_blank(b []byte, i int) bool {
|
||||||
|
//return is_space(b, i) || is_tab(b, i)
|
||||||
|
return b[i] == ' ' || b[i] == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a line break.
|
||||||
|
func is_break(b []byte, i int) bool {
|
||||||
|
return (b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
|
||||||
|
}
|
||||||
|
|
||||||
|
func is_crlf(b []byte, i int) bool {
|
||||||
|
return b[i] == '\r' && b[i+1] == '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break or NUL.
|
||||||
|
func is_breakz(b []byte, i int) bool {
|
||||||
|
//return is_break(b, i) || is_z(b, i)
|
||||||
|
return (
|
||||||
|
// is_break:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
// is_z:
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break, space, or NUL.
|
||||||
|
func is_spacez(b []byte, i int) bool {
|
||||||
|
//return is_space(b, i) || is_breakz(b, i)
|
||||||
|
return (
|
||||||
|
// is_space:
|
||||||
|
b[i] == ' ' ||
|
||||||
|
// is_breakz:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break, space, tab, or NUL.
|
||||||
|
func is_blankz(b []byte, i int) bool {
|
||||||
|
//return is_blank(b, i) || is_breakz(b, i)
|
||||||
|
return (
|
||||||
|
// is_blank:
|
||||||
|
b[i] == ' ' || b[i] == '\t' ||
|
||||||
|
// is_breakz:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the width of the character.
|
||||||
|
func width(b byte) int {
|
||||||
|
// Don't replace these by a switch without first
|
||||||
|
// confirming that it is being inlined.
|
||||||
|
if b&0x80 == 0x00 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if b&0xE0 == 0xC0 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
if b&0xF0 == 0xE0 {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
if b&0xF8 == 0xF0 {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@ -144,7 +144,7 @@ github.com/mgutz/ansi
|
|||||||
github.com/missdeer/golib/ic
|
github.com/missdeer/golib/ic
|
||||||
# github.com/mitchellh/mapstructure v1.2.3
|
# github.com/mitchellh/mapstructure v1.2.3
|
||||||
github.com/mitchellh/mapstructure
|
github.com/mitchellh/mapstructure
|
||||||
# github.com/monaco-io/request v1.0.3
|
# github.com/monaco-io/request v1.0.4
|
||||||
github.com/monaco-io/request
|
github.com/monaco-io/request
|
||||||
# github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474
|
# github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474
|
||||||
github.com/mreiferson/go-httpclient
|
github.com/mreiferson/go-httpclient
|
||||||
@ -201,7 +201,7 @@ github.com/spf13/jwalterweatherman
|
|||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
# github.com/spf13/viper v1.7.0
|
# github.com/spf13/viper v1.7.0
|
||||||
github.com/spf13/viper
|
github.com/spf13/viper
|
||||||
# github.com/stretchr/testify v1.5.1
|
# github.com/stretchr/testify v1.6.1
|
||||||
github.com/stretchr/testify/assert
|
github.com/stretchr/testify/assert
|
||||||
github.com/stretchr/testify/require
|
github.com/stretchr/testify/require
|
||||||
github.com/stretchr/testify/suite
|
github.com/stretchr/testify/suite
|
||||||
@ -291,7 +291,7 @@ golang.org/x/text/secure/bidirule
|
|||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/bidi
|
golang.org/x/text/unicode/bidi
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
# gomod.garykim.dev/nc-talk v0.0.2
|
# gomod.garykim.dev/nc-talk v0.1.1
|
||||||
gomod.garykim.dev/nc-talk
|
gomod.garykim.dev/nc-talk
|
||||||
gomod.garykim.dev/nc-talk/constants
|
gomod.garykim.dev/nc-talk/constants
|
||||||
gomod.garykim.dev/nc-talk/ocs
|
gomod.garykim.dev/nc-talk/ocs
|
||||||
@ -342,3 +342,5 @@ gopkg.in/natefinch/lumberjack.v2
|
|||||||
gopkg.in/olahol/melody.v1
|
gopkg.in/olahol/melody.v1
|
||||||
# gopkg.in/yaml.v2 v2.2.8
|
# gopkg.in/yaml.v2 v2.2.8
|
||||||
gopkg.in/yaml.v2
|
gopkg.in/yaml.v2
|
||||||
|
# gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||||
|
gopkg.in/yaml.v3
|
||||||
|
Loading…
Reference in New Issue
Block a user