diff --git a/.hooks/post-create b/.hooks/post-create
new file mode 100755
index 0000000..f25d9d5
--- /dev/null
+++ b/.hooks/post-create
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+id="$TUS_ID"
+offset="$TUS_OFFSET"
+size="$TUS_SIZE"
+
+echo "Upload created with ID ${id} and size ${size}"
+cat /dev/stdin | jq .
diff --git a/.infra/files/apache2.conf b/.infra/files/apache2.conf
new file mode 100644
index 0000000..9718504
--- /dev/null
+++ b/.infra/files/apache2.conf
@@ -0,0 +1,35 @@
+# Please make sure that you have the modules mod_ssl, mod_headers,
+# mod_proxy and mod_proxy_http enabled. If not, you can use following
+# command:
+# $ sudo a2enmod ssl headers proxy proxy_http
+
+
+ ServerName localhost
+
+ # Enable secure communication using HTTPS
+ # Adjust the paths to the certificates files to your environment
+ SSLEngine on
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+
+ # Tell tusd that the HTTPS protocol is used, in order to
+ # allow constructing correct upload URLs.
+ RequestHeader set X-Forwarded-Proto "https"
+
+ # Pass requests to tusd server
+ ProxyPass /files http://localhost:1080/files
+ ProxyPassReverse /files http://localhost:1080/files
+
+
+# This SSL configuration has been taken from Mozilla SSL Generator:
+# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.10.1&openssl=1.0.1e&hsts=no&profile=intermediate
+SSLProtocol all -SSLv3
+SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-$
+SSLHonorCipherOrder on
+SSLCompression off
+
+# OCSP Stapling, only in httpd 2.3.3 and later
+SSLUseStapling on
+SSLStaplingResponderTimeout 5
+SSLStaplingReturnResponderErrors off
+SSLStaplingCache shmcb:/var/run/ocsp(128000)
diff --git a/.infra/kube/00-namespace.yaml b/.infra/kube/00-namespace.yaml
new file mode 100644
index 0000000..da874a3
--- /dev/null
+++ b/.infra/kube/00-namespace.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: tus
+
diff --git a/.infra/kube/deployment.yaml b/.infra/kube/deployment.yaml
new file mode 100644
index 0000000..e170349
--- /dev/null
+++ b/.infra/kube/deployment.yaml
@@ -0,0 +1,19 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: tusd
+ namespace: tus
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: tusd
+ spec:
+ containers:
+ - image: docker.io/tusproject/tusd:latest
+ imagePullPolicy: Always
+ args: ["-port=8080","-behind-proxy","-max-size=1000000000"]
+ name: tusd
+ ports:
+ - containerPort: 8080
diff --git a/.infra/kube/ingress-tls.yaml b/.infra/kube/ingress-tls.yaml
new file mode 100644
index 0000000..c2dddc2
--- /dev/null
+++ b/.infra/kube/ingress-tls.yaml
@@ -0,0 +1,22 @@
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: tusd
+ namespace: tus
+ annotations:
+ kubernetes.io/tls-acme: "true"
+ kubernetes.io/ingress.class: "nginx"
+spec:
+ tls:
+ - hosts:
+ - thesocialcactus.com
+ secretName: tusd-tls
+ rules:
+ - host: thesocialcactus.com
+ http:
+ paths:
+ - path: /
+ backend:
+ serviceName: tusd
+ servicePort: 80
+
diff --git a/.infra/kube/service.yaml b/.infra/kube/service.yaml
new file mode 100644
index 0000000..b6c6c83
--- /dev/null
+++ b/.infra/kube/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: tusd
+ namespace: tus
+spec:
+ ports:
+ - port: 80
+ targetPort: 8080
+ protocol: TCP
+ selector:
+ app: tusd
+
diff --git a/.scripts/deploy_gcloud.sh b/.scripts/deploy_gcloud.sh
new file mode 100755
index 0000000..7759ab3
--- /dev/null
+++ b/.scripts/deploy_gcloud.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+set -o pipefail
+set -o errexit
+set -o nounset
+# set -o xtrace
+
+# Set magic variables for current FILE & DIR
+__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+__root="$(cd "$(dirname "${__dir}")" && pwd)"
+
+# Store the new image in docker hub
+docker build --quiet -t tusproject/tusd:latest -t tusproject/tusd:$TRAVIS_COMMIT ${__root};
+docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD";
+docker push tusproject/tusd:$TRAVIS_COMMIT;
+docker push tusproject/tusd:latest;
+
+echo $GCLOUD_KEY | base64 --decode -i > ${HOME}/gcloud-service-key.json
+gcloud auth activate-service-account --key-file ${HOME}/gcloud-service-key.json
+
+gcloud --quiet config set project $PROJECT_NAME
+gcloud --quiet config set container/cluster $CLUSTER_NAME
+gcloud --quiet config set compute/zone ${COMPUTE_ZONE}
+gcloud --quiet container clusters get-credentials $CLUSTER_NAME
+
+kubectl config current-context
+
+helm init --service-account tiller --upgrade
+
+kubectl apply -f "${__root}/.infra/kube/00-namespace.yaml"
+kubectl apply -f "${__root}/.infra/kube/deployment.yaml"
+kubectl apply -f "${__root}/.infra/kube/service.yaml"
+kubectl apply -f "${__root}/.infra/kube/ingress-tls.yaml"
+
+kubectl set image deployment/tusd --namespace=tus tusd=docker.io/tusproject/tusd:$TRAVIS_COMMIT
+
+kubectl get pods --namespace=tus
+kubectl get service --namespace=tus
+kubectl get deployment --namespace=tus
+
+
+function cleanup {
+ printf "Cleaning up...\n"
+ rm -vf "${HOME}/gcloud-service-key.json"
+ printf "Cleaning done."
+}
+
+trap cleanup EXIT
diff --git a/.scripts/test_all.sh b/.scripts/test_all.sh
index 7d85877..207f780 100755
--- a/.scripts/test_all.sh
+++ b/.scripts/test_all.sh
@@ -5,16 +5,20 @@ set -e
# Find all packages containing Go source code inside the current directory
packages=$(find ./ -maxdepth 2 -name '*.go' -printf '%h\n' | sort | uniq)
-# The consul package only supports Go1.7+ and therefore we will only run the
+# The consul package only supports Go1.8+ and therefore we will only run the
# corresponding tests on these versions.
goversion=$(go version)
if [[ "$goversion" == *"go1.5"* ]] ||
- [[ "$goversion" == *"go1.6"* ]]; then
+ [[ "$goversion" == *"go1.6"* ]] ||
+ [[ "$goversion" == *"go1.7"* ]]; then
echo "Skipping tests requiring Consul which is not supported on $goversion"
# Exclude consullocker since this may not be run on all Go versions.
packages=$(echo "$packages" | sed '/consul/d')
+
+ echo "Skipping tests requiring GCSStore, which is not supported on $goversion"
+ packages=$(echo "$packages" | sed '/gcsstore/d')
else
# Install the Consul packages which are not vendored.
go get -u github.com/hashicorp/consul/...
diff --git a/.travis.yml b/.travis.yml
index 68c7d70..5871433 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,12 +4,14 @@ go:
- 1.6
- 1.7
- 1.8
+- 1.9
sudo: required
cache:
apt: true
directories:
- $HOME/.gimme
- $HOME/.frey
+ - "$HOME/google-cloud-sdk/"
env:
global:
- GO15VENDOREXPERIMENT=1
@@ -24,6 +26,12 @@ script:
- ./.scripts/test_all.sh
before_deploy:
- if [[ "$TRAVIS_TAG" != "" ]]; then ./.scripts/build_all.sh; fi
+- if [ ! -d "$HOME/google-cloud-sdk/bin" ]; then rm -rf $HOME/google-cloud-sdk; curl https://sdk.cloud.google.com | bash; fi
+- source /home/travis/google-cloud-sdk/path.bash.inc
+- gcloud --quiet version
+- gcloud --quiet components update
+- gcloud --quiet components update kubectl
+- curl https://raw.githubusercontent.com/kubernetes/helm/8478fb4fc723885b155c924d1c8c410b7a9444e6/scripts/get | bash
deploy:
- provider: releases
api_key:
@@ -41,3 +49,9 @@ deploy:
branch: master
go: 1.8
repo: tus/tusd
+- provider: script
+ script: .scripts/deploy_gcloud.sh
+ on:
+ branch: k8s
+ go: 1.8
+ repo: tus/tusd
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..1c61c03
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,28 @@
+FROM golang:1.7-alpine
+
+# Copy in the git repo from the build context
+COPY . /go/src/github.com/tus/tusd/
+
+# Create app directory
+
+RUN addgroup -g 1000 tusd \
+ && adduser -u 1000 -G tusd -s /bin/sh -D tusd \
+ && cd /go/src/github.com/tus/tusd \
+ && apk add --no-cache \
+ git \
+ && go get -d -v ./... \
+ && version="$(git tag -l --points-at HEAD)" \
+ && commit=$(git log --format="%H" -n 1) \
+ && GOOS=linux GOARCH=amd64 go build \
+ -ldflags="-X github.com/tus/tusd/cmd/tusd/cli.VersionName=${version} -X github.com/tus/tusd/cmd/tusd/cli.GitCommit=${commit} -X 'github.com/tus/tusd/cmd/tusd/cli.BuildDate=$(date --utc)'" \
+ -o "/go/bin/tusd" ./cmd/tusd/main.go \
+ && mkdir -p /srv/tusd-data \
+ && mkdir -p /srv/tusd-hooks \
+ && chown tusd:tusd /srv/tusd-data \
+ && rm -r /go/src/* \
+ && apk del git
+
+WORKDIR /srv/tusd-data
+EXPOSE 1080
+USER tusd
+ENTRYPOINT ["/go/bin/tusd","-dir","/srv/tusd-data","--hooks-dir","/srv/tusd-hooks"]
diff --git a/README.md b/README.md
index c65ed86..b86f6e1 100644
--- a/README.md
+++ b/README.md
@@ -125,6 +125,7 @@ useful tools:
* [**s3store**](https://godoc.org/github.com/tus/tusd/s3store): A storage backend using AWS S3
* [**filestore**](https://godoc.org/github.com/tus/tusd/filestore): A storage backend using the local file system
+* [**gcsstore**](https://godoc.org/github.com/tus/tusd/gcsstore): A storage backend using Google cloud storage
* [**memorylocker**](https://godoc.org/github.com/tus/tusd/memorylocker): An in-memory locker for handling concurrent uploads
* [**consullocker**](https://godoc.org/github.com/tus/tusd/consullocker): A locker using the distributed Consul service
* [**limitedstore**](https://godoc.org/github.com/tus/tusd/limitedstore): A storage wrapper limiting the total used space for uploads
@@ -142,7 +143,7 @@ go test -v ./...
### How can I access tusd using HTTPS?
-The tusd binary, once executed, listens on the provided port for only non-encrypted HTTP requests and *does not accept* HTTPS connections. This decision has been made to limit the functionality inside this repository which has to be developed, tested and maintained. If you want to send requests to tusd in a secure fashion - what we absolutely encourage, we recommend you to utilize a reverse proxy in front of tusd which accepts incoming HTTPS connections and forwards them to tusd using plain HTTP. More information about this topic, including sample configurations for Nginx and Apache, can be found in [issue #86](https://github.com/tus/tusd/issues/86#issuecomment-269569077).
+The tusd binary, once executed, listens on the provided port for only non-encrypted HTTP requests and *does not accept* HTTPS connections. This decision has been made to limit the functionality inside this repository which has to be developed, tested and maintained. If you want to send requests to tusd in a secure fashion - what we absolutely encourage, we recommend you to utilize a reverse proxy in front of tusd which accepts incoming HTTPS connections and forwards them to tusd using plain HTTP. More information about this topic, including sample configurations for Nginx and Apache, can be found in [issue #86](https://github.com/tus/tusd/issues/86#issuecomment-269569077) and in the [Apache example configuration](.infra/files/apache2.conf).
### Can I run tusd behind a reverse proxy?
diff --git a/appveyor.yml b/appveyor.yml
index 444b35b..096d7e4 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -21,7 +21,6 @@ test_script:
- go test ./filestore
- go test ./limitedstore
- go test ./memorylocker
- - go test ./consullocker
- go test ./s3store
-
- go vet ./prometheuscollector
+ - go test ./gcsstore
diff --git a/cmd/tusd/cli/composer.go b/cmd/tusd/cli/composer.go
index 3590ef7..9715529 100644
--- a/cmd/tusd/cli/composer.go
+++ b/cmd/tusd/cli/composer.go
@@ -8,6 +8,7 @@ import (
"github.com/tus/tusd/limitedstore"
"github.com/tus/tusd/memorylocker"
"github.com/tus/tusd/s3store"
+ "github.com/tus/tusd/gcsstore"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
@@ -21,17 +22,7 @@ func CreateComposer() {
// Attempt to use S3 as a backend if the -s3-bucket option has been supplied.
// If not, we default to storing them locally on disk.
Composer = tusd.NewStoreComposer()
- if Flags.S3Bucket == "" {
- dir := Flags.UploadDir
-
- stdout.Printf("Using '%s' as directory storage.\n", dir)
- if err := os.MkdirAll(dir, os.FileMode(0774)); err != nil {
- stderr.Fatalf("Unable to ensure directory exists: %s", err)
- }
-
- store := filestore.New(dir)
- store.UseIn(Composer)
- } else {
+ if Flags.S3Bucket != "" {
s3Config := aws.NewConfig()
if Flags.S3Endpoint == "" {
@@ -50,6 +41,34 @@ func CreateComposer() {
locker := memorylocker.New()
locker.UseIn(Composer)
+ } else if Flags.GCSBucket != "" {
+ // Derivce credentials from service account file path passed in
+ // GCS_SERVICE_ACCOUNT_FILE environment variable.
+ gcsSAF := os.Getenv("GCS_SERVICE_ACCOUNT_FILE")
+ if gcsSAF == "" {
+ stderr.Fatalf("No service account file provided for Google Cloud Storage\n")
+ }
+
+ service, err := gcsstore.NewGCSService(gcsSAF)
+ if err != nil {
+ stderr.Fatalf("Unable to create Google Cloud Storage service: %s\n", err)
+ }
+
+ store := gcsstore.New(Flags.GCSBucket, service)
+ store.UseIn(Composer)
+
+ locker := memorylocker.New()
+ locker.UseIn(Composer)
+ } else {
+ dir := Flags.UploadDir
+
+ stdout.Printf("Using '%s' as directory storage.\n", dir)
+ if err := os.MkdirAll(dir, os.FileMode(0774)); err != nil {
+ stderr.Fatalf("Unable to ensure directory exists: %s", err)
+ }
+
+ store := filestore.New(dir)
+ store.UseIn(Composer)
}
storeSize := Flags.StoreSize
diff --git a/cmd/tusd/cli/flags.go b/cmd/tusd/cli/flags.go
index b61f4e7..d7c6234 100644
--- a/cmd/tusd/cli/flags.go
+++ b/cmd/tusd/cli/flags.go
@@ -6,22 +6,27 @@ import (
)
var Flags struct {
- HttpHost string
- HttpPort string
- MaxSize int64
- UploadDir string
- StoreSize int64
- Basepath string
- Timeout int64
- S3Bucket string
- S3Endpoint string
- HooksDir string
- ShowVersion bool
- ExposeMetrics bool
- MetricsPath string
- BehindProxy bool
+ HttpHost string
+ HttpPort string
+ MaxSize int64
+ UploadDir string
+ StoreSize int64
+ Basepath string
+ Timeout int64
+ S3Bucket string
+ S3Endpoint string
+ GCSBucket string
+ FileHooksDir string
+ HttpHooksEndpoint string
+ HttpHooksRetry int
+ HttpHooksBackoff int
+ ShowVersion bool
+ ExposeMetrics bool
+ MetricsPath string
+ BehindProxy bool
- HooksInstalled bool
+ FileHooksInstalled bool
+ HttpHooksInstalled bool
}
func ParseFlags() {
@@ -34,7 +39,11 @@ func ParseFlags() {
flag.Int64Var(&Flags.Timeout, "timeout", 30*1000, "Read timeout for connections in milliseconds. A zero value means that reads will not timeout")
flag.StringVar(&Flags.S3Bucket, "s3-bucket", "", "Use AWS S3 with this bucket as storage backend (requires the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION environment variables to be set)")
flag.StringVar(&Flags.S3Endpoint, "s3-endpoint", "", "Endpoint to use S3 compatible implementations like minio (requires s3-bucket to be pass)")
- flag.StringVar(&Flags.HooksDir, "hooks-dir", "", "Directory to search for available hooks scripts")
+ flag.StringVar(&Flags.GCSBucket, "gcs-bucket", "", "Use Google Cloud Storage with this bucket as storage backend (requires the GCS_SERVICE_ACCOUNT_FILE environment variable to be set)")
+ flag.StringVar(&Flags.FileHooksDir, "hooks-dir", "", "Directory to search for available hooks scripts")
+ flag.StringVar(&Flags.HttpHooksEndpoint, "hooks-http", "", "An HTTP endpoint to which hook events will be sent to")
+ flag.IntVar(&Flags.HttpHooksRetry, "hooks-http-retry", 3, "Number of times to retry on a 500 or network timeout")
+ flag.IntVar(&Flags.HttpHooksBackoff, "hooks-http-backoff", 1, "Number of seconds to wait before retrying each retry")
flag.BoolVar(&Flags.ShowVersion, "version", false, "Print tusd version information")
flag.BoolVar(&Flags.ExposeMetrics, "expose-metrics", true, "Expose metrics about tusd usage")
flag.StringVar(&Flags.MetricsPath, "metrics-path", "/metrics", "Path under which the metrics endpoint will be accessible")
@@ -42,11 +51,17 @@ func ParseFlags() {
flag.Parse()
- if Flags.HooksDir != "" {
- Flags.HooksDir, _ = filepath.Abs(Flags.HooksDir)
- Flags.HooksInstalled = true
+ if Flags.FileHooksDir != "" {
+ Flags.FileHooksDir, _ = filepath.Abs(Flags.FileHooksDir)
+ Flags.FileHooksInstalled = true
- stdout.Printf("Using '%s' for hooks", Flags.HooksDir)
+ stdout.Printf("Using '%s' for hooks", Flags.FileHooksDir)
+ }
+
+ if Flags.HttpHooksEndpoint != "" {
+ Flags.HttpHooksInstalled = true
+
+ stdout.Printf("Using '%s' as the endpoint for hooks", Flags.HttpHooksEndpoint)
}
if Flags.UploadDir == "" && Flags.S3Bucket == "" {
diff --git a/cmd/tusd/cli/hooks.go b/cmd/tusd/cli/hooks.go
index 5caf28e..3c64afe 100644
--- a/cmd/tusd/cli/hooks.go
+++ b/cmd/tusd/cli/hooks.go
@@ -4,11 +4,16 @@ import (
"bytes"
"encoding/json"
"fmt"
+ "io/ioutil"
+ "net/http"
"os"
"os/exec"
"strconv"
+ "time"
"github.com/tus/tusd"
+
+ "github.com/sethgrid/pester"
)
type HookType string
@@ -17,6 +22,7 @@ const (
HookPostFinish HookType = "post-finish"
HookPostTerminate HookType = "post-terminate"
HookPostReceive HookType = "post-receive"
+ HookPostCreate HookType = "post-create"
HookPreCreate HookType = "pre-create"
)
@@ -26,7 +32,7 @@ type hookDataStore struct {
func (store hookDataStore) NewUpload(info tusd.FileInfo) (id string, err error) {
if output, err := invokeHookSync(HookPreCreate, info, true); err != nil {
- return "", fmt.Errorf("pre-create hook failed: %s\n%s", err, string(output))
+ return "", fmt.Errorf("pre-create hook failed: %s\n%s", err, string(output))
}
return store.DataStore.NewUpload(info)
}
@@ -47,6 +53,8 @@ func SetupPostHooks(handler *tusd.Handler) {
invokeHook(HookPostTerminate, info)
case info := <-handler.UploadProgress:
invokeHook(HookPostReceive, info)
+ case info := <-handler.CreatedUploads:
+ invokeHook(HookPostCreate, info)
}
}
}()
@@ -67,14 +75,78 @@ func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byt
logEv("UploadTerminated", "id", info.ID)
}
- if !Flags.HooksInstalled {
+ if !Flags.FileHooksInstalled && !Flags.HttpHooksInstalled {
return nil, nil
}
-
name := string(typ)
logEv("HookInvocationStart", "type", name, "id", info.ID)
- cmd := exec.Command(Flags.HooksDir + "/" + name)
+ output := []byte{}
+ err := error(nil)
+
+ if Flags.FileHooksInstalled {
+ output, err = invokeFileHook(name, typ, info, captureOutput)
+ }
+
+ if Flags.HttpHooksInstalled {
+ output, err = invokeHttpHook(name, typ, info, captureOutput)
+ }
+
+ if err != nil {
+ logEv("HookInvocationError", "type", string(typ), "id", info.ID, "error", err.Error())
+ } else {
+ logEv("HookInvocationFinish", "type", string(typ), "id", info.ID)
+ }
+
+ return output, err
+}
+
+func invokeHttpHook(name string, typ HookType, info tusd.FileInfo, captureOutput bool) ([]byte, error) {
+ jsonInfo, err := json.Marshal(info)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("POST", Flags.HttpHooksEndpoint, bytes.NewBuffer(jsonInfo))
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Set("Hook-Name", name)
+ req.Header.Set("Content-Type", "application/json")
+
+ // Use linear backoff strategy with the user defined values.
+ client := pester.New()
+ client.KeepLog = true
+ client.MaxRetries = Flags.HttpHooksRetry
+ client.Backoff = func(_ int) time.Duration {
+ return time.Duration(Flags.HttpHooksBackoff) * time.Second
+ }
+
+ resp, err := client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ if resp.StatusCode >= http.StatusBadRequest {
+ return body, fmt.Errorf("endpoint returned: %s\n%s", resp.Status, body)
+ }
+
+ if captureOutput {
+ return body, err
+ }
+
+ return nil, err
+}
+
+func invokeFileHook(name string, typ HookType, info tusd.FileInfo, captureOutput bool) ([]byte, error) {
+ cmd := exec.Command(Flags.FileHooksDir + "/" + name)
env := os.Environ()
env = append(env, "TUS_ID="+info.ID)
env = append(env, "TUS_SIZE="+strconv.FormatInt(info.Size, 10))
@@ -89,7 +161,7 @@ func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byt
cmd.Stdin = reader
cmd.Env = env
- cmd.Dir = Flags.HooksDir
+ cmd.Dir = Flags.FileHooksDir
cmd.Stderr = os.Stderr
// If `captureOutput` is true, this function will return the output (both,
@@ -102,12 +174,6 @@ func invokeHookSync(typ HookType, info tusd.FileInfo, captureOutput bool) ([]byt
output, err = cmd.Output()
}
- if err != nil {
- logEv("HookInvocationError", "type", string(typ), "id", info.ID, "error", err.Error())
- } else {
- logEv("HookInvocationFinish", "type", string(typ), "id", info.ID)
- }
-
// Ignore the error, only, if the hook's file could not be found. This usually
// means that the user is only using a subset of the available hooks.
if os.IsNotExist(err) {
diff --git a/cmd/tusd/cli/serve.go b/cmd/tusd/cli/serve.go
index 594d66e..e01b9d7 100644
--- a/cmd/tusd/cli/serve.go
+++ b/cmd/tusd/cli/serve.go
@@ -18,6 +18,7 @@ func Serve() {
NotifyCompleteUploads: true,
NotifyTerminatedUploads: true,
NotifyUploadProgress: true,
+ NotifyCreatedUploads: true,
})
if err != nil {
stderr.Fatalf("Unable to create handler: %s", err)
diff --git a/cmd/tusd/tusd b/cmd/tusd/tusd
new file mode 100755
index 0000000..03a31a7
Binary files /dev/null and b/cmd/tusd/tusd differ
diff --git a/config.go b/config.go
index 94b4f7e..9c8d454 100644
--- a/config.go
+++ b/config.go
@@ -34,6 +34,9 @@ type Config struct {
// NotifyUploadProgress indicates whether sending notifications about
// the upload progress using the UploadProgress channel should be enabled.
NotifyUploadProgress bool
+ // NotifyCreatedUploads indicates whether sending notifications about
+ // the upload having been created using the CreatedUploads channel should be enabled.
+ NotifyCreatedUploads bool
// Logger is the logger to use internally, mostly for printing requests.
Logger *log.Logger
// Respect the X-Forwarded-Host, X-Forwarded-Proto and Forwarded headers
diff --git a/consullocker/consullocker_test.go b/consullocker/consullocker_test.go
index 0eb90e5..19dbed6 100644
--- a/consullocker/consullocker_test.go
+++ b/consullocker/consullocker_test.go
@@ -14,12 +14,15 @@ import (
func TestConsulLocker(t *testing.T) {
a := assert.New(t)
- server := consultestutil.NewTestServer(t)
+ server, err := consultestutil.NewTestServer()
+ if err != nil {
+ t.Fatal(err)
+ }
defer server.Stop()
- client, err := consul.NewClient(&consul.Config{
- Address: server.HTTPAddr,
- })
+ conf := consul.DefaultConfig()
+ conf.Address = server.HTTPAddr
+ client, err := consul.NewClient(conf)
a.NoError(err)
locker := New(client)
@@ -38,7 +41,10 @@ func TestLockLost(t *testing.T) {
a := assert.New(t)
- server := consultestutil.NewTestServer(t)
+ server, err := consultestutil.NewTestServer()
+ if err != nil {
+ t.Fatal(err)
+ }
client, err := consul.NewClient(&consul.Config{
Address: server.HTTPAddr,
diff --git a/cors_test.go b/cors_test.go
index 0dfb537..e7876e5 100644
--- a/cors_test.go
+++ b/cors_test.go
@@ -2,6 +2,7 @@ package tusd_test
import (
"net/http"
+ "net/http/httptest"
"testing"
. "github.com/tus/tusd"
@@ -46,4 +47,31 @@ func TestCORS(t *testing.T) {
},
}).Run(handler, t)
})
+
+ SubTest(t, "AppendHeaders", func(t *testing.T, store *MockFullDataStore) {
+ handler, _ := NewHandler(Config{
+ DataStore: store,
+ })
+
+ req, _ := http.NewRequest("OPTIONS", "", nil)
+ req.Header.Set("Tus-Resumable", "1.0.0")
+ req.Header.Set("Origin", "tus.io")
+ req.Host = "tus.io"
+
+ res := httptest.NewRecorder()
+ res.HeaderMap.Set("Access-Control-Allow-Headers", "HEADER")
+ res.HeaderMap.Set("Access-Control-Allow-Methods", "METHOD")
+ handler.ServeHTTP(res, req)
+
+ headers := res.HeaderMap["Access-Control-Allow-Headers"]
+ methods := res.HeaderMap["Access-Control-Allow-Methods"]
+
+ if headers[0] != "HEADER" {
+ t.Errorf("expected header to contain HEADER but got: %#v", headers)
+ }
+
+ if methods[0] != "METHOD" {
+ t.Errorf("expected header to contain HEADER but got: %#v", methods)
+ }
+ })
}
diff --git a/docs/hooks.md b/docs/hooks.md
index 55d6101..cfa3e47 100644
--- a/docs/hooks.md
+++ b/docs/hooks.md
@@ -1,15 +1,47 @@
# Hooks
-When integrating tusd into an application, it is important to establish a communication channel between the two components. The tusd binary accomplishes this by providing a Hook system which will execute custom code when certain events happen, such as an upload being created or finished. While being simple, yet powerful enough, enabled uses ranging from logging over validation and authorization to processing the uploaded files.
+When integrating tusd into an application, it is important to establish a communication channel between the two components. The tusd binary accomplishes this by providing a system which triggers actions when certain events happen, such as an upload being created or finished. This simple-but-powerful system enables uses ranging from logging over validation and authorization to processing the uploaded files.
-If you have previously worked with the hook system provided by [Git](https://git-scm.com/book/it/v2/Customizing-Git-Git-Hooks), you will see a lot of parallels. If this does not apply to you, don't worry, it is not complicated. Before getting stated, it is good to have a high level overview of what a hook is actually: It is a regular file, located in a specific directory, which will be executed once a certain event occurs. This file can either be a script interpreted by a runtime, such as Bash or Python, or a compiled binary. When invoked, the process will be provided with information about the event triggering the occuring event and the associated uploaded.
+When a specific action happens during an upload (pre-create, post-receive, post-finish, or post-terminate), the hook system enables tusd to fire off a specific event. Tusd provides two ways of doing this:
-## The Hook Directory
+1. Execute an arbitrary file, mirroring the Git hook system, called File Hooks.
+2. Fire off an HTTP POST request to a custom endpoint, called HTTP Hooks.
-By default, the hook system is disabled. To enable it, pass the `--hook-dir` option to the tusd binary. The flag's value will be a path, the **hook directory**, relative to the current working directory, pointing to the folder containing the executable **hook files**:
+## Blocking and Non-Blocking Hooks
+
+If not otherwise noted, all hooks are invoked in a *non-blocking* way, meaning that tusd will not wait until the hook process has finished and exited. Therefore, the hook process is not able to influence how tusd may continue handling the current request, regardless of which exit code it may set. Furthermore, the hook process' stdout and stderr will be piped to tusd's stdout and stderr correspondingly, allowing one to use these channels for additional logging.
+
+On the other hand, there are a few *blocking* hooks, such as caused by the `pre-create` event. Because their exit code will dictate whether tusd will accept the current incoming request, tusd will wait until the hook process has exited. Therefore, in order to keep the response times low, one should avoid to make time-consuming operations inside the processes for blocking hooks. An exit code of `0` indicates that tusd should continue handling the request as normal. On the other hand, a non-zero exit code tells tusd to reject the request with a `500 Internal Server Error` response containing the process' output from stderr. For the sake of logging, the process' output from stdout will always be piped to tusd's stdout.
+
+## List of Available Hooks
+
+### pre-create
+
+This event will be triggered before an upload is created, allowing you to run certain routines. For example, validating that specific metadata values are set, or verifying that a corresponding entity belonging to the upload (e.g. a user) exists. Because this event will result in a blocking hook, you can determine whether the upload should be created or rejected using the exit code. An exit code of `0` will allow the upload to be created and continued as usual. A non-zero exit code will reject an upload creation request, making it a good place for authentication and authorization. Please be aware, that during this stage the upload ID will be an empty string as the entity has not been created and therefore this piece of information is not yet available.
+
+### post-create
+
+This event will be triggered after an upload is created, allowing you to run certain routines. For example, notifying other parts of your system that a new upload has to be handled. At this point the upload may have received some data already since the invocation of these hooks may be delayed by a short duration.
+
+### post-finish
+
+This event will be triggered after an upload is fully finished, meaning that all chunks have been transfered and saved in the storage. After this point, no further modifications, except possible deletion, can be made to the upload entity and it may be desirable to use the file for further processing or notify other applications of the completions of this upload.
+
+### post-terminate
+
+This event will be triggered after an upload has been terminated, meaning that the upload has been totally stopped and all associating chunks have been fully removed from the storage. Therefore, one is not able to retrieve the upload's content anymore and one may wish to notify further applications that this upload will never be resumed nor finished.
+
+### post-receive
+
+This event will be triggered for every running upload to indicate its current progress. It will occur for each open PATCH request, every second. The offset property will be set to the number of bytes which have been transfered to the server, at the time in total. Please be aware that this number may be higher than the number of bytes which have been stored by the data store!
+
+
+## File Hooks
+### The Hook Directory
+By default, the file hook system is disabled. To enable it, pass the `--hooks-dir` option to the tusd binary. The flag's value will be a path, the **hook directory**, relative to the current working directory, pointing to the folder containing the executable **hook files**:
```bash
-$ tusd --hook-dir ./path/to/hooks/
+$ tusd --hooks-dir ./path/to/hooks/
[tusd] Using './path/to/hooks/' for hooks
[tusd] Using './data' as directory storage.
@@ -18,7 +50,7 @@ $ tusd --hook-dir ./path/to/hooks/
If an event occurs, the tusd binary will look for a file, named exactly as the event, which will then be executed, as long as the object exists. In the example above, the binary `./path/to/hooks/pre-create` will be invoked, before an upload is created, which can be used to e.g. validate certain metadata. Please note, that the hook file *must not* have an extension, such as `.sh` or `.py`, or else tusd will not recognize and ignore it. A detailed list of all events can be found at the end of this document.
-## The Hook's Environment
+### The Hook's Environment
The process of the hook files are provided with information about the event and the upload using to two methods:
* The `TUS_ID` and `TUS_SIZE` environment variables will contain the upload ID and its size in bytes, which triggered the event. Please be aware, that in the `pre-create` hook the upload ID will be an empty string as the entity has not been created and therefore this piece of information is not yet available.
@@ -50,26 +82,58 @@ The process of the hook files are provided with information about the event and
}
```
-## Blocking and Non-Blocking Hooks
+Be aware that this environment does *not* contain direct data from any HTTP request, in particular not any header values or cookies. If you would like to pass information from the client to the hook, such as authentication details, you may wish to use the [metadata system](http://tus.io/protocols/resumable-upload.html#upload-metadata).
-If not otherwise noted, all hooks are invoked in a *non-blocking* way, meaning that tusd will not wait until the hook process has finished and exited. Therefore, the hook process is not able to influence how tusd may continue handling the current request, regardless of which exit code it may set. Furthermore, the hook process' stdout and stderr will be piped to tusd's stdout and stderr correspondingly, allowing one to use these channels for additional logging.
-On the other hand, there are a few *blocking* hooks, such as caused by the `pre-create` event. Because their exit code will dictate whether tusd will accept the current incoming request, tusd will wait until the hook process has exited. Therefore, in order to keep the response times low, one should avoid to make time-consuming operations inside the processes for blocking hooks. An exit code of `0` indicates that tusd should continue handling the request as normal. On the other hand, a non-zero exit code tells tusd to reject the request with a `500 Internal Server Error` response containing the process' output from stderr. For the sake of logging, the process' output from stdout will always be piped to tusd's stdout.
+## HTTP Hooks
-## List of Available Hooks
+HTTP Hooks are the second type of hooks supported by tusd. Like the file hooks, it is disabled by default. To enable it, pass the `--hooks-http` option to the tusd binary. The flag's value will be an HTTP URL endpoint, which the tusd binary will issue POST requests to:
-### pre-create
+```bash
+$ tusd --hooks-http http://localhost:8081/write
-This event will be triggered before an upload is created, allowing you to run certain routines. For example, validating that specific metadata values are set, or verifying that a corresponding entity belonging to the upload (e.g. a user) exists. Because this event will result in a blocking hook, you can determine whether the upload should be created or rejected using the exit code. An exit code of `0` will allow the upload to be created and continued as usual. A non-zero exit code will reject an upload creation request, making it a good place for authentication and authorization. Please be aware, that during this stage the upload ID will be an empty string as the entity has not been created and therefore this piece of information is not yet available.
+[tusd] Using 'http://localhost:8081/write' as the endpoint for hooks
+[tusd] Using './data' as directory storage.
+...
+```
-### post-finish
+Note that the URL must include the `http://` prefix!
-This event will be triggered after an upload is fully finished, meaning that all chunks have been transfered and saved in the storage. After this point, no further modifications, except possible deletion, can be made to the upload entity and it may be desirable to use the file for further processing or notify other applications of the completions of this upload.
+### Usage
-### post-terminate
+Tusd will issue a `POST` request to the specified URL endpoint, specifying the hook name, such as pre-create or post-finish, in the `Hook-Name` header and following body:
-This event will be triggered after an upload has been terminated, meaning that the upload has been totally stopped and all associating chunks have been fully removed from the storage. Therefore, one is not able to retrieve the upload's content anymore and one may wish to notify further applications that this upload will never be resumed nor finished.
+```js
+{
+ // The upload's ID. Will be empty during the pre-create event
+ "ID": "14b1c4c77771671a8479bc0444bbc5ce",
+ // The upload's total size in bytes.
+ "Size": 46205,
+ // The upload's current offset in bytes.
+ "Offset": 1592,
+ // These properties will be set to true, if the upload as a final or partial
+ // one. See the Concatenation extension for details:
+ // http://tus.io/protocols/resumable-upload.html#concatenation
+ "IsFinal": false,
+ "IsPartial": false,
+ // If the upload is a final one, this value will be an array of upload IDs
+ // which are concatenated to produce the upload.
+ "PartialUploads": null,
+ // The upload's meta data which can be supplied by the clients as it wishes.
+ // All keys and values in this object will be strings.
+ // Be aware that it may contain maliciously crafted values and you must not
+ // trust it without escaping it first!
+ "MetaData": {
+ "filename": "transloadit.png"
+ }
+}
+```
-### post-receive
+### Configuration
-This event will be triggered for every running upload to indicate its current progress. It will occur for each open PATCH request, every second. The offset property will be set to the number of bytes which have been transfered to the server, at the time in total. Please be aware that this number may be higher than the number of bytes which have been stored by the data store!
+Tusd uses the [Pester library](https://github.com/sethgrid/pester) to issue requests and handle retries. By default, tusd will retry 3 times on a `500 Internal Server Error` response or network error, with a 1 second backoff. This can be configured with the flags `--hooks-http-retry` and `--hooks-http-backoff`, like so:
+
+```
+$ # Retrying 5 times with a 2 second backoff
+$ tusd --hooks-http http://localhost:8081/write --hooks-http-retry 5 --hooks-http-backoff 2
+```
diff --git a/filestore/filestore.go b/filestore/filestore.go
index f1b5c5b..23a1618 100644
--- a/filestore/filestore.go
+++ b/filestore/filestore.go
@@ -54,6 +54,7 @@ func (store FileStore) UseIn(composer *tusd.StoreComposer) {
composer.UseGetReader(store)
composer.UseTerminater(store)
composer.UseLocker(store)
+ composer.UseConcater(store)
}
func (store FileStore) NewUpload(info tusd.FileInfo) (id string, err error) {
diff --git a/filestore/filestore_test.go b/filestore/filestore_test.go
index 06c1d39..69c99c8 100644
--- a/filestore/filestore_test.go
+++ b/filestore/filestore_test.go
@@ -95,7 +95,6 @@ func TestFileLocker(t *testing.T) {
a.NoError(locker.LockUpload("one"))
a.Equal(tusd.ErrFileLocked, locker.LockUpload("one"))
a.NoError(locker.UnlockUpload("one"))
- a.NoError(locker.UnlockUpload("one"))
}
func TestConcatUploads(t *testing.T) {
diff --git a/gcsstore/gcsservice.go b/gcsstore/gcsservice.go
new file mode 100644
index 0000000..b331717
--- /dev/null
+++ b/gcsstore/gcsservice.go
@@ -0,0 +1,376 @@
+package gcsstore
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "strconv"
+ "strings"
+
+ "cloud.google.com/go/storage"
+ "golang.org/x/net/context"
+ "google.golang.org/api/iterator"
+ "google.golang.org/api/option"
+
+ "github.com/vimeo/go-util/crc32combine"
+ "hash/crc32"
+)
+
+type GCSObjectParams struct {
+ // Bucket specifies the GCS bucket that the object resides in.
+ Bucket string
+
+ // ID specifies the ID of the GCS object.
+ ID string
+}
+
+type GCSComposeParams struct {
+ // Bucket specifies the GCS bucket which the composed objects will be stored in.
+ Bucket string
+
+ // Sources is a list of the object IDs that are going to be composed.
+ Sources []string
+
+ // Destination specifies the desired ID of the composed object.
+ Destination string
+}
+
+type GCSFilterParams struct {
+ // Bucket specifies the GCS bucket of which the objects you want to filter reside in.
+ Bucket string
+
+ // Prefix specifies the prefix of which you want to filter object names with.
+ Prefix string
+}
+
+// GCSReader implements cloud.google.com/go/storage.Reader.
+// It is used to read Google Cloud storage objects.
+type GCSReader interface {
+ Close() error
+ ContentType() string
+ Read(p []byte) (int, error)
+ Remain() int64
+ Size() int64
+}
+
+// GCSAPI is an interface composed of all the necessary GCS
+// operations that are required to enable the tus protocol
+// to work with Google's cloud storage.
+type GCSAPI interface {
+ ReadObject(params GCSObjectParams) (GCSReader, error)
+ GetObjectSize(params GCSObjectParams) (int64, error)
+ SetObjectMetadata(params GCSObjectParams, metadata map[string]string) error
+ DeleteObject(params GCSObjectParams) error
+ DeleteObjectsWithFilter(params GCSFilterParams) error
+ WriteObject(params GCSObjectParams, r io.Reader) (int64, error)
+ ComposeObjects(params GCSComposeParams) error
+ FilterObjects(params GCSFilterParams) ([]string, error)
+}
+
+// GCSService holds the cloud.google.com/go/storage client
+// as well as its associated context.
+// Closures are used as minimal wrappers aroudn the Google Cloud Storage API, since the Storage API cannot be mocked.
+// The usage of these closures allow them to be redefined in the testing package, allowing test to be run against this file.
+type GCSService struct {
+ Client *storage.Client
+ Ctx context.Context
+}
+
+// NewGCSService returns a GCSSerivce object given a GCloud service account file path.
+func NewGCSService(filename string) (*GCSService, error) {
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithServiceAccountFile(filename))
+ if err != nil {
+ return nil, err
+ }
+
+ service := &GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ return service, nil
+}
+
+// GetObjectSize returns the byte length of the specified GCS object.
+func (service *GCSService) GetObjectSize(params GCSObjectParams) (int64, error) {
+ attrs, err := service.GetObjectAttrs(params)
+ if err != nil {
+ return 0, err
+ }
+
+ return attrs.Size, nil
+}
+
+// DeleteObjectWithPrefix will delete objects who match the provided filter parameters.
+func (service *GCSService) DeleteObjectsWithFilter(params GCSFilterParams) error {
+ names, err := service.FilterObjects(params)
+ if err != nil {
+ return err
+ }
+
+ var objectParams GCSObjectParams
+ for _, name := range names {
+ objectParams = GCSObjectParams{
+ Bucket: params.Bucket,
+ ID: name,
+ }
+
+ err := service.DeleteObject(objectParams)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+const COMPOSE_RETRIES = 3
+
+// Compose takes a bucket name, a list of initial source names, and a destination string to compose multiple GCS objects together
+func (service *GCSService) compose(bucket string, srcs []string, dst string) error {
+ dstParams := GCSObjectParams{
+ Bucket: bucket,
+ ID: dst,
+ }
+ objSrcs := make([]*storage.ObjectHandle, len(srcs))
+ var crc uint32
+ for i := 0; i < len(srcs); i++ {
+ objSrcs[i] = service.Client.Bucket(bucket).Object(srcs[i])
+ srcAttrs, err := service.GetObjectAttrs(GCSObjectParams{
+ Bucket: bucket,
+ ID: srcs[i],
+ })
+ if err != nil {
+ return err
+ }
+
+ if i == 0 {
+ crc = srcAttrs.CRC32C
+ } else {
+ crc = crc32combine.CRC32Combine(crc32.Castagnoli, crc, srcAttrs.CRC32C, srcAttrs.Size)
+ }
+ }
+
+ attrs, err := service.GetObjectAttrs(GCSObjectParams{
+ Bucket: bucket,
+ ID: srcs[0],
+ })
+ if err != nil {
+ return err
+ }
+
+ for i := 0; i < COMPOSE_RETRIES; i++ {
+ dstCRC, err := service.ComposeFrom(objSrcs, dstParams, attrs.ContentType)
+ if err != nil {
+ return err
+ }
+
+ if dstCRC == crc {
+ return nil
+ }
+ }
+
+ err = service.DeleteObject(GCSObjectParams{
+ Bucket: bucket,
+ ID: dst,
+ })
+
+ if err != nil {
+ return err
+ }
+
+ err = errors.New("GCS compose failed: Mismatch of CRC32 checksums")
+ return err
+}
+
+// MAX_OBJECT_COMPOSITION specifies the maximum number of objects that
+// can combined in a compose operation. GCloud storage's limit is 32.
+const MAX_OBJECT_COMPOSITION = 32
+
+func (service *GCSService) recursiveCompose(srcs []string, params GCSComposeParams, lvl int) error {
+ if len(srcs) <= MAX_OBJECT_COMPOSITION {
+ err := service.compose(params.Bucket, srcs, params.Destination)
+ if err != nil {
+ return err
+ }
+
+ // Remove all the temporary composition objects
+ prefix := fmt.Sprintf("%s_tmp", params.Destination)
+ filterParams := GCSFilterParams{
+ Bucket: params.Bucket,
+ Prefix: prefix,
+ }
+
+ err = service.DeleteObjectsWithFilter(filterParams)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ }
+
+ tmpSrcLen := int(math.Ceil(float64(len(srcs)) / float64(MAX_OBJECT_COMPOSITION)))
+ tmpSrcs := make([]string, tmpSrcLen)
+
+ for i := 0; i < tmpSrcLen; i++ {
+ start := i * MAX_OBJECT_COMPOSITION
+ end := MAX_OBJECT_COMPOSITION * (i + 1)
+ if tmpSrcLen-i == 1 {
+ end = len(srcs)
+ }
+
+ tmpDst := fmt.Sprintf("%s_tmp_%d_%d", params.Destination, lvl, i)
+ err := service.compose(params.Bucket, srcs[start:end], tmpDst)
+ if err != nil {
+ return err
+ }
+
+ tmpSrcs[i] = tmpDst
+ }
+
+ return service.recursiveCompose(tmpSrcs, params, lvl+1)
+}
+
+// ComposeObjects composes multiple GCS objects in to a single object.
+// Since GCS limits composition to a max of 32 objects, additional logic
+// has been added to chunk objects in to groups of 32 and then recursively
+// compose those objects together.
+func (service *GCSService) ComposeObjects(params GCSComposeParams) error {
+ err := service.recursiveCompose(params.Sources, params, 0)
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// GetObjectAttrs returns the associated attributes of a GCS object. See: https://godoc.org/cloud.google.com/go/storage#ObjectAttrs
+func (service *GCSService) GetObjectAttrs(params GCSObjectParams) (*storage.ObjectAttrs, error) {
+ obj := service.Client.Bucket(params.Bucket).Object(params.ID)
+
+ attrs, err := obj.Attrs(service.Ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ return attrs, nil
+
+}
+
+// ReadObject reaads a GCSObjectParams, returning a GCSReader object if successful, and an error otherwise
+func (service *GCSService) ReadObject(params GCSObjectParams) (GCSReader, error) {
+ r, err := service.Client.Bucket(params.Bucket).Object(params.ID).NewReader(service.Ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ return r, nil
+}
+
+// SetObjectMetadata reads a GCSObjectParams and a map of metedata, returning a nil on sucess and an error otherwise
+func (service *GCSService) SetObjectMetadata(params GCSObjectParams, metadata map[string]string) error {
+ attrs := storage.ObjectAttrsToUpdate{
+ Metadata: metadata,
+ }
+ _, err := service.Client.Bucket(params.Bucket).Object(params.ID).Update(service.Ctx, attrs)
+
+ return err
+}
+
+// DeleteObject deletes the object defined by GCSObjectParams
+func (service *GCSService) DeleteObject(params GCSObjectParams) error {
+ return service.Client.Bucket(params.Bucket).Object(params.ID).Delete(service.Ctx)
+}
+
+// Write object writes the file set out by the GCSObjectParams
+func (service *GCSService) WriteObject(params GCSObjectParams, r io.Reader) (int64, error) {
+ obj := service.Client.Bucket(params.Bucket).Object(params.ID)
+
+ w := obj.NewWriter(service.Ctx)
+
+ defer w.Close()
+
+ n, err := io.Copy(w, r)
+ if err != nil {
+ return 0, err
+ }
+
+ return n, err
+}
+
+// ComposeFrom composes multiple object types together,
+func (service *GCSService) ComposeFrom(objSrcs []*storage.ObjectHandle, dstParams GCSObjectParams, contentType string) (uint32, error) {
+ dstObj := service.Client.Bucket(dstParams.Bucket).Object(dstParams.ID)
+ c := dstObj.ComposerFrom(objSrcs...)
+ c.ContentType = contentType
+ _, err := c.Run(service.Ctx)
+ if err != nil {
+ return 0, err
+ }
+
+ dstAttrs, err := dstObj.Attrs(service.Ctx)
+ if err != nil {
+ return 0, err
+ }
+
+ return dstAttrs.CRC32C, nil
+}
+
+// FilterObjects retuns a list of GCS object IDs that match the passed GCSFilterParams.
+// It expects GCS objects to be of the format [uid]_[chunk_idx] where chunk_idx
+// is zero based. The format [uid]_tmp_[recursion_lvl]_[chunk_idx] can also be used to
+// specify objects that have been composed in a recursive fashion. These different formats
+// are usedd to ensure that objects are composed in the correct order.
+func (service *GCSService) FilterObjects(params GCSFilterParams) ([]string, error) {
+ bkt := service.Client.Bucket(params.Bucket)
+ q := storage.Query{
+ Prefix: params.Prefix,
+ Versions: false,
+ }
+
+ it := bkt.Objects(service.Ctx, &q)
+ names := make([]string, 0)
+ for {
+ objAttrs, err := it.Next()
+ if err == iterator.Done {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ split := strings.Split(objAttrs.Name, "_")
+
+ // If the object name splits on "_" in to four pieces we
+ // know the object name we are working with is in the format
+ // [uid]_tmp_[recursion_lvl]_[chunk_idx]. The only time we filter
+ // these temporary objects is on a delete operation so we can just
+ // append and continue without worrying about index order
+ if len(split) == 4 {
+ names = append(names, objAttrs.Name)
+ continue
+ }
+
+ if len(split) != 2 {
+ err := errors.New("Invalid filter format for object name")
+ return nil, err
+ }
+
+ idx, err := strconv.Atoi(split[1])
+ if err != nil {
+ return nil, err
+ }
+
+ if len(names) <= idx {
+ names = append(names, make([]string, idx-len(names)+1)...)
+ }
+
+ names[idx] = objAttrs.Name
+ }
+
+ return names, nil
+
+}
diff --git a/gcsstore/gcsservice_test.go b/gcsstore/gcsservice_test.go
new file mode 100644
index 0000000..b9093ef
--- /dev/null
+++ b/gcsstore/gcsservice_test.go
@@ -0,0 +1,497 @@
+package gcsstore_test
+
+import (
+ "bytes"
+ "context"
+ "testing"
+
+ "gopkg.in/h2non/gock.v1"
+
+ "cloud.google.com/go/storage"
+ . "github.com/tus/tusd/gcsstore"
+ "google.golang.org/api/option"
+)
+
+type googleObjectResponse struct {
+ Name string `json:"name"`
+}
+
+type googleBucketResponse struct {
+ Items []googleObjectResponse `json:"items"`
+}
+
+func TestGetObjectSize(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/test-name").
+ MatchParam("alt", "json").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{"size": "54321"})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ size, err := service.GetObjectSize(GCSObjectParams{
+ Bucket: "test-bucket",
+ ID: "test-name",
+ })
+ if err != nil {
+ t.Errorf("Error: %v", err)
+ return
+ }
+
+ if size != 54321 {
+ t.Errorf("Error: Did not match given size")
+ return
+ }
+}
+
+func TestDeleteObjectWithFilter(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o").
+ MatchParam("alt", "json").
+ MatchParam("pageToken", "").
+ MatchParam("prefix", "test-prefix").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ err = service.DeleteObjectsWithFilter(GCSFilterParams{
+ Bucket: "test-bucket",
+ Prefix: "test-prefix",
+ })
+
+ if err != nil {
+ t.Errorf("Error: %v", err)
+ return
+ }
+
+}
+
+func TestComposeObjects(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/test1").
+ MatchParam("alt", "json").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/test2").
+ MatchParam("alt", "json").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/test3").
+ MatchParam("alt", "json").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/test1").
+ MatchParam("alt", "json").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://www.googleapis.com").
+ Post("/storage/v1/b/test-bucket/o/test_all/compose").
+ MatchParam("alt", "json").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/test_all").
+ MatchParam("alt", "json").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o").
+ MatchParam("alt", "json").
+ MatchParam("delimiter", "").
+ MatchParam("pageToken", "").
+ MatchParam("prefix", "test_all_tmp").
+ MatchParam("projection", "full").
+ MatchParam("versions", "false").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ err = service.ComposeObjects(GCSComposeParams{
+ Bucket: "test-bucket",
+ Sources: []string{"test1", "test2", "test3"},
+ Destination: "test_all",
+ })
+
+ if err != nil {
+ t.Errorf("Error: %v", err)
+ return
+ }
+}
+
+func TestGetObjectAttrs(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/test-name").
+ MatchParam("alt", "json").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{"size": "54321", "name": "test_name"})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ attrs, err := service.GetObjectAttrs(GCSObjectParams{
+ Bucket: "test-bucket",
+ ID: "test-name",
+ })
+ if err != nil {
+ t.Errorf("Error: %v", err)
+ return
+ }
+
+ if attrs.Name != "test_name" && attrs.Size != 54321 {
+ t.Errorf("Mismatched attributes - got: %+v", attrs)
+ return
+ }
+
+}
+
+func TestReadObject(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://storage.googleapis.com").
+ Get("/test-bucket/test-name").
+ Reply(200).
+ JSON(map[string]string{"this": "is", "a": "fake file"})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ reader, err := service.ReadObject(GCSObjectParams{
+ Bucket: "test-bucket",
+ ID: "test-name",
+ })
+
+ if reader.Size() != 30 {
+ t.Errorf("Object size does not match expected value: %+v", reader)
+ }
+}
+
+func TestSetObjectMetadata(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://googleapis.com").
+ Patch("/storage/v1/b/test-bucket/o/test-name").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ err = service.SetObjectMetadata(GCSObjectParams{
+ Bucket: "test-bucket",
+ ID: "test-name",
+ }, map[string]string{"test": "metadata", "fake": "test"})
+
+ if err != nil {
+ t.Errorf("Error updating metadata: %+v", err)
+ }
+}
+
+func TestDeleteObject(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://googleapis.com").
+ Delete("/storage/v1/b/test-bucket/o/test-name").
+ MatchParam("alt", "json").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ err = service.DeleteObject(GCSObjectParams{
+ Bucket: "test-bucket",
+ ID: "test-name",
+ })
+
+ if err != nil {
+ t.Errorf("Error deleting object: %+v", err)
+ }
+}
+
+func TestWriteObject(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ reader := bytes.NewReader([]byte{1})
+
+ size, err := service.WriteObject(GCSObjectParams{
+ Bucket: "test-bucket",
+ ID: "test-name",
+ }, reader)
+
+ if err != nil {
+ t.Errorf("Error deleting object: %+v", err)
+ }
+
+ if size != 1 {
+ t.Errorf("Mismatch of object size: %v", size)
+ }
+}
+
+func TestComposeFrom(t *testing.T) {
+ defer gock.Off()
+
+ gock.New("https://googleapis.com").
+ Post("/storage/v1/b/test-bucket/o/my-object/compose").
+ MatchParam("alt", "json").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://googleapis.com").
+ Get("/storage/v1/b/test-bucket/o/my-object").
+ MatchParam("alt", "json").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(map[string]string{})
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ crc, err := service.ComposeFrom([]*storage.ObjectHandle{client.Bucket("test-bucket").Object("my-object")}, GCSObjectParams{
+ Bucket: "test-bucket",
+ ID: "my-object",
+ }, "text")
+
+ if err != nil {
+ t.Errorf("Error composing multiple objects: %+v", err)
+ }
+
+ if crc != 0 {
+ t.Errorf("Error composing multiple objects: %v", crc)
+ }
+}
+
+func TestFilterObject(t *testing.T) {
+ defer gock.Off()
+
+ resp := googleBucketResponse{[]googleObjectResponse{
+ googleObjectResponse{Name: "test-prefix_1"},
+ }}
+
+ gock.New("https://www.googleapis.com").
+ Get("/storage/v1/b/test-bucket/o").
+ MatchParam("alt", "json").
+ MatchParam("pageToken", "").
+ MatchParam("prefix", "test-prefix").
+ MatchParam("projection", "full").
+ Reply(200).
+ JSON(resp)
+
+ gock.New("https://accounts.google.com/").
+ Post("/o/oauth2/token").Reply(200).JSON(map[string]string{
+ "access_token": "H3l5321N123sdI4HLY/RF39FjrCRF39FjrCRF39FjrCRF39FjrC_RF39FjrCRF39FjrC",
+ "token_type": "Bearer",
+ "refresh_token": "1/smWJksmWJksmWJksmWJksmWJk_smWJksmWJksmWJksmWJksmWJk",
+ "expiry_date": "1425333671141",
+ })
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithAPIKey("foo"))
+ if err != nil {
+ t.Fatal(err)
+ return
+ }
+
+ service := GCSService{
+ Client: client,
+ Ctx: ctx,
+ }
+
+ objects, err := service.FilterObjects(GCSFilterParams{
+ Bucket: "test-bucket",
+ Prefix: "test-prefix",
+ })
+
+ if err != nil {
+ t.Errorf("Error: %v", err)
+ return
+ }
+
+ if len(objects) != 2 {
+ t.Errorf("Didn't get appropriate amount of objects back: got %v from %v", len(objects), objects)
+ }
+}
diff --git a/gcsstore/gcsstore.go b/gcsstore/gcsstore.go
new file mode 100644
index 0000000..8f3e34e
--- /dev/null
+++ b/gcsstore/gcsstore.go
@@ -0,0 +1,259 @@
+// Package gcsstore provides a Google cloud storage based backend.
+//
+// GCSStore is a storage backend that uses the GCSAPI interface in order to store uploads
+// on GCS. Uploads will be represented by two files in GCS; the data file will be stored
+// as an extensionless object [uid] and the JSON info file will stored as [uid].info.
+// In order to store uploads on GCS, make sure to specifiy the appropriate Google service
+// account file path in the GCS_SERVICE_ACCOUNT_FILE environment variable. Also make sure that
+// this service account file has the "https://www.googleapis.com/auth/devstorage.read_write"
+// scope enabled so you can read and write data to the storage buckets associated with the
+// service account file.
+package gcsstore
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+
+ "github.com/tus/tusd"
+ "github.com/tus/tusd/uid"
+)
+
+// See the tusd.DataStore interface for documentation about the different
+// methods.
+type GCSStore struct {
+ // Specifies the GCS bucket that uploads will be stored in
+ Bucket string
+
+ // Service specifies an interface used to communicate with the Google
+ // cloud storage backend. Implementation can be seen in gcsservice file.
+ Service GCSAPI
+}
+
+// New constructs a new GCS storage backend using the supplied GCS bucket name
+// and service object.
+func New(bucket string, service GCSAPI) GCSStore {
+ return GCSStore{
+ Bucket: bucket,
+ Service: service,
+ }
+}
+
+func (store GCSStore) UseIn(composer *tusd.StoreComposer) {
+ composer.UseCore(store)
+ composer.UseTerminater(store)
+ composer.UseFinisher(store)
+ composer.UseGetReader(store)
+}
+
+func (store GCSStore) NewUpload(info tusd.FileInfo) (id string, err error) {
+ if info.ID == "" {
+ info.ID = uid.Uid()
+ }
+
+ err = store.writeInfo(info.ID, info)
+ if err != nil {
+ return info.ID, err
+ }
+
+ return info.ID, nil
+}
+
+func (store GCSStore) WriteChunk(id string, offset int64, src io.Reader) (int64, error) {
+ prefix := fmt.Sprintf("%s_", id)
+ filterParams := GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: prefix,
+ }
+
+ names, err := store.Service.FilterObjects(filterParams)
+ if err != nil {
+ return 0, err
+ }
+
+ maxIdx := -1
+
+ for _, name := range names {
+ split := strings.Split(name, "_")
+ idx, err := strconv.Atoi(split[len(split)-1])
+ if err != nil {
+ return 0, err
+ }
+
+ if idx > maxIdx {
+ maxIdx = idx
+ }
+ }
+
+ cid := fmt.Sprintf("%s_%d", id, maxIdx+1)
+ objectParams := GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: cid,
+ }
+
+ n, err := store.Service.WriteObject(objectParams, src)
+ if err != nil {
+ return 0, err
+ }
+
+ return n, err
+}
+
+func (store GCSStore) GetInfo(id string) (tusd.FileInfo, error) {
+ info := tusd.FileInfo{}
+ i := fmt.Sprintf("%s.info", id)
+
+ params := GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: i,
+ }
+
+ r, err := store.Service.ReadObject(params)
+ if err != nil {
+ return info, err
+ }
+
+ buf := make([]byte, r.Size())
+ _, err = r.Read(buf)
+ if err != nil {
+ return info, err
+ }
+
+ if err := json.Unmarshal(buf, &info); err != nil {
+ return info, err
+ }
+
+ prefix := fmt.Sprintf("%s_", id)
+ filterParams := GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: prefix,
+ }
+
+ names, err := store.Service.FilterObjects(filterParams)
+ if err != nil {
+ return info, err
+ }
+
+ var offset int64 = 0
+ for _, name := range names {
+ params = GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: name,
+ }
+
+ size, err := store.Service.GetObjectSize(params)
+ if err != nil {
+ return info, err
+ }
+
+ offset += size
+ }
+
+ info.Offset = offset
+ err = store.writeInfo(id, info)
+ if err != nil {
+ return info, err
+ }
+
+ return info, nil
+
+}
+
+func (store GCSStore) writeInfo(id string, info tusd.FileInfo) error {
+ data, err := json.Marshal(info)
+ if err != nil {
+ return err
+ }
+
+ r := bytes.NewReader(data)
+
+ i := fmt.Sprintf("%s.info", id)
+ params := GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: i,
+ }
+
+ _, err = store.Service.WriteObject(params, r)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (store GCSStore) FinishUpload(id string) error {
+ prefix := fmt.Sprintf("%s_", id)
+ filterParams := GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: prefix,
+ }
+
+ names, err := store.Service.FilterObjects(filterParams)
+ if err != nil {
+ return err
+ }
+
+ composeParams := GCSComposeParams{
+ Bucket: store.Bucket,
+ Destination: id,
+ Sources: names,
+ }
+
+ err = store.Service.ComposeObjects(composeParams)
+ if err != nil {
+ return err
+ }
+
+ err = store.Service.DeleteObjectsWithFilter(filterParams)
+ if err != nil {
+ return err
+ }
+
+ info, err := store.GetInfo(id)
+ if err != nil {
+ return err
+ }
+
+ objectParams := GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: id,
+ }
+
+ err = store.Service.SetObjectMetadata(objectParams, info.MetaData)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (store GCSStore) Terminate(id string) error {
+ filterParams := GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: id,
+ }
+
+ err := store.Service.DeleteObjectsWithFilter(filterParams)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (store GCSStore) GetReader(id string) (io.Reader, error) {
+ params := GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: id,
+ }
+
+ r, err := store.Service.ReadObject(params)
+ if err != nil {
+ return nil, err
+ }
+
+ return r, nil
+}
diff --git a/gcsstore/gcsstore_mock_test.go b/gcsstore/gcsstore_mock_test.go
new file mode 100644
index 0000000..74549ff
--- /dev/null
+++ b/gcsstore/gcsstore_mock_test.go
@@ -0,0 +1,187 @@
+// Automatically generated by MockGen. DO NOT EDIT!
+// Source: github.com/tus/tusd/gcsstore (interfaces: GCSReader,GCSAPI)
+
+package gcsstore_test
+
+import (
+ gomock "github.com/golang/mock/gomock"
+ gcsstore "github.com/tus/tusd/gcsstore"
+ io "io"
+)
+
+// Mock of GCSReader interface
+type MockGCSReader struct {
+ ctrl *gomock.Controller
+ recorder *_MockGCSReaderRecorder
+}
+
+// Recorder for MockGCSReader (not exported)
+type _MockGCSReaderRecorder struct {
+ mock *MockGCSReader
+}
+
+func NewMockGCSReader(ctrl *gomock.Controller) *MockGCSReader {
+ mock := &MockGCSReader{ctrl: ctrl}
+ mock.recorder = &_MockGCSReaderRecorder{mock}
+ return mock
+}
+
+func (_m *MockGCSReader) EXPECT() *_MockGCSReaderRecorder {
+ return _m.recorder
+}
+
+func (_m *MockGCSReader) Close() error {
+ ret := _m.ctrl.Call(_m, "Close")
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockGCSReaderRecorder) Close() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "Close")
+}
+
+func (_m *MockGCSReader) ContentType() string {
+ ret := _m.ctrl.Call(_m, "ContentType")
+ ret0, _ := ret[0].(string)
+ return ret0
+}
+
+func (_mr *_MockGCSReaderRecorder) ContentType() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ContentType")
+}
+
+func (_m *MockGCSReader) Read(_param0 []byte) (int, error) {
+ ret := _m.ctrl.Call(_m, "Read", _param0)
+ ret0, _ := ret[0].(int)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockGCSReaderRecorder) Read(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "Read", arg0)
+}
+
+func (_m *MockGCSReader) Remain() int64 {
+ ret := _m.ctrl.Call(_m, "Remain")
+ ret0, _ := ret[0].(int64)
+ return ret0
+}
+
+func (_mr *_MockGCSReaderRecorder) Remain() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "Remain")
+}
+
+func (_m *MockGCSReader) Size() int64 {
+ ret := _m.ctrl.Call(_m, "Size")
+ ret0, _ := ret[0].(int64)
+ return ret0
+}
+
+func (_mr *_MockGCSReaderRecorder) Size() *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "Size")
+}
+
+// Mock of GCSAPI interface
+type MockGCSAPI struct {
+ ctrl *gomock.Controller
+ recorder *_MockGCSAPIRecorder
+}
+
+// Recorder for MockGCSAPI (not exported)
+type _MockGCSAPIRecorder struct {
+ mock *MockGCSAPI
+}
+
+func NewMockGCSAPI(ctrl *gomock.Controller) *MockGCSAPI {
+ mock := &MockGCSAPI{ctrl: ctrl}
+ mock.recorder = &_MockGCSAPIRecorder{mock}
+ return mock
+}
+
+func (_m *MockGCSAPI) EXPECT() *_MockGCSAPIRecorder {
+ return _m.recorder
+}
+
+func (_m *MockGCSAPI) ComposeObjects(_param0 gcsstore.GCSComposeParams) error {
+ ret := _m.ctrl.Call(_m, "ComposeObjects", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockGCSAPIRecorder) ComposeObjects(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ComposeObjects", arg0)
+}
+
+func (_m *MockGCSAPI) DeleteObject(_param0 gcsstore.GCSObjectParams) error {
+ ret := _m.ctrl.Call(_m, "DeleteObject", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockGCSAPIRecorder) DeleteObject(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "DeleteObject", arg0)
+}
+
+func (_m *MockGCSAPI) DeleteObjectsWithFilter(_param0 gcsstore.GCSFilterParams) error {
+ ret := _m.ctrl.Call(_m, "DeleteObjectsWithFilter", _param0)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockGCSAPIRecorder) DeleteObjectsWithFilter(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "DeleteObjectsWithFilter", arg0)
+}
+
+func (_m *MockGCSAPI) FilterObjects(_param0 gcsstore.GCSFilterParams) ([]string, error) {
+ ret := _m.ctrl.Call(_m, "FilterObjects", _param0)
+ ret0, _ := ret[0].([]string)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockGCSAPIRecorder) FilterObjects(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "FilterObjects", arg0)
+}
+
+func (_m *MockGCSAPI) GetObjectSize(_param0 gcsstore.GCSObjectParams) (int64, error) {
+ ret := _m.ctrl.Call(_m, "GetObjectSize", _param0)
+ ret0, _ := ret[0].(int64)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockGCSAPIRecorder) GetObjectSize(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "GetObjectSize", arg0)
+}
+
+func (_m *MockGCSAPI) ReadObject(_param0 gcsstore.GCSObjectParams) (gcsstore.GCSReader, error) {
+ ret := _m.ctrl.Call(_m, "ReadObject", _param0)
+ ret0, _ := ret[0].(gcsstore.GCSReader)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockGCSAPIRecorder) ReadObject(arg0 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadObject", arg0)
+}
+
+func (_m *MockGCSAPI) SetObjectMetadata(_param0 gcsstore.GCSObjectParams, _param1 map[string]string) error {
+ ret := _m.ctrl.Call(_m, "SetObjectMetadata", _param0, _param1)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+func (_mr *_MockGCSAPIRecorder) SetObjectMetadata(arg0, arg1 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "SetObjectMetadata", arg0, arg1)
+}
+
+func (_m *MockGCSAPI) WriteObject(_param0 gcsstore.GCSObjectParams, _param1 io.Reader) (int64, error) {
+ ret := _m.ctrl.Call(_m, "WriteObject", _param0, _param1)
+ ret0, _ := ret[0].(int64)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+func (_mr *_MockGCSAPIRecorder) WriteObject(arg0, arg1 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteObject", arg0, arg1)
+}
diff --git a/gcsstore/gcsstore_test.go b/gcsstore/gcsstore_test.go
new file mode 100644
index 0000000..b0293fc
--- /dev/null
+++ b/gcsstore/gcsstore_test.go
@@ -0,0 +1,365 @@
+package gcsstore_test
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "testing"
+
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/assert"
+
+ "github.com/tus/tusd"
+ "github.com/tus/tusd/gcsstore"
+)
+
+// go:generate mockgen -destination=./gcsstore_mock_test.go -package=gcsstore_test github.com/tus/tusd/gcsstore GCSReader,GCSAPI
+
+const mockID = "123456789abcdefghijklmnopqrstuvwxyz"
+const mockBucket = "bucket"
+const mockSize = 1337
+const mockReaderData = "helloworld"
+
+var mockTusdInfoJson = fmt.Sprintf(`{"ID":"%s","Size":%d,"MetaData":{"foo":"bar"}}`, mockID, mockSize)
+var mockTusdInfo = tusd.FileInfo{
+ ID: mockID,
+ Size: mockSize,
+ MetaData: map[string]string{
+ "foo": "bar",
+ },
+}
+
+var mockPartial0 = fmt.Sprintf("%s_0", mockID)
+var mockPartial1 = fmt.Sprintf("%s_1", mockID)
+var mockPartial2 = fmt.Sprintf("%s_2", mockID)
+var mockPartials = []string{mockPartial0, mockPartial1, mockPartial2}
+
+func TestNewUpload(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ service := NewMockGCSAPI(mockCtrl)
+ store := gcsstore.New(mockBucket, service)
+
+ assert.Equal(store.Bucket, mockBucket)
+
+ data, err := json.Marshal(mockTusdInfo)
+ assert.Nil(err)
+
+ r := bytes.NewReader(data)
+
+ params := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: fmt.Sprintf("%s.info", mockID),
+ }
+
+ service.EXPECT().WriteObject(params, r).Return(int64(r.Len()), nil)
+
+ id, err := store.NewUpload(mockTusdInfo)
+ assert.Nil(err)
+ assert.Equal(id, mockID)
+}
+
+type MockGetInfoReader struct{}
+
+func (r MockGetInfoReader) Close() error {
+ return nil
+}
+
+func (r MockGetInfoReader) ContentType() string {
+ return "text/plain; charset=utf-8"
+}
+
+func (r MockGetInfoReader) Read(p []byte) (int, error) {
+ copy(p, mockTusdInfoJson)
+ return len(p), nil
+}
+
+func (r MockGetInfoReader) Remain() int64 {
+ return int64(len(mockTusdInfoJson))
+}
+
+func (r MockGetInfoReader) Size() int64 {
+ return int64(len(mockTusdInfoJson))
+}
+
+func TestGetInfo(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ service := NewMockGCSAPI(mockCtrl)
+ store := gcsstore.New(mockBucket, service)
+
+ assert.Equal(store.Bucket, mockBucket)
+
+ params := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: fmt.Sprintf("%s.info", mockID),
+ }
+
+ r := MockGetInfoReader{}
+
+ filterParams := gcsstore.GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: fmt.Sprintf("%s_", mockID),
+ }
+
+ mockObjectParams0 := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockPartial0,
+ }
+
+ mockObjectParams1 := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockPartial1,
+ }
+
+ mockObjectParams2 := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockPartial2,
+ }
+
+ var size int64 = 100
+
+ mockTusdInfo.Offset = 300
+ offsetInfoData, err := json.Marshal(mockTusdInfo)
+ assert.Nil(err)
+
+ infoR := bytes.NewReader(offsetInfoData)
+
+ gomock.InOrder(
+ service.EXPECT().ReadObject(params).Return(r, nil),
+ service.EXPECT().FilterObjects(filterParams).Return(mockPartials, nil),
+ service.EXPECT().GetObjectSize(mockObjectParams0).Return(size, nil),
+ service.EXPECT().GetObjectSize(mockObjectParams1).Return(size, nil),
+ service.EXPECT().GetObjectSize(mockObjectParams2).Return(size, nil),
+ service.EXPECT().WriteObject(params, infoR).Return(int64(len(offsetInfoData)), nil),
+ )
+
+ info, err := store.GetInfo(mockID)
+ assert.Nil(err)
+ assert.Equal(mockTusdInfo, info)
+}
+
+type MockGetReader struct{}
+
+func (r MockGetReader) Close() error {
+ return nil
+}
+
+func (r MockGetReader) ContentType() string {
+ return "text/plain; charset=utf-8"
+}
+
+func (r MockGetReader) Read(p []byte) (int, error) {
+ copy(p, mockReaderData)
+ return len(p), nil
+}
+
+func (r MockGetReader) Remain() int64 {
+ return int64(len(mockReaderData))
+}
+
+func (r MockGetReader) Size() int64 {
+ return int64(len(mockReaderData))
+}
+
+func TestGetReader(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ service := NewMockGCSAPI(mockCtrl)
+ store := gcsstore.New(mockBucket, service)
+
+ assert.Equal(store.Bucket, mockBucket)
+
+ params := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockID,
+ }
+
+ r := MockGetReader{}
+
+ service.EXPECT().ReadObject(params).Return(r, nil)
+ reader, err := store.GetReader(mockID)
+ assert.Nil(err)
+
+ buf := make([]byte, len(mockReaderData))
+ _, err = reader.Read(buf)
+
+ assert.Nil(err)
+ assert.Equal(mockReaderData, string(buf[:]))
+}
+
+func TestTerminate(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ service := NewMockGCSAPI(mockCtrl)
+ store := gcsstore.New(mockBucket, service)
+
+ assert.Equal(store.Bucket, mockBucket)
+
+ filterParams := gcsstore.GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: mockID,
+ }
+
+ service.EXPECT().DeleteObjectsWithFilter(filterParams).Return(nil)
+
+ err := store.Terminate(mockID)
+ assert.Nil(err)
+}
+
+func TestFinishUpload(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ service := NewMockGCSAPI(mockCtrl)
+ store := gcsstore.New(mockBucket, service)
+
+ assert.Equal(store.Bucket, mockBucket)
+
+ filterParams := gcsstore.GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: fmt.Sprintf("%s_", mockID),
+ }
+
+ composeParams := gcsstore.GCSComposeParams{
+ Bucket: store.Bucket,
+ Destination: mockID,
+ Sources: mockPartials,
+ }
+
+ infoParams := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: fmt.Sprintf("%s.info", mockID),
+ }
+
+ r := MockGetInfoReader{}
+
+ mockObjectParams0 := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockPartial0,
+ }
+
+ mockObjectParams1 := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockPartial1,
+ }
+
+ mockObjectParams2 := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockPartial2,
+ }
+
+ var size int64 = 100
+
+ mockTusdInfo.Offset = 300
+ offsetInfoData, err := json.Marshal(mockTusdInfo)
+ assert.Nil(err)
+
+ infoR := bytes.NewReader(offsetInfoData)
+
+ objectParams := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockID,
+ }
+
+ metadata := map[string]string{
+ "foo": "bar",
+ }
+
+ gomock.InOrder(
+ service.EXPECT().FilterObjects(filterParams).Return(mockPartials, nil),
+ service.EXPECT().ComposeObjects(composeParams).Return(nil),
+ service.EXPECT().DeleteObjectsWithFilter(filterParams).Return(nil),
+ service.EXPECT().ReadObject(infoParams).Return(r, nil),
+ service.EXPECT().FilterObjects(filterParams).Return(mockPartials, nil),
+ service.EXPECT().GetObjectSize(mockObjectParams0).Return(size, nil),
+ service.EXPECT().GetObjectSize(mockObjectParams1).Return(size, nil),
+ service.EXPECT().GetObjectSize(mockObjectParams2).Return(size, nil),
+ service.EXPECT().WriteObject(infoParams, infoR).Return(int64(len(offsetInfoData)), nil),
+ service.EXPECT().SetObjectMetadata(objectParams, metadata).Return(nil),
+ )
+
+ err = store.FinishUpload(mockID)
+ assert.Nil(err)
+}
+
+var mockTusdChunk0InfoJson = fmt.Sprintf(`{"ID":"%s","Size":%d,"Offset":%d,"MetaData":{"foo":"bar"}}`, mockID, mockSize, mockSize/3)
+var mockTusdChunk1Info = tusd.FileInfo{
+ ID: mockID,
+ Size: mockSize,
+ Offset: 455,
+ MetaData: map[string]string{
+ "foo": "bar",
+ },
+}
+
+type MockWriteChunkReader struct{}
+
+func (r MockWriteChunkReader) Close() error {
+ return nil
+}
+
+func (r MockWriteChunkReader) ContentType() string {
+ return "text/plain; charset=utf-8"
+}
+
+func (r MockWriteChunkReader) Read(p []byte) (int, error) {
+ copy(p, mockTusdChunk0InfoJson)
+ return len(p), nil
+}
+
+func (r MockWriteChunkReader) Remain() int64 {
+ return int64(len(mockTusdChunk0InfoJson))
+}
+
+func (r MockWriteChunkReader) Size() int64 {
+ return int64(len(mockTusdChunk0InfoJson))
+}
+
+func TestWriteChunk(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ service := NewMockGCSAPI(mockCtrl)
+ store := gcsstore.New(mockBucket, service)
+
+ assert.Equal(store.Bucket, mockBucket)
+
+ // filter objects
+ filterParams := gcsstore.GCSFilterParams{
+ Bucket: store.Bucket,
+ Prefix: fmt.Sprintf("%s_", mockID),
+ }
+
+ var partials = []string{mockPartial0}
+
+ // write object
+ writeObjectParams := gcsstore.GCSObjectParams{
+ Bucket: store.Bucket,
+ ID: mockPartial1,
+ }
+
+ rGet := bytes.NewReader([]byte(mockReaderData))
+
+ gomock.InOrder(
+ service.EXPECT().FilterObjects(filterParams).Return(partials, nil),
+ service.EXPECT().WriteObject(writeObjectParams, rGet).Return(int64(len(mockReaderData)), nil),
+ )
+
+ reader := bytes.NewReader([]byte(mockReaderData))
+ var offset int64
+ offset = mockSize / 3
+ _, err := store.WriteChunk(mockID, offset, reader)
+ assert.Nil(err)
+
+}
diff --git a/metrics.go b/metrics.go
index 3639f23..b52f7bf 100644
--- a/metrics.go
+++ b/metrics.go
@@ -2,7 +2,6 @@ package tusd
import (
"errors"
- "net"
"sync"
"sync/atomic"
)
@@ -88,18 +87,8 @@ type simpleHTTPError struct {
}
func simplifyHTTPError(err HTTPError) simpleHTTPError {
- var msg string
- // Errors for read timeouts contain too much information which is not
- // necessary for us and makes grouping for the metrics harder. The error
- // message looks like: read tcp 127.0.0.1:1080->127.0.0.1:53673: i/o timeout
- // Therefore, we use a common error message for all of them.
- if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
- msg = "read tcp: i/o timeout"
- } else {
- msg = err.Error()
- }
return simpleHTTPError{
- Message: msg,
+ Message: err.Error(),
StatusCode: err.StatusCode(),
}
}
diff --git a/post_test.go b/post_test.go
index 605ad7c..b7ffcc7 100644
--- a/post_test.go
+++ b/post_test.go
@@ -7,6 +7,7 @@ import (
"testing"
"github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/assert"
. "github.com/tus/tusd"
)
@@ -22,10 +23,14 @@ func TestPost(t *testing.T) {
}).Return("foo", nil)
handler, _ := NewHandler(Config{
- DataStore: store,
- BasePath: "https://buy.art/files/",
+ DataStore: store,
+ BasePath: "https://buy.art/files/",
+ NotifyCreatedUploads: true,
})
+ c := make(chan FileInfo, 1)
+ handler.CreatedUploads = c
+
(&httpTest{
Method: "POST",
ReqHeader: map[string]string{
@@ -39,6 +44,12 @@ func TestPost(t *testing.T) {
"Location": "https://buy.art/files/foo",
},
}).Run(handler, t)
+
+ info := <-c
+
+ a := assert.New(t)
+ a.Equal("foo", info.ID)
+ a.Equal(int64(300), info.Size)
})
SubTest(t, "CreateExceedingMaxSizeFail", func(t *testing.T, store *MockFullDataStore) {
diff --git a/prometheuscollector/prometheuscollector.go b/prometheuscollector/prometheuscollector.go
index 8486f23..cfc4a0b 100644
--- a/prometheuscollector/prometheuscollector.go
+++ b/prometheuscollector/prometheuscollector.go
@@ -68,7 +68,7 @@ func (c Collector) Collect(metrics chan<- prometheus.Metric) {
for method, valuePtr := range c.metrics.RequestsTotal {
metrics <- prometheus.MustNewConstMetric(
requestsTotalDesc,
- prometheus.GaugeValue,
+ prometheus.CounterValue,
float64(atomic.LoadUint64(valuePtr)),
method,
)
@@ -77,7 +77,7 @@ func (c Collector) Collect(metrics chan<- prometheus.Metric) {
for httpError, valuePtr := range c.metrics.ErrorsTotal.Load() {
metrics <- prometheus.MustNewConstMetric(
errorsTotalDesc,
- prometheus.GaugeValue,
+ prometheus.CounterValue,
float64(atomic.LoadUint64(valuePtr)),
strconv.Itoa(httpError.StatusCode()),
httpError.Error(),
diff --git a/s3store/calcpartsize_test.go b/s3store/calcpartsize_test.go
new file mode 100644
index 0000000..4b0f9d7
--- /dev/null
+++ b/s3store/calcpartsize_test.go
@@ -0,0 +1,165 @@
+package s3store
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/assert"
+)
+
+const enableTestDebugOutput = false
+
+func assertCalculatedPartSize(store S3Store, assert *assert.Assertions, size int64) {
+ optimalPartSize, err := store.calcOptimalPartSize(size)
+ assert.Nil(err, "Size %d, no error should be returned.\n", size)
+
+ // Number of parts with the same size
+ equalparts := size / optimalPartSize
+ // Size of the last part (or 0 if no spare part is needed)
+ lastpartSize := size % optimalPartSize
+
+ prelude := fmt.Sprintf("Size %d, %d parts of size %d, lastpart %d: ", size, equalparts, optimalPartSize, lastpartSize)
+
+ assert.False(optimalPartSize < store.MinPartSize, prelude+"optimalPartSize < MinPartSize %d.\n", store.MinPartSize)
+ assert.False(optimalPartSize > store.MaxPartSize, prelude+"optimalPartSize > MaxPartSize %d.\n", store.MaxPartSize)
+ assert.False(lastpartSize == 0 && equalparts > store.MaxMultipartParts, prelude+"more parts than MaxMultipartParts %d.\n", store.MaxMultipartParts)
+ assert.False(lastpartSize > 0 && equalparts > store.MaxMultipartParts-1, prelude+"more parts than MaxMultipartParts %d.\n", store.MaxMultipartParts)
+ assert.False(lastpartSize > store.MaxPartSize, prelude+"lastpart > MaxPartSize %d.\n", store.MaxPartSize)
+ assert.False(lastpartSize > optimalPartSize, prelude+"lastpart > optimalPartSize %d.\n", optimalPartSize)
+ assert.True(size <= optimalPartSize*store.MaxMultipartParts, prelude+"upload does not fit in %d parts.\n", store.MaxMultipartParts)
+
+ if enableTestDebugOutput {
+ fmt.Printf(prelude+"does exceed MaxObjectSize: %t.\n", size > store.MaxObjectSize)
+ }
+}
+
+func TestCalcOptimalPartSize(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ s3obj := NewMockS3API(mockCtrl)
+ store := New("bucket", s3obj)
+
+ // If you quickly want to override the default values in this test
+ /*
+ store.MinPartSize = 2
+ store.MaxPartSize = 10
+ store.MaxMultipartParts = 20
+ store.MaxObjectSize = 200
+ */
+
+ // sanity check
+ if store.MaxObjectSize > store.MaxPartSize*store.MaxMultipartParts {
+ t.Errorf("MaxObjectSize %v can never be achieved, as MaxMultipartParts %v and MaxPartSize %v only allow for an upload of %v bytes total.\n", store.MaxObjectSize, store.MaxMultipartParts, store.MaxPartSize, store.MaxMultipartParts*store.MaxPartSize)
+ }
+
+ HighestApplicablePartSize := store.MaxObjectSize / store.MaxMultipartParts
+ if store.MaxObjectSize%store.MaxMultipartParts > 0 {
+ HighestApplicablePartSize++
+ }
+ RemainderWithHighestApplicablePartSize := store.MaxObjectSize % HighestApplicablePartSize
+
+ // some of these tests are actually duplicates, as they specify the same size
+ // in bytes - two ways to describe the same thing. That is wanted, in order
+ // to provide a full picture from any angle.
+ testcases := []int64{
+ 0,
+ 1,
+ store.MinPartSize - 1,
+ store.MinPartSize,
+ store.MinPartSize + 1,
+
+ store.MinPartSize*(store.MaxMultipartParts-1) - 1,
+ store.MinPartSize * (store.MaxMultipartParts - 1),
+ store.MinPartSize*(store.MaxMultipartParts-1) + 1,
+
+ store.MinPartSize*store.MaxMultipartParts - 1,
+ store.MinPartSize * store.MaxMultipartParts,
+ store.MinPartSize*store.MaxMultipartParts + 1,
+
+ store.MinPartSize*(store.MaxMultipartParts+1) - 1,
+ store.MinPartSize * (store.MaxMultipartParts + 1),
+ store.MinPartSize*(store.MaxMultipartParts+1) + 1,
+
+ (HighestApplicablePartSize-1)*store.MaxMultipartParts - 1,
+ (HighestApplicablePartSize - 1) * store.MaxMultipartParts,
+ (HighestApplicablePartSize-1)*store.MaxMultipartParts + 1,
+
+ HighestApplicablePartSize*(store.MaxMultipartParts-1) - 1,
+ HighestApplicablePartSize * (store.MaxMultipartParts - 1),
+ HighestApplicablePartSize*(store.MaxMultipartParts-1) + 1,
+
+ HighestApplicablePartSize*(store.MaxMultipartParts-1) + RemainderWithHighestApplicablePartSize - 1,
+ HighestApplicablePartSize*(store.MaxMultipartParts-1) + RemainderWithHighestApplicablePartSize,
+ HighestApplicablePartSize*(store.MaxMultipartParts-1) + RemainderWithHighestApplicablePartSize + 1,
+
+ store.MaxObjectSize - 1,
+ store.MaxObjectSize,
+ store.MaxObjectSize + 1,
+
+ (store.MaxObjectSize/store.MaxMultipartParts)*(store.MaxMultipartParts-1) - 1,
+ (store.MaxObjectSize / store.MaxMultipartParts) * (store.MaxMultipartParts - 1),
+ (store.MaxObjectSize/store.MaxMultipartParts)*(store.MaxMultipartParts-1) + 1,
+
+ store.MaxPartSize*(store.MaxMultipartParts-1) - 1,
+ store.MaxPartSize * (store.MaxMultipartParts - 1),
+ store.MaxPartSize*(store.MaxMultipartParts-1) + 1,
+
+ store.MaxPartSize*store.MaxMultipartParts - 1,
+ store.MaxPartSize * store.MaxMultipartParts,
+ // We cannot calculate a part size for store.MaxPartSize*store.MaxMultipartParts + 1
+ // This case is tested in TestCalcOptimalPartSize_ExceedingMaxPartSize
+ }
+
+ for _, size := range testcases {
+ assertCalculatedPartSize(store, assert, size)
+ }
+
+ if enableTestDebugOutput {
+ fmt.Println("HighestApplicablePartSize", HighestApplicablePartSize)
+ fmt.Println("RemainderWithHighestApplicablePartSize", RemainderWithHighestApplicablePartSize)
+ }
+}
+
+func TestCalcOptimalPartSize_AllUploadSizes(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ s3obj := NewMockS3API(mockCtrl)
+ store := New("bucket", s3obj)
+
+ store.MinPartSize = 5
+ store.MaxPartSize = 5 * 1024
+ store.MaxMultipartParts = 1000
+ store.MaxObjectSize = store.MaxPartSize * store.MaxMultipartParts
+
+ // sanity check
+ if store.MaxObjectSize > store.MaxPartSize*store.MaxMultipartParts {
+ t.Errorf("MaxObjectSize %v can never be achieved, as MaxMultipartParts %v and MaxPartSize %v only allow for an upload of %v bytes total.\n", store.MaxObjectSize, store.MaxMultipartParts, store.MaxPartSize, store.MaxMultipartParts*store.MaxPartSize)
+ }
+
+ for size := int64(0); size <= store.MaxObjectSize; size++ {
+ assertCalculatedPartSize(store, assert, size)
+ }
+}
+
+func TestCalcOptimalPartSize_ExceedingMaxPartSize(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ s3obj := NewMockS3API(mockCtrl)
+ store := New("bucket", s3obj)
+
+ size := store.MaxPartSize*store.MaxMultipartParts + 1
+
+ optimalPartSize, err := store.calcOptimalPartSize(size)
+ assert.NotNil(err)
+ assert.EqualError(err, fmt.Sprintf("calcOptimalPartSize: to upload %v bytes optimalPartSize %v must exceed MaxPartSize %v", size, optimalPartSize, store.MaxPartSize))
+}
diff --git a/s3store/s3store.go b/s3store/s3store.go
index 2f4c269..3b9465e 100644
--- a/s3store/s3store.go
+++ b/s3store/s3store.go
@@ -128,6 +128,13 @@ type S3Store struct {
// in bytes. This number needs to match with the underlying S3 backend or else
// uploaded parts will be reject. AWS S3, for example, uses 5MB for this value.
MinPartSize int64
+ // MaxMultipartParts is the maximum number of parts an S3 multipart upload is
+ // allowed to have according to AWS S3 API specifications.
+ // See: http://docs.aws.amazon.com/AmazonS3/latest/dev/qfacts.html
+ MaxMultipartParts int64
+ // MaxObjectSize is the maximum size an S3 Object can have according to S3
+ // API specifications. See link above.
+ MaxObjectSize int64
}
type S3API interface {
@@ -146,10 +153,12 @@ type S3API interface {
// The MaxPartSize and MinPartSize properties are set to 6 and 5MB.
func New(bucket string, service S3API) S3Store {
return S3Store{
- Bucket: bucket,
- Service: service,
- MaxPartSize: 6 * 1024 * 1024,
- MinPartSize: 5 * 1024 * 1024,
+ Bucket: bucket,
+ Service: service,
+ MaxPartSize: 5 * 1024 * 1024 * 1024,
+ MinPartSize: 5 * 1024 * 1024,
+ MaxMultipartParts: 10000,
+ MaxObjectSize: 5 * 1024 * 1024 * 1024 * 1024,
}
}
@@ -164,29 +173,19 @@ func (store S3Store) UseIn(composer *tusd.StoreComposer) {
}
func (store S3Store) NewUpload(info tusd.FileInfo) (id string, err error) {
+ // an upload larger than MaxObjectSize must throw an error
+ if info.Size > store.MaxObjectSize {
+ return "", fmt.Errorf("s3store: upload size of %v bytes exceeds MaxObjectSize of %v bytes", info.Size, store.MaxObjectSize)
+ }
+
var uploadId string
if info.ID == "" {
uploadId = uid.Uid()
} else {
+ // certain tests set info.ID in advance
uploadId = info.ID
}
- infoJson, err := json.Marshal(info)
- if err != nil {
- return "", err
- }
-
- // Create object on S3 containing information about the file
- _, err = store.Service.PutObject(&s3.PutObjectInput{
- Bucket: aws.String(store.Bucket),
- Key: aws.String(uploadId + ".info"),
- Body: bytes.NewReader(infoJson),
- ContentLength: aws.Int64(int64(len(infoJson))),
- })
- if err != nil {
- return "", fmt.Errorf("s3store: unable to create info file:\n%s", err)
- }
-
// Convert meta data into a map of pointers for AWS Go SDK, sigh.
metadata := make(map[string]*string, len(info.MetaData))
for key, value := range info.MetaData {
@@ -207,8 +206,25 @@ func (store S3Store) NewUpload(info tusd.FileInfo) (id string, err error) {
}
id = uploadId + "+" + *res.UploadId
+ info.ID = id
- return
+ infoJson, err := json.Marshal(info)
+ if err != nil {
+ return "", err
+ }
+
+ // Create object on S3 containing information about the file
+ _, err = store.Service.PutObject(&s3.PutObjectInput{
+ Bucket: aws.String(store.Bucket),
+ Key: aws.String(uploadId + ".info"),
+ Body: bytes.NewReader(infoJson),
+ ContentLength: aws.Int64(int64(len(infoJson))),
+ })
+ if err != nil {
+ return "", fmt.Errorf("s3store: unable to create info file:\n%s", err)
+ }
+
+ return id, nil
}
func (store S3Store) WriteChunk(id string, offset int64, src io.Reader) (int64, error) {
@@ -222,19 +238,18 @@ func (store S3Store) WriteChunk(id string, offset int64, src io.Reader) (int64,
size := info.Size
bytesUploaded := int64(0)
+ optimalPartSize, err := store.calcOptimalPartSize(size)
+ if err != nil {
+ return bytesUploaded, err
+ }
// Get number of parts to generate next number
- listPtr, err := store.Service.ListParts(&s3.ListPartsInput{
- Bucket: aws.String(store.Bucket),
- Key: aws.String(uploadId),
- UploadId: aws.String(multipartId),
- })
+ parts, err := store.listAllParts(id)
if err != nil {
return 0, err
}
- list := *listPtr
- numParts := len(list.Parts)
+ numParts := len(parts)
nextPartNum := int64(numParts + 1)
for {
@@ -246,17 +261,22 @@ func (store S3Store) WriteChunk(id string, offset int64, src io.Reader) (int64,
defer os.Remove(file.Name())
defer file.Close()
- limitedReader := io.LimitReader(src, store.MaxPartSize)
+ limitedReader := io.LimitReader(src, optimalPartSize)
n, err := io.Copy(file, limitedReader)
- if err != nil && err != io.EOF {
+ // io.Copy does not return io.EOF, so we not have to handle it differently.
+ if err != nil {
return bytesUploaded, err
}
+ // If io.Copy is finished reading, it will always return (0, nil).
+ if n == 0 {
+ return bytesUploaded, nil
+ }
- if (size - offset) <= store.MinPartSize {
+ if (size - offset) <= optimalPartSize {
if (size - offset) != n {
return bytesUploaded, nil
}
- } else if n < store.MinPartSize {
+ } else if n < optimalPartSize {
return bytesUploaded, nil
}
@@ -274,14 +294,14 @@ func (store S3Store) WriteChunk(id string, offset int64, src io.Reader) (int64,
return bytesUploaded, err
}
- offset += bytesUploaded
+ offset += n
bytesUploaded += n
nextPartNum += 1
}
}
func (store S3Store) GetInfo(id string) (info tusd.FileInfo, err error) {
- uploadId, multipartId := splitIds(id)
+ uploadId, _ := splitIds(id)
// Get file info stored in separate object
res, err := store.Service.GetObject(&s3.GetObjectInput{
@@ -300,17 +320,8 @@ func (store S3Store) GetInfo(id string) (info tusd.FileInfo, err error) {
return info, err
}
- // The JSON object stored on S3 does not contain the proper upload ID because
- // the ID has constructed after the storing happened. Therefore we set it
- // manually.
- info.ID = id
-
// Get uploaded parts and their offset
- listPtr, err := store.Service.ListParts(&s3.ListPartsInput{
- Bucket: aws.String(store.Bucket),
- Key: aws.String(uploadId),
- UploadId: aws.String(multipartId),
- })
+ parts, err := store.listAllParts(id)
if err != nil {
// Check if the error is caused by the upload not being found. This happens
// when the multipart upload has already been completed or aborted. Since
@@ -324,11 +335,9 @@ func (store S3Store) GetInfo(id string) (info tusd.FileInfo, err error) {
}
}
- list := *listPtr
-
offset := int64(0)
- for _, part := range list.Parts {
+ for _, part := range parts {
offset += *part.Size
}
@@ -442,22 +451,17 @@ func (store S3Store) FinishUpload(id string) error {
uploadId, multipartId := splitIds(id)
// Get uploaded parts
- listPtr, err := store.Service.ListParts(&s3.ListPartsInput{
- Bucket: aws.String(store.Bucket),
- Key: aws.String(uploadId),
- UploadId: aws.String(multipartId),
- })
+ parts, err := store.listAllParts(id)
if err != nil {
return err
}
// Transform the []*s3.Part slice to a []*s3.CompletedPart slice for the next
// request.
- list := *listPtr
- parts := make([]*s3.CompletedPart, len(list.Parts))
+ completedParts := make([]*s3.CompletedPart, len(parts))
- for index, part := range list.Parts {
- parts[index] = &s3.CompletedPart{
+ for index, part := range parts {
+ completedParts[index] = &s3.CompletedPart{
ETag: part.ETag,
PartNumber: part.PartNumber,
}
@@ -468,7 +472,7 @@ func (store S3Store) FinishUpload(id string) error {
Key: aws.String(uploadId),
UploadId: aws.String(multipartId),
MultipartUpload: &s3.CompletedMultipartUpload{
- Parts: parts,
+ Parts: completedParts,
},
})
@@ -515,6 +519,33 @@ func (store S3Store) ConcatUploads(dest string, partialUploads []string) error {
return store.FinishUpload(dest)
}
+func (store S3Store) listAllParts(id string) (parts []*s3.Part, err error) {
+ uploadId, multipartId := splitIds(id)
+
+ partMarker := int64(0)
+ for {
+ // Get uploaded parts
+ listPtr, err := store.Service.ListParts(&s3.ListPartsInput{
+ Bucket: aws.String(store.Bucket),
+ Key: aws.String(uploadId),
+ UploadId: aws.String(multipartId),
+ PartNumberMarker: aws.Int64(partMarker),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ parts = append(parts, (*listPtr).Parts...)
+
+ if listPtr.IsTruncated != nil && *listPtr.IsTruncated {
+ partMarker = *listPtr.NextPartNumberMarker
+ } else {
+ break
+ }
+ }
+ return parts, nil
+}
+
func splitIds(id string) (uploadId, multipartId string) {
index := strings.Index(id, "+")
if index == -1 {
@@ -534,3 +565,47 @@ func isAwsError(err error, code string) bool {
}
return false
}
+
+func (store S3Store) calcOptimalPartSize(size int64) (optimalPartSize int64, err error) {
+ switch {
+ // When upload is smaller or equal MinPartSize, we upload in just one part.
+ case size <= store.MinPartSize:
+ optimalPartSize = store.MinPartSize
+ // Does the upload fit in MaxMultipartParts parts or less with MinPartSize.
+ case size <= store.MinPartSize*store.MaxMultipartParts:
+ optimalPartSize = store.MinPartSize
+ // Prerequisite: Be aware, that the result of an integer division (x/y) is
+ // ALWAYS rounded DOWN, as there are no digits behind the comma.
+ // In order to find out, whether we have an exact result or a rounded down
+ // one, we can check, whether the remainder of that division is 0 (x%y == 0).
+ //
+ // So if the result of (size/MaxMultipartParts) is not a rounded down value,
+ // then we can use it as our optimalPartSize. But if this division produces a
+ // remainder, we have to round up the result by adding +1. Otherwise our
+ // upload would not fit into MaxMultipartParts number of parts with that
+ // size. We would need an additional part in order to upload everything.
+ // While in almost all cases, we could skip the check for the remainder and
+ // just add +1 to every result, but there is one case, where doing that would
+ // doom our upload. When (MaxObjectSize == MaxPartSize * MaxMultipartParts),
+ // by adding +1, we would end up with an optimalPartSize > MaxPartSize.
+ // With the current S3 API specifications, we will not run into this problem,
+ // but these specs are subject to change, and there are other stores as well,
+ // which are implementing the S3 API (e.g. RIAK, Ceph RadosGW), but might
+ // have different settings.
+ case size%store.MaxMultipartParts == 0:
+ optimalPartSize = size / store.MaxMultipartParts
+ // Having a remainder larger than 0 means, the float result would have
+ // digits after the comma (e.g. be something like 10.9). As a result, we can
+ // only squeeze our upload into MaxMultipartParts parts, if we rounded UP
+ // this division's result. That is what is happending here. We round up by
+ // adding +1, if the prior test for (remainder == 0) did not succeed.
+ default:
+ optimalPartSize = size/store.MaxMultipartParts + 1
+ }
+
+ // optimalPartSize must never exceed MaxPartSize
+ if optimalPartSize > store.MaxPartSize {
+ return optimalPartSize, fmt.Errorf("calcOptimalPartSize: to upload %v bytes optimalPartSize %v must exceed MaxPartSize %v", size, optimalPartSize, store.MaxPartSize)
+ }
+ return optimalPartSize, nil
+}
diff --git a/s3store/s3store_mock_test.go b/s3store/s3store_mock_test.go
index 4f75ba7..0fc2125 100644
--- a/s3store/s3store_mock_test.go
+++ b/s3store/s3store_mock_test.go
@@ -1,7 +1,7 @@
// Automatically generated by MockGen. DO NOT EDIT!
// Source: github.com/tus/tusd/s3store (interfaces: S3API)
-package s3store_test
+package s3store
import (
s3 "github.com/aws/aws-sdk-go/service/s3"
diff --git a/s3store/s3store_test.go b/s3store/s3store_test.go
index 2875e2b..f9729e0 100644
--- a/s3store/s3store_test.go
+++ b/s3store/s3store_test.go
@@ -1,7 +1,8 @@
-package s3store_test
+package s3store
import (
"bytes"
+ "fmt"
"io/ioutil"
"testing"
@@ -12,17 +13,16 @@ import (
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/tus/tusd"
- "github.com/tus/tusd/s3store"
)
-//go:generate mockgen -destination=./s3store_mock_test.go -package=s3store_test github.com/tus/tusd/s3store S3API
+//go:generate mockgen -destination=./s3store_mock_test.go -package=s3store github.com/tus/tusd/s3store S3API
// Test interface implementations
-var _ tusd.DataStore = s3store.S3Store{}
-var _ tusd.GetReaderDataStore = s3store.S3Store{}
-var _ tusd.TerminaterDataStore = s3store.S3Store{}
-var _ tusd.FinisherDataStore = s3store.S3Store{}
-var _ tusd.ConcaterDataStore = s3store.S3Store{}
+var _ tusd.DataStore = S3Store{}
+var _ tusd.GetReaderDataStore = S3Store{}
+var _ tusd.TerminaterDataStore = S3Store{}
+var _ tusd.FinisherDataStore = S3Store{}
+var _ tusd.ConcaterDataStore = S3Store{}
func TestNewUpload(t *testing.T) {
mockCtrl := gomock.NewController(t)
@@ -30,21 +30,15 @@ func TestNewUpload(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
- assert.Equal(store.Bucket, "bucket")
- assert.Equal(store.Service, s3obj)
+ assert.Equal("bucket", store.Bucket)
+ assert.Equal(s3obj, store.Service)
s1 := "hello"
s2 := "men?"
gomock.InOrder(
- s3obj.EXPECT().PutObject(&s3.PutObjectInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId.info"),
- Body: bytes.NewReader([]byte(`{"ID":"uploadId","Size":500,"Offset":0,"MetaData":{"bar":"menü","foo":"hello"},"IsPartial":false,"IsFinal":false,"PartialUploads":null}`)),
- ContentLength: aws.Int64(int64(136)),
- }),
s3obj.EXPECT().CreateMultipartUpload(&s3.CreateMultipartUploadInput{
Bucket: aws.String("bucket"),
Key: aws.String("uploadId"),
@@ -55,6 +49,12 @@ func TestNewUpload(t *testing.T) {
}).Return(&s3.CreateMultipartUploadOutput{
UploadId: aws.String("multipartId"),
}, nil),
+ s3obj.EXPECT().PutObject(&s3.PutObjectInput{
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId.info"),
+ Body: bytes.NewReader([]byte(`{"ID":"uploadId+multipartId","Size":500,"Offset":0,"MetaData":{"bar":"menü","foo":"hello"},"IsPartial":false,"IsFinal":false,"PartialUploads":null}`)),
+ ContentLength: aws.Int64(int64(148)),
+ }),
)
info := tusd.FileInfo{
@@ -68,7 +68,29 @@ func TestNewUpload(t *testing.T) {
id, err := store.NewUpload(info)
assert.Nil(err)
- assert.Equal(id, "uploadId+multipartId")
+ assert.Equal("uploadId+multipartId", id)
+}
+
+func TestNewUploadLargerMaxObjectSize(t *testing.T) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ assert := assert.New(t)
+
+ s3obj := NewMockS3API(mockCtrl)
+ store := New("bucket", s3obj)
+
+ assert.Equal("bucket", store.Bucket)
+ assert.Equal(s3obj, store.Service)
+
+ info := tusd.FileInfo{
+ ID: "uploadId",
+ Size: store.MaxObjectSize + 1,
+ }
+
+ id, err := store.NewUpload(info)
+ assert.NotNil(err)
+ assert.EqualError(err, fmt.Sprintf("s3store: upload size of %v bytes exceeds MaxObjectSize of %v bytes", info.Size, store.MaxObjectSize))
+ assert.Equal("", id)
}
func TestGetInfoNotFound(t *testing.T) {
@@ -77,7 +99,7 @@ func TestGetInfoNotFound(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
Bucket: aws.String("bucket"),
@@ -85,7 +107,7 @@ func TestGetInfoNotFound(t *testing.T) {
}).Return(nil, awserr.New("NoSuchKey", "The specified key does not exist.", nil))
_, err := store.GetInfo("uploadId+multipartId")
- assert.Equal(err, tusd.ErrNotFound)
+ assert.Equal(tusd.ErrNotFound, err)
}
func TestGetInfo(t *testing.T) {
@@ -94,19 +116,20 @@ func TestGetInfo(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
gomock.InOrder(
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
Bucket: aws.String("bucket"),
Key: aws.String("uploadId.info"),
}).Return(&s3.GetObjectOutput{
- Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"ID":"uploadId","Size":500,"Offset":0,"MetaData":{"bar":"menü","foo":"hello"},"IsPartial":false,"IsFinal":false,"PartialUploads":null}`))),
+ Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"ID":"uploadId+multipartId","Size":500,"Offset":0,"MetaData":{"bar":"menü","foo":"hello"},"IsPartial":false,"IsFinal":false,"PartialUploads":null}`))),
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -116,13 +139,27 @@ func TestGetInfo(t *testing.T) {
Size: aws.Int64(200),
},
},
+ NextPartNumberMarker: aws.Int64(2),
+ IsTruncated: aws.Bool(true),
+ }, nil),
+ s3obj.EXPECT().ListParts(&s3.ListPartsInput{
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(2),
+ }).Return(&s3.ListPartsOutput{
+ Parts: []*s3.Part{
+ {
+ Size: aws.Int64(100),
+ },
+ },
}, nil),
)
info, err := store.GetInfo("uploadId+multipartId")
assert.Nil(err)
assert.Equal(int64(500), info.Size)
- assert.Equal(int64(300), info.Offset)
+ assert.Equal(int64(400), info.Offset)
assert.Equal("uploadId+multipartId", info.ID)
assert.Equal("hello", info.MetaData["foo"])
assert.Equal("menü", info.MetaData["bar"])
@@ -134,7 +171,7 @@ func TestGetInfoFinished(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
gomock.InOrder(
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
@@ -144,9 +181,10 @@ func TestGetInfoFinished(t *testing.T) {
Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"ID":"uploadId","Size":500,"Offset":0,"MetaData":null,"IsPartial":false,"IsFinal":false,"PartialUploads":null}`))),
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(nil, awserr.New("NoSuchUpload", "The specified upload does not exist.", nil)),
)
@@ -162,7 +200,7 @@ func TestGetReader(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
Bucket: aws.String("bucket"),
@@ -173,7 +211,7 @@ func TestGetReader(t *testing.T) {
content, err := store.GetReader("uploadId+multipartId")
assert.Nil(err)
- assert.Equal(content, ioutil.NopCloser(bytes.NewReader([]byte(`hello world`))))
+ assert.Equal(ioutil.NopCloser(bytes.NewReader([]byte(`hello world`))), content)
}
func TestGetReaderNotFound(t *testing.T) {
@@ -182,7 +220,7 @@ func TestGetReaderNotFound(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
gomock.InOrder(
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
@@ -199,7 +237,7 @@ func TestGetReaderNotFound(t *testing.T) {
content, err := store.GetReader("uploadId+multipartId")
assert.Nil(content)
- assert.Equal(err, tusd.ErrNotFound)
+ assert.Equal(tusd.ErrNotFound, err)
}
func TestGetReaderNotFinished(t *testing.T) {
@@ -208,7 +246,7 @@ func TestGetReaderNotFinished(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
gomock.InOrder(
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
@@ -227,7 +265,7 @@ func TestGetReaderNotFinished(t *testing.T) {
content, err := store.GetReader("uploadId+multipartId")
assert.Nil(content)
- assert.Equal(err.Error(), "cannot stream non-finished upload")
+ assert.Equal("cannot stream non-finished upload", err.Error())
}
func TestFinishUpload(t *testing.T) {
@@ -236,13 +274,14 @@ func TestFinishUpload(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
gomock.InOrder(
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -256,6 +295,22 @@ func TestFinishUpload(t *testing.T) {
PartNumber: aws.Int64(2),
},
},
+ NextPartNumberMarker: aws.Int64(2),
+ IsTruncated: aws.Bool(true),
+ }, nil),
+ s3obj.EXPECT().ListParts(&s3.ListPartsInput{
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(2),
+ }).Return(&s3.ListPartsOutput{
+ Parts: []*s3.Part{
+ {
+ Size: aws.Int64(100),
+ ETag: aws.String("foobar"),
+ PartNumber: aws.Int64(3),
+ },
+ },
}, nil),
s3obj.EXPECT().CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
Bucket: aws.String("bucket"),
@@ -271,6 +326,10 @@ func TestFinishUpload(t *testing.T) {
ETag: aws.String("bar"),
PartNumber: aws.Int64(2),
},
+ {
+ ETag: aws.String("foobar"),
+ PartNumber: aws.Int64(3),
+ },
},
},
}).Return(nil, nil),
@@ -286,9 +345,11 @@ func TestWriteChunk(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
- store.MaxPartSize = 4
- store.MinPartSize = 2
+ store := New("bucket", s3obj)
+ store.MaxPartSize = 8
+ store.MinPartSize = 4
+ store.MaxMultipartParts = 10000
+ store.MaxObjectSize = 5 * 1024 * 1024 * 1024 * 1024
gomock.InOrder(
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
@@ -298,9 +359,10 @@ func TestWriteChunk(t *testing.T) {
Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"ID":"uploadId","Size":500,"Offset":0,"MetaData":null,"IsPartial":false,"IsFinal":false,"PartialUploads":null}`))),
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -312,9 +374,10 @@ func TestWriteChunk(t *testing.T) {
},
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -344,13 +407,15 @@ func TestWriteChunk(t *testing.T) {
Key: aws.String("uploadId"),
UploadId: aws.String("multipartId"),
PartNumber: aws.Int64(5),
- Body: bytes.NewReader([]byte("90")),
+ Body: bytes.NewReader([]byte("90AB")),
})).Return(nil, nil),
)
- bytesRead, err := store.WriteChunk("uploadId+multipartId", 300, bytes.NewReader([]byte("1234567890")))
+ // The last bytes "CD" will be ignored, as they are not the last bytes of the
+ // upload (500 bytes total) and not of full part-size.
+ bytesRead, err := store.WriteChunk("uploadId+multipartId", 300, bytes.NewReader([]byte("1234567890ABCD")))
assert.Nil(err)
- assert.Equal(int64(10), bytesRead)
+ assert.Equal(int64(12), bytesRead)
}
func TestWriteChunkDropTooSmall(t *testing.T) {
@@ -359,7 +424,7 @@ func TestWriteChunkDropTooSmall(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
gomock.InOrder(
s3obj.EXPECT().GetObject(&s3.GetObjectInput{
@@ -369,9 +434,10 @@ func TestWriteChunkDropTooSmall(t *testing.T) {
Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"ID":"uploadId","Size":500,"Offset":0,"MetaData":null,"IsPartial":false,"IsFinal":false,"PartialUploads":null}`))),
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -383,9 +449,10 @@ func TestWriteChunkDropTooSmall(t *testing.T) {
},
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -409,7 +476,7 @@ func TestWriteChunkAllowTooSmallLast(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
store.MinPartSize = 20
gomock.InOrder(
@@ -420,9 +487,10 @@ func TestWriteChunkAllowTooSmallLast(t *testing.T) {
Body: ioutil.NopCloser(bytes.NewReader([]byte(`{"ID":"uploadId","Size":500,"Offset":0,"MetaData":null,"IsPartial":false,"IsFinal":false,"PartialUploads":null}`))),
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -434,9 +502,10 @@ func TestWriteChunkAllowTooSmallLast(t *testing.T) {
},
}, nil),
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
@@ -470,7 +539,7 @@ func TestTerminate(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
// Order is not important in this situation.
s3obj.EXPECT().AbortMultipartUpload(&s3.AbortMultipartUploadInput{
@@ -504,7 +573,7 @@ func TestTerminateWithErrors(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
// Order is not important in this situation.
// NoSuchUpload errors should be ignored
@@ -547,7 +616,7 @@ func TestConcatUploads(t *testing.T) {
assert := assert.New(t)
s3obj := NewMockS3API(mockCtrl)
- store := s3store.New("bucket", s3obj)
+ store := New("bucket", s3obj)
s3obj.EXPECT().UploadPartCopy(&s3.UploadPartCopyInput{
Bucket: aws.String("bucket"),
@@ -576,9 +645,10 @@ func TestConcatUploads(t *testing.T) {
// Output from s3Store.FinishUpload
gomock.InOrder(
s3obj.EXPECT().ListParts(&s3.ListPartsInput{
- Bucket: aws.String("bucket"),
- Key: aws.String("uploadId"),
- UploadId: aws.String("multipartId"),
+ Bucket: aws.String("bucket"),
+ Key: aws.String("uploadId"),
+ UploadId: aws.String("multipartId"),
+ PartNumberMarker: aws.Int64(0),
}).Return(&s3.ListPartsOutput{
Parts: []*s3.Part{
{
diff --git a/s3store/s3store_util_test.go b/s3store/s3store_util_test.go
index dde80d5..10553d6 100644
--- a/s3store/s3store_util_test.go
+++ b/s3store/s3store_util_test.go
@@ -1,4 +1,4 @@
-package s3store_test
+package s3store
import (
"fmt"
diff --git a/unrouted_handler.go b/unrouted_handler.go
index 6fd8d9c..2285e58 100644
--- a/unrouted_handler.go
+++ b/unrouted_handler.go
@@ -5,6 +5,7 @@ import (
"errors"
"io"
"log"
+ "net"
"net/http"
"os"
"regexp"
@@ -93,6 +94,12 @@ type UnroutedHandler struct {
// happen if the NotifyUploadProgress field is set to true in the Config
// structure.
UploadProgress chan FileInfo
+ // CreatedUploads is used to send notifications about the uploads having been
+ // created. It triggers post creation and therefore has all the FileInfo incl.
+ // the ID available already. It facilitates the post-create hook. Sending to
+ // this channel will only happen if the NotifyCreatedUploads field is set to
+ // true in the Config structure.
+ CreatedUploads chan FileInfo
// Metrics provides numbers of the usage for this handler.
Metrics Metrics
}
@@ -123,6 +130,7 @@ func NewUnroutedHandler(config Config) (*UnroutedHandler, error) {
CompleteUploads: make(chan FileInfo),
TerminatedUploads: make(chan FileInfo),
UploadProgress: make(chan FileInfo),
+ CreatedUploads: make(chan FileInfo),
logger: config.Logger,
extensions: extensions,
Metrics: newMetrics(),
@@ -156,13 +164,13 @@ func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler {
if r.Method == "OPTIONS" {
// Preflight request
- header.Set("Access-Control-Allow-Methods", "POST, GET, HEAD, PATCH, DELETE, OPTIONS")
- header.Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata")
+ header.Add("Access-Control-Allow-Methods", "POST, GET, HEAD, PATCH, DELETE, OPTIONS")
+ header.Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata")
header.Set("Access-Control-Max-Age", "86400")
} else {
// Actual request
- header.Set("Access-Control-Expose-Headers", "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata")
+ header.Add("Access-Control-Expose-Headers", "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata")
}
}
@@ -283,6 +291,11 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request)
go handler.Metrics.incUploadsCreated()
handler.log("UploadCreated", "id", id, "size", i64toa(size), "url", url)
+ if handler.config.NotifyCreatedUploads {
+ info.ID = id
+ handler.CreatedUploads <- info
+ }
+
if isFinal {
if err := handler.composer.Concater.ConcatUploads(id, partialUploads); err != nil {
handler.sendError(w, r, err)
@@ -611,6 +624,14 @@ func (handler *UnroutedHandler) sendError(w http.ResponseWriter, r *http.Request
err = ErrNotFound
}
+ // Errors for read timeouts contain too much information which is not
+ // necessary for us and makes grouping for the metrics harder. The error
+ // message looks like: read tcp 127.0.0.1:1080->127.0.0.1:53673: i/o timeout
+ // Therefore, we use a common error message for all of them.
+ if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
+ err = errors.New("read tcp: i/o timeout")
+ }
+
statusErr, ok := err.(HTTPError)
if !ok {
statusErr = NewHTTPError(err, http.StatusInternalServerError)
diff --git a/vendor/cloud.google.com/go/LICENSE b/vendor/cloud.google.com/go/LICENSE
new file mode 100644
index 0000000..a4c5efd
--- /dev/null
+++ b/vendor/cloud.google.com/go/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 Google Inc.
+
+ 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.
diff --git a/vendor/cloud.google.com/go/compute/metadata/metadata.go b/vendor/cloud.google.com/go/compute/metadata/metadata.go
new file mode 100644
index 0000000..e708c03
--- /dev/null
+++ b/vendor/cloud.google.com/go/compute/metadata/metadata.go
@@ -0,0 +1,437 @@
+// Copyright 2014 Google Inc. 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.
+
+// Package metadata provides access to Google Compute Engine (GCE)
+// metadata and API service accounts.
+//
+// This package is a wrapper around the GCE metadata service,
+// as documented at https://developers.google.com/compute/docs/metadata.
+package metadata // import "cloud.google.com/go/compute/metadata"
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "runtime"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/net/context/ctxhttp"
+)
+
+const (
+ // metadataIP is the documented metadata server IP address.
+ metadataIP = "169.254.169.254"
+
+ // metadataHostEnv is the environment variable specifying the
+ // GCE metadata hostname. If empty, the default value of
+ // metadataIP ("169.254.169.254") is used instead.
+ // This is variable name is not defined by any spec, as far as
+ // I know; it was made up for the Go package.
+ metadataHostEnv = "GCE_METADATA_HOST"
+
+ userAgent = "gcloud-golang/0.1"
+)
+
+type cachedValue struct {
+ k string
+ trim bool
+ mu sync.Mutex
+ v string
+}
+
+var (
+ projID = &cachedValue{k: "project/project-id", trim: true}
+ projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
+ instID = &cachedValue{k: "instance/id", trim: true}
+)
+
+var (
+ metaClient = &http.Client{
+ Transport: &http.Transport{
+ Dial: (&net.Dialer{
+ Timeout: 2 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }).Dial,
+ ResponseHeaderTimeout: 2 * time.Second,
+ },
+ }
+ subscribeClient = &http.Client{
+ Transport: &http.Transport{
+ Dial: (&net.Dialer{
+ Timeout: 2 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }).Dial,
+ },
+ }
+)
+
+// NotDefinedError is returned when requested metadata is not defined.
+//
+// The underlying string is the suffix after "/computeMetadata/v1/".
+//
+// This error is not returned if the value is defined to be the empty
+// string.
+type NotDefinedError string
+
+func (suffix NotDefinedError) Error() string {
+ return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
+}
+
+// Get returns a value from the metadata service.
+// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
+//
+// If the GCE_METADATA_HOST environment variable is not defined, a default of
+// 169.254.169.254 will be used instead.
+//
+// If the requested metadata is not defined, the returned error will
+// be of type NotDefinedError.
+func Get(suffix string) (string, error) {
+ val, _, err := getETag(metaClient, suffix)
+ return val, err
+}
+
+// getETag returns a value from the metadata service as well as the associated
+// ETag using the provided client. This func is otherwise equivalent to Get.
+func getETag(client *http.Client, suffix string) (value, etag string, err error) {
+ // Using a fixed IP makes it very difficult to spoof the metadata service in
+ // a container, which is an important use-case for local testing of cloud
+ // deployments. To enable spoofing of the metadata service, the environment
+ // variable GCE_METADATA_HOST is first inspected to decide where metadata
+ // requests shall go.
+ host := os.Getenv(metadataHostEnv)
+ if host == "" {
+ // Using 169.254.169.254 instead of "metadata" here because Go
+ // binaries built with the "netgo" tag and without cgo won't
+ // know the search suffix for "metadata" is
+ // ".google.internal", and this IP address is documented as
+ // being stable anyway.
+ host = metadataIP
+ }
+ url := "http://" + host + "/computeMetadata/v1/" + suffix
+ req, _ := http.NewRequest("GET", url, nil)
+ req.Header.Set("Metadata-Flavor", "Google")
+ req.Header.Set("User-Agent", userAgent)
+ res, err := client.Do(req)
+ if err != nil {
+ return "", "", err
+ }
+ defer res.Body.Close()
+ if res.StatusCode == http.StatusNotFound {
+ return "", "", NotDefinedError(suffix)
+ }
+ if res.StatusCode != 200 {
+ return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return "", "", err
+ }
+ return string(all), res.Header.Get("Etag"), nil
+}
+
+func getTrimmed(suffix string) (s string, err error) {
+ s, err = Get(suffix)
+ s = strings.TrimSpace(s)
+ return
+}
+
+func (c *cachedValue) get() (v string, err error) {
+ defer c.mu.Unlock()
+ c.mu.Lock()
+ if c.v != "" {
+ return c.v, nil
+ }
+ if c.trim {
+ v, err = getTrimmed(c.k)
+ } else {
+ v, err = Get(c.k)
+ }
+ if err == nil {
+ c.v = v
+ }
+ return
+}
+
+var (
+ onGCEOnce sync.Once
+ onGCE bool
+)
+
+// OnGCE reports whether this process is running on Google Compute Engine.
+func OnGCE() bool {
+ onGCEOnce.Do(initOnGCE)
+ return onGCE
+}
+
+func initOnGCE() {
+ onGCE = testOnGCE()
+}
+
+func testOnGCE() bool {
+ // The user explicitly said they're on GCE, so trust them.
+ if os.Getenv(metadataHostEnv) != "" {
+ return true
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ resc := make(chan bool, 2)
+
+ // Try two strategies in parallel.
+ // See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
+ go func() {
+ req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
+ req.Header.Set("User-Agent", userAgent)
+ res, err := ctxhttp.Do(ctx, metaClient, req)
+ if err != nil {
+ resc <- false
+ return
+ }
+ defer res.Body.Close()
+ resc <- res.Header.Get("Metadata-Flavor") == "Google"
+ }()
+
+ go func() {
+ addrs, err := net.LookupHost("metadata.google.internal")
+ if err != nil || len(addrs) == 0 {
+ resc <- false
+ return
+ }
+ resc <- strsContains(addrs, metadataIP)
+ }()
+
+ tryHarder := systemInfoSuggestsGCE()
+ if tryHarder {
+ res := <-resc
+ if res {
+ // The first strategy succeeded, so let's use it.
+ return true
+ }
+ // Wait for either the DNS or metadata server probe to
+ // contradict the other one and say we are running on
+ // GCE. Give it a lot of time to do so, since the system
+ // info already suggests we're running on a GCE BIOS.
+ timer := time.NewTimer(5 * time.Second)
+ defer timer.Stop()
+ select {
+ case res = <-resc:
+ return res
+ case <-timer.C:
+ // Too slow. Who knows what this system is.
+ return false
+ }
+ }
+
+ // There's no hint from the system info that we're running on
+ // GCE, so use the first probe's result as truth, whether it's
+ // true or false. The goal here is to optimize for speed for
+ // users who are NOT running on GCE. We can't assume that
+ // either a DNS lookup or an HTTP request to a blackholed IP
+ // address is fast. Worst case this should return when the
+ // metaClient's Transport.ResponseHeaderTimeout or
+ // Transport.Dial.Timeout fires (in two seconds).
+ return <-resc
+}
+
+// systemInfoSuggestsGCE reports whether the local system (without
+// doing network requests) suggests that we're running on GCE. If this
+// returns true, testOnGCE tries a bit harder to reach its metadata
+// server.
+func systemInfoSuggestsGCE() bool {
+ if runtime.GOOS != "linux" {
+ // We don't have any non-Linux clues available, at least yet.
+ return false
+ }
+ slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
+ name := strings.TrimSpace(string(slurp))
+ return name == "Google" || name == "Google Compute Engine"
+}
+
+// Subscribe subscribes to a value from the metadata service.
+// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
+// The suffix may contain query parameters.
+//
+// Subscribe calls fn with the latest metadata value indicated by the provided
+// suffix. If the metadata value is deleted, fn is called with the empty string
+// and ok false. Subscribe blocks until fn returns a non-nil error or the value
+// is deleted. Subscribe returns the error value returned from the last call to
+// fn, which may be nil when ok == false.
+func Subscribe(suffix string, fn func(v string, ok bool) error) error {
+ const failedSubscribeSleep = time.Second * 5
+
+ // First check to see if the metadata value exists at all.
+ val, lastETag, err := getETag(subscribeClient, suffix)
+ if err != nil {
+ return err
+ }
+
+ if err := fn(val, true); err != nil {
+ return err
+ }
+
+ ok := true
+ if strings.ContainsRune(suffix, '?') {
+ suffix += "&wait_for_change=true&last_etag="
+ } else {
+ suffix += "?wait_for_change=true&last_etag="
+ }
+ for {
+ val, etag, err := getETag(subscribeClient, suffix+url.QueryEscape(lastETag))
+ if err != nil {
+ if _, deleted := err.(NotDefinedError); !deleted {
+ time.Sleep(failedSubscribeSleep)
+ continue // Retry on other errors.
+ }
+ ok = false
+ }
+ lastETag = etag
+
+ if err := fn(val, ok); err != nil || !ok {
+ return err
+ }
+ }
+}
+
+// ProjectID returns the current instance's project ID string.
+func ProjectID() (string, error) { return projID.get() }
+
+// NumericProjectID returns the current instance's numeric project ID.
+func NumericProjectID() (string, error) { return projNum.get() }
+
+// InternalIP returns the instance's primary internal IP address.
+func InternalIP() (string, error) {
+ return getTrimmed("instance/network-interfaces/0/ip")
+}
+
+// ExternalIP returns the instance's primary external (public) IP address.
+func ExternalIP() (string, error) {
+ return getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
+}
+
+// Hostname returns the instance's hostname. This will be of the form
+// ".c..internal".
+func Hostname() (string, error) {
+ return getTrimmed("instance/hostname")
+}
+
+// InstanceTags returns the list of user-defined instance tags,
+// assigned when initially creating a GCE instance.
+func InstanceTags() ([]string, error) {
+ var s []string
+ j, err := Get("instance/tags")
+ if err != nil {
+ return nil, err
+ }
+ if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
+ return nil, err
+ }
+ return s, nil
+}
+
+// InstanceID returns the current VM's numeric instance ID.
+func InstanceID() (string, error) {
+ return instID.get()
+}
+
+// InstanceName returns the current VM's instance ID string.
+func InstanceName() (string, error) {
+ host, err := Hostname()
+ if err != nil {
+ return "", err
+ }
+ return strings.Split(host, ".")[0], nil
+}
+
+// Zone returns the current VM's zone, such as "us-central1-b".
+func Zone() (string, error) {
+ zone, err := getTrimmed("instance/zone")
+ // zone is of the form "projects//zones/".
+ if err != nil {
+ return "", err
+ }
+ return zone[strings.LastIndex(zone, "/")+1:], nil
+}
+
+// InstanceAttributes returns the list of user-defined attributes,
+// assigned when initially creating a GCE VM instance. The value of an
+// attribute can be obtained with InstanceAttributeValue.
+func InstanceAttributes() ([]string, error) { return lines("instance/attributes/") }
+
+// ProjectAttributes returns the list of user-defined attributes
+// applying to the project as a whole, not just this VM. The value of
+// an attribute can be obtained with ProjectAttributeValue.
+func ProjectAttributes() ([]string, error) { return lines("project/attributes/") }
+
+func lines(suffix string) ([]string, error) {
+ j, err := Get(suffix)
+ if err != nil {
+ return nil, err
+ }
+ s := strings.Split(strings.TrimSpace(j), "\n")
+ for i := range s {
+ s[i] = strings.TrimSpace(s[i])
+ }
+ return s, nil
+}
+
+// InstanceAttributeValue returns the value of the provided VM
+// instance attribute.
+//
+// If the requested attribute is not defined, the returned error will
+// be of type NotDefinedError.
+//
+// InstanceAttributeValue may return ("", nil) if the attribute was
+// defined to be the empty string.
+func InstanceAttributeValue(attr string) (string, error) {
+ return Get("instance/attributes/" + attr)
+}
+
+// ProjectAttributeValue returns the value of the provided
+// project attribute.
+//
+// If the requested attribute is not defined, the returned error will
+// be of type NotDefinedError.
+//
+// ProjectAttributeValue may return ("", nil) if the attribute was
+// defined to be the empty string.
+func ProjectAttributeValue(attr string) (string, error) {
+ return Get("project/attributes/" + attr)
+}
+
+// Scopes returns the service account scopes for the given account.
+// The account may be empty or the string "default" to use the instance's
+// main account.
+func Scopes(serviceAccount string) ([]string, error) {
+ if serviceAccount == "" {
+ serviceAccount = "default"
+ }
+ return lines("instance/service-accounts/" + serviceAccount + "/scopes")
+}
+
+func strsContains(ss []string, s string) bool {
+ for _, v := range ss {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/cloud.google.com/go/iam/iam.go b/vendor/cloud.google.com/go/iam/iam.go
new file mode 100644
index 0000000..8722ee8
--- /dev/null
+++ b/vendor/cloud.google.com/go/iam/iam.go
@@ -0,0 +1,256 @@
+// Copyright 2016 Google Inc. 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.
+
+// Package iam supports the resource-specific operations of Google Cloud
+// IAM (Identity and Access Management) for the Google Cloud Libraries.
+// See https://cloud.google.com/iam for more about IAM.
+//
+// Users of the Google Cloud Libraries will typically not use this package
+// directly. Instead they will begin with some resource that supports IAM, like
+// a pubsub topic, and call its IAM method to get a Handle for that resource.
+package iam
+
+import (
+ "golang.org/x/net/context"
+ pb "google.golang.org/genproto/googleapis/iam/v1"
+ "google.golang.org/grpc"
+)
+
+// client abstracts the IAMPolicy API to allow multiple implementations.
+type client interface {
+ Get(ctx context.Context, resource string) (*pb.Policy, error)
+ Set(ctx context.Context, resource string, p *pb.Policy) error
+ Test(ctx context.Context, resource string, perms []string) ([]string, error)
+}
+
+// grpcClient implements client for the standard gRPC-based IAMPolicy service.
+type grpcClient struct {
+ c pb.IAMPolicyClient
+}
+
+func (g *grpcClient) Get(ctx context.Context, resource string) (*pb.Policy, error) {
+ proto, err := g.c.GetIamPolicy(ctx, &pb.GetIamPolicyRequest{Resource: resource})
+ if err != nil {
+ return nil, err
+ }
+ return proto, nil
+}
+func (g *grpcClient) Set(ctx context.Context, resource string, p *pb.Policy) error {
+ _, err := g.c.SetIamPolicy(ctx, &pb.SetIamPolicyRequest{
+ Resource: resource,
+ Policy: p,
+ })
+ return err
+}
+
+func (g *grpcClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
+ res, err := g.c.TestIamPermissions(ctx, &pb.TestIamPermissionsRequest{
+ Resource: resource,
+ Permissions: perms,
+ })
+ if err != nil {
+ return nil, err
+ }
+ return res.Permissions, nil
+}
+
+// A Handle provides IAM operations for a resource.
+type Handle struct {
+ c client
+ resource string
+}
+
+// InternalNewHandle is for use by the Google Cloud Libraries only.
+//
+// InternalNewHandle returns a Handle for resource.
+// The conn parameter refers to a server that must support the IAMPolicy service.
+func InternalNewHandle(conn *grpc.ClientConn, resource string) *Handle {
+ return InternalNewHandleClient(&grpcClient{c: pb.NewIAMPolicyClient(conn)}, resource)
+}
+
+// InternalNewHandleClient is for use by the Google Cloud Libraries only.
+//
+// InternalNewHandleClient returns a Handle for resource using the given
+// client implementation.
+func InternalNewHandleClient(c client, resource string) *Handle {
+ return &Handle{
+ c: c,
+ resource: resource,
+ }
+}
+
+// Policy retrieves the IAM policy for the resource.
+func (h *Handle) Policy(ctx context.Context) (*Policy, error) {
+ proto, err := h.c.Get(ctx, h.resource)
+ if err != nil {
+ return nil, err
+ }
+ return &Policy{InternalProto: proto}, nil
+}
+
+// SetPolicy replaces the resource's current policy with the supplied Policy.
+//
+// If policy was created from a prior call to Get, then the modification will
+// only succeed if the policy has not changed since the Get.
+func (h *Handle) SetPolicy(ctx context.Context, policy *Policy) error {
+ return h.c.Set(ctx, h.resource, policy.InternalProto)
+}
+
+// TestPermissions returns the subset of permissions that the caller has on the resource.
+func (h *Handle) TestPermissions(ctx context.Context, permissions []string) ([]string, error) {
+ return h.c.Test(ctx, h.resource, permissions)
+}
+
+// A RoleName is a name representing a collection of permissions.
+type RoleName string
+
+// Common role names.
+const (
+ Owner RoleName = "roles/owner"
+ Editor RoleName = "roles/editor"
+ Viewer RoleName = "roles/viewer"
+)
+
+const (
+ // AllUsers is a special member that denotes all users, even unauthenticated ones.
+ AllUsers = "allUsers"
+
+ // AllAuthenticatedUsers is a special member that denotes all authenticated users.
+ AllAuthenticatedUsers = "allAuthenticatedUsers"
+)
+
+// A Policy is a list of Bindings representing roles
+// granted to members.
+//
+// The zero Policy is a valid policy with no bindings.
+type Policy struct {
+ // TODO(jba): when type aliases are available, put Policy into an internal package
+ // and provide an exported alias here.
+
+ // This field is exported for use by the Google Cloud Libraries only.
+ // It may become unexported in a future release.
+ InternalProto *pb.Policy
+}
+
+// Members returns the list of members with the supplied role.
+// The return value should not be modified. Use Add and Remove
+// to modify the members of a role.
+func (p *Policy) Members(r RoleName) []string {
+ b := p.binding(r)
+ if b == nil {
+ return nil
+ }
+ return b.Members
+}
+
+// HasRole reports whether member has role r.
+func (p *Policy) HasRole(member string, r RoleName) bool {
+ return memberIndex(member, p.binding(r)) >= 0
+}
+
+// Add adds member member to role r if it is not already present.
+// A new binding is created if there is no binding for the role.
+func (p *Policy) Add(member string, r RoleName) {
+ b := p.binding(r)
+ if b == nil {
+ if p.InternalProto == nil {
+ p.InternalProto = &pb.Policy{}
+ }
+ p.InternalProto.Bindings = append(p.InternalProto.Bindings, &pb.Binding{
+ Role: string(r),
+ Members: []string{member},
+ })
+ return
+ }
+ if memberIndex(member, b) < 0 {
+ b.Members = append(b.Members, member)
+ return
+ }
+}
+
+// Remove removes member from role r if it is present.
+func (p *Policy) Remove(member string, r RoleName) {
+ bi := p.bindingIndex(r)
+ if bi < 0 {
+ return
+ }
+ bindings := p.InternalProto.Bindings
+ b := bindings[bi]
+ mi := memberIndex(member, b)
+ if mi < 0 {
+ return
+ }
+ // Order doesn't matter for bindings or members, so to remove, move the last item
+ // into the removed spot and shrink the slice.
+ if len(b.Members) == 1 {
+ // Remove binding.
+ last := len(bindings) - 1
+ bindings[bi] = bindings[last]
+ bindings[last] = nil
+ p.InternalProto.Bindings = bindings[:last]
+ return
+ }
+ // Remove member.
+ // TODO(jba): worry about multiple copies of m?
+ last := len(b.Members) - 1
+ b.Members[mi] = b.Members[last]
+ b.Members[last] = ""
+ b.Members = b.Members[:last]
+}
+
+// Roles returns the names of all the roles that appear in the Policy.
+func (p *Policy) Roles() []RoleName {
+ if p.InternalProto == nil {
+ return nil
+ }
+ var rns []RoleName
+ for _, b := range p.InternalProto.Bindings {
+ rns = append(rns, RoleName(b.Role))
+ }
+ return rns
+}
+
+// binding returns the Binding for the suppied role, or nil if there isn't one.
+func (p *Policy) binding(r RoleName) *pb.Binding {
+ i := p.bindingIndex(r)
+ if i < 0 {
+ return nil
+ }
+ return p.InternalProto.Bindings[i]
+}
+
+func (p *Policy) bindingIndex(r RoleName) int {
+ if p.InternalProto == nil {
+ return -1
+ }
+ for i, b := range p.InternalProto.Bindings {
+ if b.Role == string(r) {
+ return i
+ }
+ }
+ return -1
+}
+
+// memberIndex returns the index of m in b's Members, or -1 if not found.
+func memberIndex(m string, b *pb.Binding) int {
+ if b == nil {
+ return -1
+ }
+ for i, mm := range b.Members {
+ if mm == m {
+ return i
+ }
+ }
+ return -1
+}
diff --git a/vendor/cloud.google.com/go/internal/annotate.go b/vendor/cloud.google.com/go/internal/annotate.go
new file mode 100644
index 0000000..797809a
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/annotate.go
@@ -0,0 +1,54 @@
+// Copyright 2017 Google Inc. 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.
+
+package internal
+
+import (
+ "fmt"
+
+ "google.golang.org/api/googleapi"
+ "google.golang.org/grpc/status"
+)
+
+// Annotate prepends msg to the error message in err, attempting
+// to preserve other information in err, like an error code.
+//
+// Annotate panics if err is nil.
+//
+// Annotate knows about these error types:
+// - "google.golang.org/grpc/status".Status
+// - "google.golang.org/api/googleapi".Error
+// If the error is not one of these types, Annotate behaves
+// like
+// fmt.Errorf("%s: %v", msg, err)
+func Annotate(err error, msg string) error {
+ if err == nil {
+ panic("Annotate called with nil")
+ }
+ if s, ok := status.FromError(err); ok {
+ p := s.Proto()
+ p.Message = msg + ": " + p.Message
+ return status.ErrorProto(p)
+ }
+ if g, ok := err.(*googleapi.Error); ok {
+ g.Message = msg + ": " + g.Message
+ return g
+ }
+ return fmt.Errorf("%s: %v", msg, err)
+}
+
+// Annotatef uses format and args to format a string, then calls Annotate.
+func Annotatef(err error, format string, args ...interface{}) error {
+ return Annotate(err, fmt.Sprintf(format, args...))
+}
diff --git a/vendor/cloud.google.com/go/internal/optional/optional.go b/vendor/cloud.google.com/go/internal/optional/optional.go
new file mode 100644
index 0000000..4c15410
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/optional/optional.go
@@ -0,0 +1,108 @@
+// Copyright 2016 Google Inc. 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.
+
+// Package optional provides versions of primitive types that can
+// be nil. These are useful in methods that update some of an API object's
+// fields.
+package optional
+
+import (
+ "fmt"
+ "strings"
+ "time"
+)
+
+type (
+ // Bool is either a bool or nil.
+ Bool interface{}
+
+ // String is either a string or nil.
+ String interface{}
+
+ // Int is either an int or nil.
+ Int interface{}
+
+ // Uint is either a uint or nil.
+ Uint interface{}
+
+ // Float64 is either a float64 or nil.
+ Float64 interface{}
+
+ // Duration is either a time.Duration or nil.
+ Duration interface{}
+)
+
+// ToBool returns its argument as a bool.
+// It panics if its argument is nil or not a bool.
+func ToBool(v Bool) bool {
+ x, ok := v.(bool)
+ if !ok {
+ doPanic("Bool", v)
+ }
+ return x
+}
+
+// ToString returns its argument as a string.
+// It panics if its argument is nil or not a string.
+func ToString(v String) string {
+ x, ok := v.(string)
+ if !ok {
+ doPanic("String", v)
+ }
+ return x
+}
+
+// ToInt returns its argument as an int.
+// It panics if its argument is nil or not an int.
+func ToInt(v Int) int {
+ x, ok := v.(int)
+ if !ok {
+ doPanic("Int", v)
+ }
+ return x
+}
+
+// ToUint returns its argument as a uint.
+// It panics if its argument is nil or not a uint.
+func ToUint(v Uint) uint {
+ x, ok := v.(uint)
+ if !ok {
+ doPanic("Uint", v)
+ }
+ return x
+}
+
+// ToFloat64 returns its argument as a float64.
+// It panics if its argument is nil or not a float64.
+func ToFloat64(v Float64) float64 {
+ x, ok := v.(float64)
+ if !ok {
+ doPanic("Float64", v)
+ }
+ return x
+}
+
+// ToDuration returns its argument as a time.Duration.
+// It panics if its argument is nil or not a time.Duration.
+func ToDuration(v Duration) time.Duration {
+ x, ok := v.(time.Duration)
+ if !ok {
+ doPanic("Duration", v)
+ }
+ return x
+}
+
+func doPanic(capType string, v interface{}) {
+ panic(fmt.Sprintf("optional.%s value should be %s, got %T", capType, strings.ToLower(capType), v))
+}
diff --git a/vendor/cloud.google.com/go/internal/retry.go b/vendor/cloud.google.com/go/internal/retry.go
new file mode 100644
index 0000000..e1f9aaa
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/retry.go
@@ -0,0 +1,55 @@
+// Copyright 2016 Google Inc. 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.
+
+package internal
+
+import (
+ "time"
+
+ gax "github.com/googleapis/gax-go"
+
+ "golang.org/x/net/context"
+)
+
+// Retry calls the supplied function f repeatedly according to the provided
+// backoff parameters. It returns when one of the following occurs:
+// When f's first return value is true, Retry immediately returns with f's second
+// return value.
+// When the provided context is done, Retry returns with an error that
+// includes both ctx.Error() and the last error returned by f.
+func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error {
+ return retry(ctx, bo, f, gax.Sleep)
+}
+
+func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
+ sleep func(context.Context, time.Duration) error) error {
+ var lastErr error
+ for {
+ stop, err := f()
+ if stop {
+ return err
+ }
+ // Remember the last "real" error from f.
+ if err != nil && err != context.Canceled && err != context.DeadlineExceeded {
+ lastErr = err
+ }
+ p := bo.Pause()
+ if cerr := sleep(ctx, p); cerr != nil {
+ if lastErr != nil {
+ return Annotatef(lastErr, "retry failed with %v; last error", cerr)
+ }
+ return cerr
+ }
+ }
+}
diff --git a/vendor/cloud.google.com/go/internal/version/update_version.sh b/vendor/cloud.google.com/go/internal/version/update_version.sh
new file mode 100755
index 0000000..fecf1f0
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/version/update_version.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+today=$(date +%Y%m%d)
+
+sed -i -r -e 's/const Repo = "([0-9]{8})"/const Repo = "'$today'"/' $GOFILE
+
diff --git a/vendor/cloud.google.com/go/internal/version/version.go b/vendor/cloud.google.com/go/internal/version/version.go
new file mode 100644
index 0000000..513afa4
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/version/version.go
@@ -0,0 +1,71 @@
+// Copyright 2016 Google Inc. 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.
+
+//go:generate ./update_version.sh
+
+// Package version contains version information for Google Cloud Client
+// Libraries for Go, as reported in request headers.
+package version
+
+import (
+ "runtime"
+ "strings"
+ "unicode"
+)
+
+// Repo is the current version of the client libraries in this
+// repo. It should be a date in YYYYMMDD format.
+const Repo = "20170928"
+
+// Go returns the Go runtime version. The returned string
+// has no whitespace.
+func Go() string {
+ return goVersion
+}
+
+var goVersion = goVer(runtime.Version())
+
+const develPrefix = "devel +"
+
+func goVer(s string) string {
+ if strings.HasPrefix(s, develPrefix) {
+ s = s[len(develPrefix):]
+ if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
+ s = s[:p]
+ }
+ return s
+ }
+
+ if strings.HasPrefix(s, "go1") {
+ s = s[2:]
+ var prerelease string
+ if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
+ s, prerelease = s[:p], s[p:]
+ }
+ if strings.HasSuffix(s, ".") {
+ s += "0"
+ } else if strings.Count(s, ".") < 2 {
+ s += ".0"
+ }
+ if prerelease != "" {
+ s += "-" + prerelease
+ }
+ return s
+ }
+ return ""
+}
+
+func notSemverRune(r rune) bool {
+ return strings.IndexRune("0123456789.", r) < 0
+}
diff --git a/vendor/cloud.google.com/go/storage/acl.go b/vendor/cloud.google.com/go/storage/acl.go
new file mode 100644
index 0000000..24f90c9
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/acl.go
@@ -0,0 +1,235 @@
+// Copyright 2014 Google Inc. 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.
+
+package storage
+
+import (
+ "net/http"
+ "reflect"
+
+ "golang.org/x/net/context"
+ "google.golang.org/api/googleapi"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// ACLRole is the level of access to grant.
+type ACLRole string
+
+const (
+ RoleOwner ACLRole = "OWNER"
+ RoleReader ACLRole = "READER"
+ RoleWriter ACLRole = "WRITER"
+)
+
+// ACLEntity refers to a user or group.
+// They are sometimes referred to as grantees.
+//
+// It could be in the form of:
+// "user-", "user-", "group-", "group-",
+// "domain-" and "project-team-".
+//
+// Or one of the predefined constants: AllUsers, AllAuthenticatedUsers.
+type ACLEntity string
+
+const (
+ AllUsers ACLEntity = "allUsers"
+ AllAuthenticatedUsers ACLEntity = "allAuthenticatedUsers"
+)
+
+// ACLRule represents a grant for a role to an entity (user, group or team) for a Google Cloud Storage object or bucket.
+type ACLRule struct {
+ Entity ACLEntity
+ Role ACLRole
+}
+
+// ACLHandle provides operations on an access control list for a Google Cloud Storage bucket or object.
+type ACLHandle struct {
+ c *Client
+ bucket string
+ object string
+ isDefault bool
+ userProject string // for requester-pays buckets
+}
+
+// Delete permanently deletes the ACL entry for the given entity.
+func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) error {
+ if a.object != "" {
+ return a.objectDelete(ctx, entity)
+ }
+ if a.isDefault {
+ return a.bucketDefaultDelete(ctx, entity)
+ }
+ return a.bucketDelete(ctx, entity)
+}
+
+// Set sets the permission level for the given entity.
+func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) error {
+ if a.object != "" {
+ return a.objectSet(ctx, entity, role, false)
+ }
+ if a.isDefault {
+ return a.objectSet(ctx, entity, role, true)
+ }
+ return a.bucketSet(ctx, entity, role)
+}
+
+// List retrieves ACL entries.
+func (a *ACLHandle) List(ctx context.Context) ([]ACLRule, error) {
+ if a.object != "" {
+ return a.objectList(ctx)
+ }
+ if a.isDefault {
+ return a.bucketDefaultList(ctx)
+ }
+ return a.bucketList(ctx)
+}
+
+func (a *ACLHandle) bucketDefaultList(ctx context.Context) ([]ACLRule, error) {
+ var acls *raw.ObjectAccessControls
+ var err error
+ err = runWithRetry(ctx, func() error {
+ req := a.c.raw.DefaultObjectAccessControls.List(a.bucket)
+ a.configureCall(req, ctx)
+ acls, err = req.Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return toACLRules(acls.Items), nil
+}
+
+func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error {
+ return runWithRetry(ctx, func() error {
+ req := a.c.raw.DefaultObjectAccessControls.Delete(a.bucket, string(entity))
+ a.configureCall(req, ctx)
+ return req.Do()
+ })
+}
+
+func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) {
+ var acls *raw.BucketAccessControls
+ var err error
+ err = runWithRetry(ctx, func() error {
+ req := a.c.raw.BucketAccessControls.List(a.bucket)
+ a.configureCall(req, ctx)
+ acls, err = req.Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ r := make([]ACLRule, len(acls.Items))
+ for i, v := range acls.Items {
+ r[i].Entity = ACLEntity(v.Entity)
+ r[i].Role = ACLRole(v.Role)
+ }
+ return r, nil
+}
+
+func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRole) error {
+ acl := &raw.BucketAccessControl{
+ Bucket: a.bucket,
+ Entity: string(entity),
+ Role: string(role),
+ }
+ err := runWithRetry(ctx, func() error {
+ req := a.c.raw.BucketAccessControls.Update(a.bucket, string(entity), acl)
+ a.configureCall(req, ctx)
+ _, err := req.Do()
+ return err
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error {
+ err := runWithRetry(ctx, func() error {
+ req := a.c.raw.BucketAccessControls.Delete(a.bucket, string(entity))
+ a.configureCall(req, ctx)
+ return req.Do()
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) {
+ var acls *raw.ObjectAccessControls
+ var err error
+ err = runWithRetry(ctx, func() error {
+ req := a.c.raw.ObjectAccessControls.List(a.bucket, a.object)
+ a.configureCall(req, ctx)
+ acls, err = req.Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return toACLRules(acls.Items), nil
+}
+
+func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole, isBucketDefault bool) error {
+ type setRequest interface {
+ Do(opts ...googleapi.CallOption) (*raw.ObjectAccessControl, error)
+ Header() http.Header
+ }
+
+ acl := &raw.ObjectAccessControl{
+ Bucket: a.bucket,
+ Entity: string(entity),
+ Role: string(role),
+ }
+ var req setRequest
+ if isBucketDefault {
+ req = a.c.raw.DefaultObjectAccessControls.Update(a.bucket, string(entity), acl)
+ } else {
+ req = a.c.raw.ObjectAccessControls.Update(a.bucket, a.object, string(entity), acl)
+ }
+ a.configureCall(req, ctx)
+ return runWithRetry(ctx, func() error {
+ _, err := req.Do()
+ return err
+ })
+}
+
+func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
+ return runWithRetry(ctx, func() error {
+ req := a.c.raw.ObjectAccessControls.Delete(a.bucket, a.object, string(entity))
+ a.configureCall(req, ctx)
+ return req.Do()
+ })
+}
+
+func (a *ACLHandle) configureCall(call interface {
+ Header() http.Header
+}, ctx context.Context) {
+ vc := reflect.ValueOf(call)
+ vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)})
+ if a.userProject != "" {
+ vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(a.userProject)})
+ }
+ setClientHeader(call.Header())
+}
+
+func toACLRules(items []*raw.ObjectAccessControl) []ACLRule {
+ r := make([]ACLRule, 0, len(items))
+ for _, item := range items {
+ r = append(r, ACLRule{Entity: ACLEntity(item.Entity), Role: ACLRole(item.Role)})
+ }
+ return r
+}
diff --git a/vendor/cloud.google.com/go/storage/bucket.go b/vendor/cloud.google.com/go/storage/bucket.go
new file mode 100644
index 0000000..fcaa59d
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/bucket.go
@@ -0,0 +1,767 @@
+// Copyright 2014 Google Inc. LiveAndArchived 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.
+
+package storage
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "time"
+
+ "cloud.google.com/go/internal/optional"
+ "golang.org/x/net/context"
+ "google.golang.org/api/googleapi"
+ "google.golang.org/api/iterator"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// BucketHandle provides operations on a Google Cloud Storage bucket.
+// Use Client.Bucket to get a handle.
+type BucketHandle struct {
+ c *Client
+ name string
+ acl ACLHandle
+ defaultObjectACL ACLHandle
+ conds *BucketConditions
+ userProject string // project for Requester Pays buckets
+}
+
+// Bucket returns a BucketHandle, which provides operations on the named bucket.
+// This call does not perform any network operations.
+//
+// The supplied name must contain only lowercase letters, numbers, dashes,
+// underscores, and dots. The full specification for valid bucket names can be
+// found at:
+// https://cloud.google.com/storage/docs/bucket-naming
+func (c *Client) Bucket(name string) *BucketHandle {
+ return &BucketHandle{
+ c: c,
+ name: name,
+ acl: ACLHandle{
+ c: c,
+ bucket: name,
+ },
+ defaultObjectACL: ACLHandle{
+ c: c,
+ bucket: name,
+ isDefault: true,
+ },
+ }
+}
+
+// Create creates the Bucket in the project.
+// If attrs is nil the API defaults will be used.
+func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) error {
+ var bkt *raw.Bucket
+ if attrs != nil {
+ bkt = attrs.toRawBucket()
+ } else {
+ bkt = &raw.Bucket{}
+ }
+ bkt.Name = b.name
+ // If there is lifecycle information but no location, explicitly set
+ // the location. This is a GCS quirk/bug.
+ if bkt.Location == "" && bkt.Lifecycle != nil {
+ bkt.Location = "US"
+ }
+ req := b.c.raw.Buckets.Insert(projectID, bkt)
+ setClientHeader(req.Header())
+ return runWithRetry(ctx, func() error { _, err := req.Context(ctx).Do(); return err })
+}
+
+// Delete deletes the Bucket.
+func (b *BucketHandle) Delete(ctx context.Context) error {
+ req, err := b.newDeleteCall()
+ if err != nil {
+ return err
+ }
+ return runWithRetry(ctx, func() error { return req.Context(ctx).Do() })
+}
+
+func (b *BucketHandle) newDeleteCall() (*raw.BucketsDeleteCall, error) {
+ req := b.c.raw.Buckets.Delete(b.name)
+ setClientHeader(req.Header())
+ if err := applyBucketConds("BucketHandle.Delete", b.conds, req); err != nil {
+ return nil, err
+ }
+ if b.userProject != "" {
+ req.UserProject(b.userProject)
+ }
+ return req, nil
+}
+
+// ACL returns an ACLHandle, which provides access to the bucket's access control list.
+// This controls who can list, create or overwrite the objects in a bucket.
+// This call does not perform any network operations.
+func (b *BucketHandle) ACL() *ACLHandle {
+ return &b.acl
+}
+
+// DefaultObjectACL returns an ACLHandle, which provides access to the bucket's default object ACLs.
+// These ACLs are applied to newly created objects in this bucket that do not have a defined ACL.
+// This call does not perform any network operations.
+func (b *BucketHandle) DefaultObjectACL() *ACLHandle {
+ return &b.defaultObjectACL
+}
+
+// Object returns an ObjectHandle, which provides operations on the named object.
+// This call does not perform any network operations.
+//
+// name must consist entirely of valid UTF-8-encoded runes. The full specification
+// for valid object names can be found at:
+// https://cloud.google.com/storage/docs/bucket-naming
+func (b *BucketHandle) Object(name string) *ObjectHandle {
+ return &ObjectHandle{
+ c: b.c,
+ bucket: b.name,
+ object: name,
+ acl: ACLHandle{
+ c: b.c,
+ bucket: b.name,
+ object: name,
+ userProject: b.userProject,
+ },
+ gen: -1,
+ userProject: b.userProject,
+ }
+}
+
+// Attrs returns the metadata for the bucket.
+func (b *BucketHandle) Attrs(ctx context.Context) (*BucketAttrs, error) {
+ req, err := b.newGetCall()
+ if err != nil {
+ return nil, err
+ }
+ var resp *raw.Bucket
+ err = runWithRetry(ctx, func() error {
+ resp, err = req.Context(ctx).Do()
+ return err
+ })
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ return nil, ErrBucketNotExist
+ }
+ if err != nil {
+ return nil, err
+ }
+ return newBucket(resp), nil
+}
+
+func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
+ req := b.c.raw.Buckets.Get(b.name).Projection("full")
+ setClientHeader(req.Header())
+ if err := applyBucketConds("BucketHandle.Attrs", b.conds, req); err != nil {
+ return nil, err
+ }
+ if b.userProject != "" {
+ req.UserProject(b.userProject)
+ }
+ return req, nil
+}
+
+func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (*BucketAttrs, error) {
+ req, err := b.newPatchCall(&uattrs)
+ if err != nil {
+ return nil, err
+ }
+ // TODO(jba): retry iff metagen is set?
+ rb, err := req.Context(ctx).Do()
+ if err != nil {
+ return nil, err
+ }
+ return newBucket(rb), nil
+}
+
+func (b *BucketHandle) newPatchCall(uattrs *BucketAttrsToUpdate) (*raw.BucketsPatchCall, error) {
+ rb := uattrs.toRawBucket()
+ req := b.c.raw.Buckets.Patch(b.name, rb).Projection("full")
+ setClientHeader(req.Header())
+ if err := applyBucketConds("BucketHandle.Update", b.conds, req); err != nil {
+ return nil, err
+ }
+ if b.userProject != "" {
+ req.UserProject(b.userProject)
+ }
+ return req, nil
+}
+
+// BucketAttrs represents the metadata for a Google Cloud Storage bucket.
+// Read-only fields are ignored by BucketHandle.Create.
+type BucketAttrs struct {
+ // Name is the name of the bucket.
+ // This field is read-only.
+ Name string
+
+ // ACL is the list of access control rules on the bucket.
+ ACL []ACLRule
+
+ // DefaultObjectACL is the list of access controls to
+ // apply to new objects when no object ACL is provided.
+ DefaultObjectACL []ACLRule
+
+ // Location is the location of the bucket. It defaults to "US".
+ Location string
+
+ // MetaGeneration is the metadata generation of the bucket.
+ // This field is read-only.
+ MetaGeneration int64
+
+ // StorageClass is the default storage class of the bucket. This defines
+ // how objects in the bucket are stored and determines the SLA
+ // and the cost of storage. Typical values are "MULTI_REGIONAL",
+ // "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD" and
+ // "DURABLE_REDUCED_AVAILABILITY". Defaults to "STANDARD", which
+ // is equivalent to "MULTI_REGIONAL" or "REGIONAL" depending on
+ // the bucket's location settings.
+ StorageClass string
+
+ // Created is the creation time of the bucket.
+ // This field is read-only.
+ Created time.Time
+
+ // VersioningEnabled reports whether this bucket has versioning enabled.
+ VersioningEnabled bool
+
+ // Labels are the bucket's labels.
+ Labels map[string]string
+
+ // RequesterPays reports whether the bucket is a Requester Pays bucket.
+ // Clients performing operations on Requester Pays buckets must provide
+ // a user project (see BucketHandle.UserProject), which will be billed
+ // for the operations.
+ RequesterPays bool
+ // Lifecycle is the lifecycle configuration for objects in the bucket.
+ Lifecycle Lifecycle
+}
+
+// Lifecycle is the lifecycle configuration for objects in the bucket.
+type Lifecycle struct {
+ Rules []LifecycleRule
+}
+
+const (
+ // RFC3339 date with only the date segment, used for CreatedBefore in LifecycleRule.
+ rfc3339Date = "2006-01-02"
+
+ // DeleteAction is a lifecycle action that deletes a live and/or archived
+ // objects. Takes precendence over SetStorageClass actions.
+ DeleteAction = "Delete"
+
+ // SetStorageClassAction changes the storage class of live and/or archived
+ // objects.
+ SetStorageClassAction = "SetStorageClass"
+)
+
+// LifecycleRule is a lifecycle configuration rule.
+//
+// When all the configured conditions are met by an object in the bucket, the
+// configured action will automatically be taken on that object.
+type LifecycleRule struct {
+ // Action is the action to take when all of the associated conditions are
+ // met.
+ Action LifecycleAction
+
+ // Condition is the set of conditions that must be met for the associated
+ // action to be taken.
+ Condition LifecycleCondition
+}
+
+// LifecycleAction is a lifecycle configuration action.
+type LifecycleAction struct {
+ // Type is the type of action to take on matching objects.
+ //
+ // Acceptable values are "Delete" to delete matching objects and
+ // "SetStorageClass" to set the storage class defined in StorageClass on
+ // matching objects.
+ Type string
+
+ // StorageClass is the storage class to set on matching objects if the Action
+ // is "SetStorageClass".
+ StorageClass string
+}
+
+// Liveness specifies whether the object is live or not.
+type Liveness int
+
+const (
+ // LiveAndArchived includes both live and archived objects.
+ LiveAndArchived Liveness = iota
+ // Live specifies that the object is still live.
+ Live
+ // Archived specifies that the object is archived.
+ Archived
+)
+
+// LifecycleCondition is a set of conditions used to match objects and take an
+// action automatically.
+//
+// All configured conditions must be met for the associated action to be taken.
+type LifecycleCondition struct {
+ // AgeInDays is the age of the object in days.
+ AgeInDays int64
+
+ // CreatedBefore is the time the object was created.
+ //
+ // This condition is satisfied when an object is created before midnight of
+ // the specified date in UTC.
+ CreatedBefore time.Time
+
+ // Liveness specifies the object's liveness. Relevant only for versioned objects
+ Liveness Liveness
+
+ // MatchesStorageClasses is the condition matching the object's storage
+ // class.
+ //
+ // Values include "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE",
+ // "STANDARD", and "DURABLE_REDUCED_AVAILABILITY".
+ MatchesStorageClasses []string
+
+ // NumNewerVersions is the condition matching objects with a number of newer versions.
+ //
+ // If the value is N, this condition is satisfied when there are at least N
+ // versions (including the live version) newer than this version of the
+ // object.
+ NumNewerVersions int64
+}
+
+func newBucket(b *raw.Bucket) *BucketAttrs {
+ if b == nil {
+ return nil
+ }
+ bucket := &BucketAttrs{
+ Name: b.Name,
+ Location: b.Location,
+ MetaGeneration: b.Metageneration,
+ StorageClass: b.StorageClass,
+ Created: convertTime(b.TimeCreated),
+ VersioningEnabled: b.Versioning != nil && b.Versioning.Enabled,
+ Labels: b.Labels,
+ RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
+ Lifecycle: toLifecycle(b.Lifecycle),
+ }
+ acl := make([]ACLRule, len(b.Acl))
+ for i, rule := range b.Acl {
+ acl[i] = ACLRule{
+ Entity: ACLEntity(rule.Entity),
+ Role: ACLRole(rule.Role),
+ }
+ }
+ bucket.ACL = acl
+ objACL := make([]ACLRule, len(b.DefaultObjectAcl))
+ for i, rule := range b.DefaultObjectAcl {
+ objACL[i] = ACLRule{
+ Entity: ACLEntity(rule.Entity),
+ Role: ACLRole(rule.Role),
+ }
+ }
+ bucket.DefaultObjectACL = objACL
+ return bucket
+}
+
+// toRawBucket copies the editable attribute from b to the raw library's Bucket type.
+func (b *BucketAttrs) toRawBucket() *raw.Bucket {
+ var acl []*raw.BucketAccessControl
+ if len(b.ACL) > 0 {
+ acl = make([]*raw.BucketAccessControl, len(b.ACL))
+ for i, rule := range b.ACL {
+ acl[i] = &raw.BucketAccessControl{
+ Entity: string(rule.Entity),
+ Role: string(rule.Role),
+ }
+ }
+ }
+ dACL := toRawObjectACL(b.DefaultObjectACL)
+ // Copy label map.
+ var labels map[string]string
+ if len(b.Labels) > 0 {
+ labels = make(map[string]string, len(b.Labels))
+ for k, v := range b.Labels {
+ labels[k] = v
+ }
+ }
+ // Ignore VersioningEnabled if it is false. This is OK because
+ // we only call this method when creating a bucket, and by default
+ // new buckets have versioning off.
+ var v *raw.BucketVersioning
+ if b.VersioningEnabled {
+ v = &raw.BucketVersioning{Enabled: true}
+ }
+ var bb *raw.BucketBilling
+ if b.RequesterPays {
+ bb = &raw.BucketBilling{RequesterPays: true}
+ }
+ return &raw.Bucket{
+ Name: b.Name,
+ DefaultObjectAcl: dACL,
+ Location: b.Location,
+ StorageClass: b.StorageClass,
+ Acl: acl,
+ Versioning: v,
+ Labels: labels,
+ Billing: bb,
+ Lifecycle: toRawLifecycle(b.Lifecycle),
+ }
+}
+
+type BucketAttrsToUpdate struct {
+ // VersioningEnabled, if set, updates whether the bucket uses versioning.
+ VersioningEnabled optional.Bool
+
+ // RequesterPays, if set, updates whether the bucket is a Requester Pays bucket.
+ RequesterPays optional.Bool
+
+ setLabels map[string]string
+ deleteLabels map[string]bool
+}
+
+// SetLabel causes a label to be added or modified when ua is used
+// in a call to Bucket.Update.
+func (ua *BucketAttrsToUpdate) SetLabel(name, value string) {
+ if ua.setLabels == nil {
+ ua.setLabels = map[string]string{}
+ }
+ ua.setLabels[name] = value
+}
+
+// DeleteLabel causes a label to be deleted when ua is used in a
+// call to Bucket.Update.
+func (ua *BucketAttrsToUpdate) DeleteLabel(name string) {
+ if ua.deleteLabels == nil {
+ ua.deleteLabels = map[string]bool{}
+ }
+ ua.deleteLabels[name] = true
+}
+
+func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
+ rb := &raw.Bucket{}
+ if ua.VersioningEnabled != nil {
+ rb.Versioning = &raw.BucketVersioning{
+ Enabled: optional.ToBool(ua.VersioningEnabled),
+ ForceSendFields: []string{"Enabled"},
+ }
+ }
+ if ua.RequesterPays != nil {
+ rb.Billing = &raw.BucketBilling{
+ RequesterPays: optional.ToBool(ua.RequesterPays),
+ ForceSendFields: []string{"RequesterPays"},
+ }
+ }
+ if ua.setLabels != nil || ua.deleteLabels != nil {
+ rb.Labels = map[string]string{}
+ for k, v := range ua.setLabels {
+ rb.Labels[k] = v
+ }
+ if len(rb.Labels) == 0 && len(ua.deleteLabels) > 0 {
+ rb.ForceSendFields = append(rb.ForceSendFields, "Labels")
+ }
+ for l := range ua.deleteLabels {
+ rb.NullFields = append(rb.NullFields, "Labels."+l)
+ }
+ }
+ return rb
+}
+
+// If returns a new BucketHandle that applies a set of preconditions.
+// Preconditions already set on the BucketHandle are ignored.
+// Operations on the new handle will only occur if the preconditions are
+// satisfied. The only valid preconditions for buckets are MetagenerationMatch
+// and MetagenerationNotMatch.
+func (b *BucketHandle) If(conds BucketConditions) *BucketHandle {
+ b2 := *b
+ b2.conds = &conds
+ return &b2
+}
+
+// BucketConditions constrain bucket methods to act on specific metagenerations.
+//
+// The zero value is an empty set of constraints.
+type BucketConditions struct {
+ // MetagenerationMatch specifies that the bucket must have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationMatch is zero, it has no effect.
+ MetagenerationMatch int64
+
+ // MetagenerationNotMatch specifies that the bucket must not have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationNotMatch is zero, it has no effect.
+ MetagenerationNotMatch int64
+}
+
+func (c *BucketConditions) validate(method string) error {
+ if *c == (BucketConditions{}) {
+ return fmt.Errorf("storage: %s: empty conditions", method)
+ }
+ if c.MetagenerationMatch != 0 && c.MetagenerationNotMatch != 0 {
+ return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
+ }
+ return nil
+}
+
+// UserProject returns a new BucketHandle that passes the project ID as the user
+// project for all subsequent calls. Calls with a user project will be billed to that
+// project rather than to the bucket's owning project.
+//
+// A user project is required for all operations on Requester Pays buckets.
+func (b *BucketHandle) UserProject(projectID string) *BucketHandle {
+ b2 := *b
+ b2.userProject = projectID
+ b2.acl.userProject = projectID
+ b2.defaultObjectACL.userProject = projectID
+ return &b2
+}
+
+// applyBucketConds modifies the provided call using the conditions in conds.
+// call is something that quacks like a *raw.WhateverCall.
+func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
+ if conds == nil {
+ return nil
+ }
+ if err := conds.validate(method); err != nil {
+ return err
+ }
+ cval := reflect.ValueOf(call)
+ switch {
+ case conds.MetagenerationMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
+ }
+ case conds.MetagenerationNotMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
+ }
+ }
+ return nil
+}
+
+func toRawLifecycle(l Lifecycle) *raw.BucketLifecycle {
+ var rl raw.BucketLifecycle
+ if len(l.Rules) == 0 {
+ return nil
+ }
+ for _, r := range l.Rules {
+ rr := &raw.BucketLifecycleRule{
+ Action: &raw.BucketLifecycleRuleAction{
+ Type: r.Action.Type,
+ StorageClass: r.Action.StorageClass,
+ },
+ Condition: &raw.BucketLifecycleRuleCondition{
+ Age: r.Condition.AgeInDays,
+ MatchesStorageClass: r.Condition.MatchesStorageClasses,
+ NumNewerVersions: r.Condition.NumNewerVersions,
+ },
+ }
+
+ switch r.Condition.Liveness {
+ case LiveAndArchived:
+ rr.Condition.IsLive = nil
+ case Live:
+ rr.Condition.IsLive = googleapi.Bool(true)
+ case Archived:
+ rr.Condition.IsLive = googleapi.Bool(false)
+ }
+
+ if !r.Condition.CreatedBefore.IsZero() {
+ rr.Condition.CreatedBefore = r.Condition.CreatedBefore.Format(rfc3339Date)
+ }
+ rl.Rule = append(rl.Rule, rr)
+ }
+ return &rl
+}
+
+func toLifecycle(rl *raw.BucketLifecycle) Lifecycle {
+ var l Lifecycle
+ if rl == nil {
+ return l
+ }
+ for _, rr := range rl.Rule {
+ r := LifecycleRule{
+ Action: LifecycleAction{
+ Type: rr.Action.Type,
+ StorageClass: rr.Action.StorageClass,
+ },
+ Condition: LifecycleCondition{
+ AgeInDays: rr.Condition.Age,
+ MatchesStorageClasses: rr.Condition.MatchesStorageClass,
+ NumNewerVersions: rr.Condition.NumNewerVersions,
+ },
+ }
+
+ switch {
+ case rr.Condition.IsLive == nil:
+ r.Condition.Liveness = LiveAndArchived
+ case *rr.Condition.IsLive == true:
+ r.Condition.Liveness = Live
+ case *rr.Condition.IsLive == false:
+ r.Condition.Liveness = Archived
+ }
+
+ if rr.Condition.CreatedBefore != "" {
+ r.Condition.CreatedBefore, _ = time.Parse(rfc3339Date, rr.Condition.CreatedBefore)
+ }
+ l.Rules = append(l.Rules, r)
+ }
+ return l
+}
+
+// Objects returns an iterator over the objects in the bucket that match the Query q.
+// If q is nil, no filtering is done.
+func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
+ it := &ObjectIterator{
+ ctx: ctx,
+ bucket: b,
+ }
+ it.pageInfo, it.nextFunc = iterator.NewPageInfo(
+ it.fetch,
+ func() int { return len(it.items) },
+ func() interface{} { b := it.items; it.items = nil; return b })
+ if q != nil {
+ it.query = *q
+ }
+ return it
+}
+
+// An ObjectIterator is an iterator over ObjectAttrs.
+type ObjectIterator struct {
+ ctx context.Context
+ bucket *BucketHandle
+ query Query
+ pageInfo *iterator.PageInfo
+ nextFunc func() error
+ items []*ObjectAttrs
+}
+
+// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
+func (it *ObjectIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
+
+// Next returns the next result. Its second return value is iterator.Done if
+// there are no more results. Once Next returns iterator.Done, all subsequent
+// calls will return iterator.Done.
+//
+// If Query.Delimiter is non-empty, some of the ObjectAttrs returned by Next will
+// have a non-empty Prefix field, and a zero value for all other fields. These
+// represent prefixes.
+func (it *ObjectIterator) Next() (*ObjectAttrs, error) {
+ if err := it.nextFunc(); err != nil {
+ return nil, err
+ }
+ item := it.items[0]
+ it.items = it.items[1:]
+ return item, nil
+}
+
+func (it *ObjectIterator) fetch(pageSize int, pageToken string) (string, error) {
+ req := it.bucket.c.raw.Objects.List(it.bucket.name)
+ setClientHeader(req.Header())
+ req.Projection("full")
+ req.Delimiter(it.query.Delimiter)
+ req.Prefix(it.query.Prefix)
+ req.Versions(it.query.Versions)
+ req.PageToken(pageToken)
+ if it.bucket.userProject != "" {
+ req.UserProject(it.bucket.userProject)
+ }
+ if pageSize > 0 {
+ req.MaxResults(int64(pageSize))
+ }
+ var resp *raw.Objects
+ var err error
+ err = runWithRetry(it.ctx, func() error {
+ resp, err = req.Context(it.ctx).Do()
+ return err
+ })
+ if err != nil {
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ err = ErrBucketNotExist
+ }
+ return "", err
+ }
+ for _, item := range resp.Items {
+ it.items = append(it.items, newObject(item))
+ }
+ for _, prefix := range resp.Prefixes {
+ it.items = append(it.items, &ObjectAttrs{Prefix: prefix})
+ }
+ return resp.NextPageToken, nil
+}
+
+// TODO(jbd): Add storage.buckets.update.
+
+// Buckets returns an iterator over the buckets in the project. You may
+// optionally set the iterator's Prefix field to restrict the list to buckets
+// whose names begin with the prefix. By default, all buckets in the project
+// are returned.
+func (c *Client) Buckets(ctx context.Context, projectID string) *BucketIterator {
+ it := &BucketIterator{
+ ctx: ctx,
+ client: c,
+ projectID: projectID,
+ }
+ it.pageInfo, it.nextFunc = iterator.NewPageInfo(
+ it.fetch,
+ func() int { return len(it.buckets) },
+ func() interface{} { b := it.buckets; it.buckets = nil; return b })
+ return it
+}
+
+// A BucketIterator is an iterator over BucketAttrs.
+type BucketIterator struct {
+ // Prefix restricts the iterator to buckets whose names begin with it.
+ Prefix string
+
+ ctx context.Context
+ client *Client
+ projectID string
+ buckets []*BucketAttrs
+ pageInfo *iterator.PageInfo
+ nextFunc func() error
+}
+
+// Next returns the next result. Its second return value is iterator.Done if
+// there are no more results. Once Next returns iterator.Done, all subsequent
+// calls will return iterator.Done.
+func (it *BucketIterator) Next() (*BucketAttrs, error) {
+ if err := it.nextFunc(); err != nil {
+ return nil, err
+ }
+ b := it.buckets[0]
+ it.buckets = it.buckets[1:]
+ return b, nil
+}
+
+// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
+func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
+
+func (it *BucketIterator) fetch(pageSize int, pageToken string) (string, error) {
+ req := it.client.raw.Buckets.List(it.projectID)
+ setClientHeader(req.Header())
+ req.Projection("full")
+ req.Prefix(it.Prefix)
+ req.PageToken(pageToken)
+ if pageSize > 0 {
+ req.MaxResults(int64(pageSize))
+ }
+ var resp *raw.Buckets
+ var err error
+ err = runWithRetry(it.ctx, func() error {
+ resp, err = req.Context(it.ctx).Do()
+ return err
+ })
+ if err != nil {
+ return "", err
+ }
+ for _, item := range resp.Items {
+ it.buckets = append(it.buckets, newBucket(item))
+ }
+ return resp.NextPageToken, nil
+}
diff --git a/vendor/cloud.google.com/go/storage/copy.go b/vendor/cloud.google.com/go/storage/copy.go
new file mode 100644
index 0000000..d0a999c
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/copy.go
@@ -0,0 +1,201 @@
+// Copyright 2016 Google Inc. 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.
+
+package storage
+
+import (
+ "errors"
+ "fmt"
+
+ "golang.org/x/net/context"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// CopierFrom creates a Copier that can copy src to dst.
+// You can immediately call Run on the returned Copier, or
+// you can configure it first.
+//
+// For Requester Pays buckets, the user project of dst is billed, unless it is empty,
+// in which case the user project of src is billed.
+func (dst *ObjectHandle) CopierFrom(src *ObjectHandle) *Copier {
+ return &Copier{dst: dst, src: src}
+}
+
+// A Copier copies a source object to a destination.
+type Copier struct {
+ // ObjectAttrs are optional attributes to set on the destination object.
+ // Any attributes must be initialized before any calls on the Copier. Nil
+ // or zero-valued attributes are ignored.
+ ObjectAttrs
+
+ // RewriteToken can be set before calling Run to resume a copy
+ // operation. After Run returns a non-nil error, RewriteToken will
+ // have been updated to contain the value needed to resume the copy.
+ RewriteToken string
+
+ // ProgressFunc can be used to monitor the progress of a multi-RPC copy
+ // operation. If ProgressFunc is not nil and copying requires multiple
+ // calls to the underlying service (see
+ // https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite), then
+ // ProgressFunc will be invoked after each call with the number of bytes of
+ // content copied so far and the total size in bytes of the source object.
+ //
+ // ProgressFunc is intended to make upload progress available to the
+ // application. For example, the implementation of ProgressFunc may update
+ // a progress bar in the application's UI, or log the result of
+ // float64(copiedBytes)/float64(totalBytes).
+ //
+ // ProgressFunc should return quickly without blocking.
+ ProgressFunc func(copiedBytes, totalBytes uint64)
+
+ dst, src *ObjectHandle
+}
+
+// Run performs the copy.
+func (c *Copier) Run(ctx context.Context) (*ObjectAttrs, error) {
+ if err := c.src.validate(); err != nil {
+ return nil, err
+ }
+ if err := c.dst.validate(); err != nil {
+ return nil, err
+ }
+ // Convert destination attributes to raw form, omitting the bucket.
+ // If the bucket is included but name or content-type aren't, the service
+ // returns a 400 with "Required" as the only message. Omitting the bucket
+ // does not cause any problems.
+ rawObject := c.ObjectAttrs.toRawObject("")
+ for {
+ res, err := c.callRewrite(ctx, rawObject)
+ if err != nil {
+ return nil, err
+ }
+ if c.ProgressFunc != nil {
+ c.ProgressFunc(uint64(res.TotalBytesRewritten), uint64(res.ObjectSize))
+ }
+ if res.Done { // Finished successfully.
+ return newObject(res.Resource), nil
+ }
+ }
+}
+
+func (c *Copier) callRewrite(ctx context.Context, rawObj *raw.Object) (*raw.RewriteResponse, error) {
+ call := c.dst.c.raw.Objects.Rewrite(c.src.bucket, c.src.object, c.dst.bucket, c.dst.object, rawObj)
+
+ call.Context(ctx).Projection("full")
+ if c.RewriteToken != "" {
+ call.RewriteToken(c.RewriteToken)
+ }
+ if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil {
+ return nil, err
+ }
+ if c.dst.userProject != "" {
+ call.UserProject(c.dst.userProject)
+ } else if c.src.userProject != "" {
+ call.UserProject(c.src.userProject)
+ }
+ if err := applySourceConds(c.src.gen, c.src.conds, call); err != nil {
+ return nil, err
+ }
+ if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ if err := setEncryptionHeaders(call.Header(), c.src.encryptionKey, true); err != nil {
+ return nil, err
+ }
+ var res *raw.RewriteResponse
+ var err error
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { res, err = call.Do(); return err })
+ if err != nil {
+ return nil, err
+ }
+ c.RewriteToken = res.RewriteToken
+ return res, nil
+}
+
+// ComposerFrom creates a Composer that can compose srcs into dst.
+// You can immediately call Run on the returned Composer, or you can
+// configure it first.
+//
+// The encryption key for the destination object will be used to decrypt all
+// source objects and encrypt the destination object. It is an error
+// to specify an encryption key for any of the source objects.
+func (dst *ObjectHandle) ComposerFrom(srcs ...*ObjectHandle) *Composer {
+ return &Composer{dst: dst, srcs: srcs}
+}
+
+// A Composer composes source objects into a destination object.
+//
+// For Requester Pays buckets, the user project of dst is billed.
+type Composer struct {
+ // ObjectAttrs are optional attributes to set on the destination object.
+ // Any attributes must be initialized before any calls on the Composer. Nil
+ // or zero-valued attributes are ignored.
+ ObjectAttrs
+
+ dst *ObjectHandle
+ srcs []*ObjectHandle
+}
+
+// Run performs the compose operation.
+func (c *Composer) Run(ctx context.Context) (*ObjectAttrs, error) {
+ if err := c.dst.validate(); err != nil {
+ return nil, err
+ }
+ if len(c.srcs) == 0 {
+ return nil, errors.New("storage: at least one source object must be specified")
+ }
+
+ req := &raw.ComposeRequest{}
+ // Compose requires a non-empty Destination, so we always set it,
+ // even if the caller-provided ObjectAttrs is the zero value.
+ req.Destination = c.ObjectAttrs.toRawObject(c.dst.bucket)
+ for _, src := range c.srcs {
+ if err := src.validate(); err != nil {
+ return nil, err
+ }
+ if src.bucket != c.dst.bucket {
+ return nil, fmt.Errorf("storage: all source objects must be in bucket %q, found %q", c.dst.bucket, src.bucket)
+ }
+ if src.encryptionKey != nil {
+ return nil, fmt.Errorf("storage: compose source %s.%s must not have encryption key", src.bucket, src.object)
+ }
+ srcObj := &raw.ComposeRequestSourceObjects{
+ Name: src.object,
+ }
+ if err := applyConds("ComposeFrom source", src.gen, src.conds, composeSourceObj{srcObj}); err != nil {
+ return nil, err
+ }
+ req.SourceObjects = append(req.SourceObjects, srcObj)
+ }
+
+ call := c.dst.c.raw.Objects.Compose(c.dst.bucket, c.dst.object, req).Context(ctx)
+ if err := applyConds("ComposeFrom destination", c.dst.gen, c.dst.conds, call); err != nil {
+ return nil, err
+ }
+ if c.dst.userProject != "" {
+ call.UserProject(c.dst.userProject)
+ }
+ if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ var obj *raw.Object
+ var err error
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
+ if err != nil {
+ return nil, err
+ }
+ return newObject(obj), nil
+}
diff --git a/vendor/cloud.google.com/go/storage/doc.go b/vendor/cloud.google.com/go/storage/doc.go
new file mode 100644
index 0000000..06961b6
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/doc.go
@@ -0,0 +1,168 @@
+// Copyright 2016 Google Inc. 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.
+
+/*
+Package storage provides an easy way to work with Google Cloud Storage.
+Google Cloud Storage stores data in named objects, which are grouped into buckets.
+
+More information about Google Cloud Storage is available at
+https://cloud.google.com/storage/docs.
+
+All of the methods of this package use exponential backoff to retry calls
+that fail with certain errors, as described in
+https://cloud.google.com/storage/docs/exponential-backoff.
+
+Note: This package is in beta. Some backwards-incompatible changes may occur.
+
+
+Creating a Client
+
+To start working with this package, create a client:
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+
+The client will use your default application credentials.
+
+If you only wish to access public data, you can create
+an unauthenticated client with
+
+ client, err := storage.NewClient(ctx, option.WithoutAuthentication())
+
+Buckets
+
+A Google Cloud Storage bucket is a collection of objects. To work with a
+bucket, make a bucket handle:
+
+ bkt := client.Bucket(bucketName)
+
+A handle is a reference to a bucket. You can have a handle even if the
+bucket doesn't exist yet. To create a bucket in Google Cloud Storage,
+call Create on the handle:
+
+ if err := bkt.Create(ctx, projectID, nil); err != nil {
+ // TODO: Handle error.
+ }
+
+Note that although buckets are associated with projects, bucket names are
+global across all projects.
+
+Each bucket has associated metadata, represented in this package by
+BucketAttrs. The third argument to BucketHandle.Create allows you to set
+the intial BucketAttrs of a bucket. To retrieve a bucket's attributes, use
+Attrs:
+
+ attrs, err := bkt.Attrs(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ fmt.Printf("bucket %s, created at %s, is located in %s with storage class %s\n",
+ attrs.Name, attrs.Created, attrs.Location, attrs.StorageClass)
+
+Objects
+
+An object holds arbitrary data as a sequence of bytes, like a file. You
+refer to objects using a handle, just as with buckets. You can use the
+standard Go io.Reader and io.Writer interfaces to read and write
+object data:
+
+ obj := bkt.Object("data")
+ // Write something to obj.
+ // w implements io.Writer.
+ w := obj.NewWriter(ctx)
+ // Write some text to obj. This will overwrite whatever is there.
+ if _, err := fmt.Fprintf(w, "This object contains text.\n"); err != nil {
+ // TODO: Handle error.
+ }
+ // Close, just like writing a file.
+ if err := w.Close(); err != nil {
+ // TODO: Handle error.
+ }
+
+ // Read it back.
+ r, err := obj.NewReader(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ defer r.Close()
+ if _, err := io.Copy(os.Stdout, r); err != nil {
+ // TODO: Handle error.
+ }
+ // Prints "This object contains text."
+
+Objects also have attributes, which you can fetch with Attrs:
+
+ objAttrs, err := obj.Attrs(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ fmt.Printf("object %s has size %d and can be read using %s\n",
+ objAttrs.Name, objAttrs.Size, objAttrs.MediaLink)
+
+ACLs
+
+Both objects and buckets have ACLs (Access Control Lists). An ACL is a list of
+ACLRules, each of which specifies the role of a user, group or project. ACLs
+are suitable for fine-grained control, but you may prefer using IAM to control
+access at the project level (see
+https://cloud.google.com/storage/docs/access-control/iam).
+
+To list the ACLs of a bucket or object, obtain an ACLHandle and call its List method:
+
+ acls, err := obj.ACL().List(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ for _, rule := range acls {
+ fmt.Printf("%s has role %s\n", rule.Entity, rule.Role)
+ }
+
+You can also set and delete ACLs.
+
+Conditions
+
+Every object has a generation and a metageneration. The generation changes
+whenever the content changes, and the metageneration changes whenever the
+metadata changes. Conditions let you check these values before an operation;
+the operation only executes if the conditions match. You can use conditions to
+prevent race conditions in read-modify-write operations.
+
+For example, say you've read an object's metadata into objAttrs. Now
+you want to write to that object, but only if its contents haven't changed
+since you read it. Here is how to express that:
+
+ w = obj.If(storage.Conditions{GenerationMatch: objAttrs.Generation}).NewWriter(ctx)
+ // Proceed with writing as above.
+
+Signed URLs
+
+You can obtain a URL that lets anyone read or write an object for a limited time.
+You don't need to create a client to do this. See the documentation of
+SignedURL for details.
+
+ url, err := storage.SignedURL(bucketName, "shared-object", opts)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ fmt.Println(url)
+
+Authentication
+
+See examples of authorization and authentication at
+https://godoc.org/cloud.google.com/go#pkg-examples.
+*/
+package storage // import "cloud.google.com/go/storage"
diff --git a/vendor/cloud.google.com/go/storage/go110.go b/vendor/cloud.google.com/go/storage/go110.go
new file mode 100644
index 0000000..b85e8c3
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/go110.go
@@ -0,0 +1,30 @@
+// Copyright 2017 Google Inc. 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.
+
+// +build go1.10
+
+package storage
+
+import "google.golang.org/api/googleapi"
+
+func shouldRetry(err error) bool {
+ switch e := err.(type) {
+ case *googleapi.Error:
+ // Retry on 429 and 5xx, according to
+ // https://cloud.google.com/storage/docs/exponential-backoff.
+ return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
+ default:
+ return false
+ }
+}
diff --git a/vendor/cloud.google.com/go/storage/go17.go b/vendor/cloud.google.com/go/storage/go17.go
new file mode 100644
index 0000000..982db4e
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/go17.go
@@ -0,0 +1,26 @@
+// Copyright 2017 Google Inc. 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.
+
+// +build go1.7
+
+package storage
+
+import (
+ "context"
+ "net/http"
+)
+
+func withContext(r *http.Request, ctx context.Context) *http.Request {
+ return r.WithContext(ctx)
+}
diff --git a/vendor/cloud.google.com/go/storage/iam.go b/vendor/cloud.google.com/go/storage/iam.go
new file mode 100644
index 0000000..9365509
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/iam.go
@@ -0,0 +1,121 @@
+// Copyright 2017 Google Inc. 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.
+
+package storage
+
+import (
+ "cloud.google.com/go/iam"
+ "golang.org/x/net/context"
+ raw "google.golang.org/api/storage/v1"
+ iampb "google.golang.org/genproto/googleapis/iam/v1"
+)
+
+// IAM provides access to IAM access control for the bucket.
+func (b *BucketHandle) IAM() *iam.Handle {
+ return iam.InternalNewHandleClient(&iamClient{
+ raw: b.c.raw,
+ userProject: b.userProject,
+ }, b.name)
+}
+
+// iamClient implements the iam.client interface.
+type iamClient struct {
+ raw *raw.Service
+ userProject string
+}
+
+func (c *iamClient) Get(ctx context.Context, resource string) (*iampb.Policy, error) {
+ call := c.raw.Buckets.GetIamPolicy(resource)
+ setClientHeader(call.Header())
+ if c.userProject != "" {
+ call.UserProject(c.userProject)
+ }
+ var rp *raw.Policy
+ var err error
+ err = runWithRetry(ctx, func() error {
+ rp, err = call.Context(ctx).Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return iamFromStoragePolicy(rp), nil
+}
+
+func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) error {
+ rp := iamToStoragePolicy(p)
+ call := c.raw.Buckets.SetIamPolicy(resource, rp)
+ setClientHeader(call.Header())
+ if c.userProject != "" {
+ call.UserProject(c.userProject)
+ }
+ return runWithRetry(ctx, func() error {
+ _, err := call.Context(ctx).Do()
+ return err
+ })
+}
+
+func (c *iamClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
+ call := c.raw.Buckets.TestIamPermissions(resource, perms)
+ setClientHeader(call.Header())
+ if c.userProject != "" {
+ call.UserProject(c.userProject)
+ }
+ var res *raw.TestIamPermissionsResponse
+ var err error
+ err = runWithRetry(ctx, func() error {
+ res, err = call.Context(ctx).Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return res.Permissions, nil
+}
+
+func iamToStoragePolicy(ip *iampb.Policy) *raw.Policy {
+ return &raw.Policy{
+ Bindings: iamToStorageBindings(ip.Bindings),
+ Etag: string(ip.Etag),
+ }
+}
+
+func iamToStorageBindings(ibs []*iampb.Binding) []*raw.PolicyBindings {
+ var rbs []*raw.PolicyBindings
+ for _, ib := range ibs {
+ rbs = append(rbs, &raw.PolicyBindings{
+ Role: ib.Role,
+ Members: ib.Members,
+ })
+ }
+ return rbs
+}
+
+func iamFromStoragePolicy(rp *raw.Policy) *iampb.Policy {
+ return &iampb.Policy{
+ Bindings: iamFromStorageBindings(rp.Bindings),
+ Etag: []byte(rp.Etag),
+ }
+}
+
+func iamFromStorageBindings(rbs []*raw.PolicyBindings) []*iampb.Binding {
+ var ibs []*iampb.Binding
+ for _, rb := range rbs {
+ ibs = append(ibs, &iampb.Binding{
+ Role: rb.Role,
+ Members: rb.Members,
+ })
+ }
+ return ibs
+}
diff --git a/vendor/cloud.google.com/go/storage/invoke.go b/vendor/cloud.google.com/go/storage/invoke.go
new file mode 100644
index 0000000..46423a8
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/invoke.go
@@ -0,0 +1,36 @@
+// Copyright 2014 Google Inc. 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.
+
+package storage
+
+import (
+ "cloud.google.com/go/internal"
+ gax "github.com/googleapis/gax-go"
+ "golang.org/x/net/context"
+)
+
+// runWithRetry calls the function until it returns nil or a non-retryable error, or
+// the context is done.
+func runWithRetry(ctx context.Context, call func() error) error {
+ return internal.Retry(ctx, gax.Backoff{}, func() (stop bool, err error) {
+ err = call()
+ if err == nil {
+ return true, nil
+ }
+ if shouldRetry(err) {
+ return false, nil
+ }
+ return true, err
+ })
+}
diff --git a/vendor/cloud.google.com/go/storage/not_go110.go b/vendor/cloud.google.com/go/storage/not_go110.go
new file mode 100644
index 0000000..c354e74
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/not_go110.go
@@ -0,0 +1,40 @@
+// Copyright 2017 Google Inc. 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.
+
+// +build !go1.10
+
+package storage
+
+import (
+ "net/url"
+ "strings"
+
+ "google.golang.org/api/googleapi"
+)
+
+func shouldRetry(err error) bool {
+ switch e := err.(type) {
+ case *googleapi.Error:
+ // Retry on 429 and 5xx, according to
+ // https://cloud.google.com/storage/docs/exponential-backoff.
+ return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
+ case *url.Error:
+ // Retry on REFUSED_STREAM.
+ // Unfortunately the error type is unexported, so we resort to string
+ // matching.
+ return strings.Contains(e.Error(), "REFUSED_STREAM")
+ default:
+ return false
+ }
+}
diff --git a/vendor/cloud.google.com/go/storage/not_go17.go b/vendor/cloud.google.com/go/storage/not_go17.go
new file mode 100644
index 0000000..1f6f7ae
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/not_go17.go
@@ -0,0 +1,26 @@
+// Copyright 2017 Google Inc. 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.
+
+// +build !go1.7
+
+package storage
+
+import (
+ "net/http"
+)
+
+func withContext(r *http.Request, _ interface{}) *http.Request {
+ // In Go 1.6 and below, ignore the context.
+ return r
+}
diff --git a/vendor/cloud.google.com/go/storage/notifications.go b/vendor/cloud.google.com/go/storage/notifications.go
new file mode 100644
index 0000000..b95dd45
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/notifications.go
@@ -0,0 +1,179 @@
+// Copyright 2017 Google Inc. 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.
+
+package storage
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+
+ "golang.org/x/net/context"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// A Notification describes how to send Cloud PubSub messages when certain
+// events occur in a bucket.
+type Notification struct {
+ //The ID of the notification.
+ ID string
+
+ // The ID of the topic to which this subscription publishes.
+ TopicID string
+
+ // The ID of the project to which the topic belongs.
+ TopicProjectID string
+
+ // Only send notifications about listed event types. If empty, send notifications
+ // for all event types.
+ // See https://cloud.google.com/storage/docs/pubsub-notifications#events.
+ EventTypes []string
+
+ // If present, only apply this notification configuration to object names that
+ // begin with this prefix.
+ ObjectNamePrefix string
+
+ // An optional list of additional attributes to attach to each Cloud PubSub
+ // message published for this notification subscription.
+ CustomAttributes map[string]string
+
+ // The contents of the message payload.
+ // See https://cloud.google.com/storage/docs/pubsub-notifications#payload.
+ PayloadFormat string
+}
+
+// Values for Notification.PayloadFormat.
+const (
+ // Send no payload with notification messages.
+ NoPayload = "NONE"
+
+ // Send object metadata as JSON with notification messages.
+ JSONPayload = "JSON_API_V1"
+)
+
+// Values for Notification.EventTypes.
+const (
+ // Event that occurs when an object is successfully created.
+ ObjectFinalizeEvent = "OBJECT_FINALIZE"
+
+ // Event that occurs when the metadata of an existing object changes.
+ ObjectMetadataUpdateEvent = "OBJECT_METADATA_UPDATE"
+
+ // Event that occurs when an object is permanently deleted.
+ ObjectDeleteEvent = "OBJECT_DELETE"
+
+ // Event that occurs when the live version of an object becomes an
+ // archived version.
+ ObjectArchiveEvent = "OBJECT_ARCHIVE"
+)
+
+func toNotification(rn *raw.Notification) *Notification {
+ n := &Notification{
+ ID: rn.Id,
+ EventTypes: rn.EventTypes,
+ ObjectNamePrefix: rn.ObjectNamePrefix,
+ CustomAttributes: rn.CustomAttributes,
+ PayloadFormat: rn.PayloadFormat,
+ }
+ n.TopicProjectID, n.TopicID = parseNotificationTopic(rn.Topic)
+ return n
+}
+
+var topicRE = regexp.MustCompile("^//pubsub.googleapis.com/projects/([^/]+)/topics/([^/]+)")
+
+// parseNotificationTopic extracts the project and topic IDs from from the full
+// resource name returned by the service. If the name is malformed, it returns
+// "?" for both IDs.
+func parseNotificationTopic(nt string) (projectID, topicID string) {
+ matches := topicRE.FindStringSubmatch(nt)
+ if matches == nil {
+ return "?", "?"
+ }
+ return matches[1], matches[2]
+}
+
+func toRawNotification(n *Notification) *raw.Notification {
+ return &raw.Notification{
+ Id: n.ID,
+ Topic: fmt.Sprintf("//pubsub.googleapis.com/projects/%s/topics/%s",
+ n.TopicProjectID, n.TopicID),
+ EventTypes: n.EventTypes,
+ ObjectNamePrefix: n.ObjectNamePrefix,
+ CustomAttributes: n.CustomAttributes,
+ PayloadFormat: string(n.PayloadFormat),
+ }
+}
+
+// AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
+// and PayloadFormat, and must not set its ID. The other fields are all optional. The
+// returned Notification's ID can be used to refer to it.
+func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (*Notification, error) {
+ if n.ID != "" {
+ return nil, errors.New("storage: AddNotification: ID must not be set")
+ }
+ if n.TopicProjectID == "" {
+ return nil, errors.New("storage: AddNotification: missing TopicProjectID")
+ }
+ if n.TopicID == "" {
+ return nil, errors.New("storage: AddNotification: missing TopicID")
+ }
+ call := b.c.raw.Notifications.Insert(b.name, toRawNotification(n))
+ setClientHeader(call.Header())
+ if b.userProject != "" {
+ call.UserProject(b.userProject)
+ }
+ rn, err := call.Context(ctx).Do()
+ if err != nil {
+ return nil, err
+ }
+ return toNotification(rn), nil
+}
+
+// Notifications returns all the Notifications configured for this bucket, as a map
+// indexed by notification ID.
+func (b *BucketHandle) Notifications(ctx context.Context) (map[string]*Notification, error) {
+ call := b.c.raw.Notifications.List(b.name)
+ setClientHeader(call.Header())
+ if b.userProject != "" {
+ call.UserProject(b.userProject)
+ }
+ var res *raw.Notifications
+ var err error
+ err = runWithRetry(ctx, func() error {
+ res, err = call.Context(ctx).Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return notificationsToMap(res.Items), nil
+}
+
+func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
+ m := map[string]*Notification{}
+ for _, rn := range rns {
+ m[rn.Id] = toNotification(rn)
+ }
+ return m
+}
+
+// DeleteNotification deletes the notification with the given ID.
+func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) error {
+ call := b.c.raw.Notifications.Delete(b.name, id)
+ setClientHeader(call.Header())
+ if b.userProject != "" {
+ call.UserProject(b.userProject)
+ }
+ return call.Context(ctx).Do()
+}
diff --git a/vendor/cloud.google.com/go/storage/reader.go b/vendor/cloud.google.com/go/storage/reader.go
new file mode 100644
index 0000000..ef964f0
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/reader.go
@@ -0,0 +1,86 @@
+// Copyright 2016 Google Inc. 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.
+
+package storage
+
+import (
+ "fmt"
+ "hash/crc32"
+ "io"
+)
+
+var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
+
+// Reader reads a Cloud Storage object.
+// It implements io.Reader.
+type Reader struct {
+ body io.ReadCloser
+ remain, size int64
+ contentType string
+ contentEncoding string
+ cacheControl string
+ checkCRC bool // should we check the CRC?
+ wantCRC uint32 // the CRC32c value the server sent in the header
+ gotCRC uint32 // running crc
+}
+
+// Close closes the Reader. It must be called when done reading.
+func (r *Reader) Close() error {
+ return r.body.Close()
+}
+
+func (r *Reader) Read(p []byte) (int, error) {
+ n, err := r.body.Read(p)
+ if r.remain != -1 {
+ r.remain -= int64(n)
+ }
+ if r.checkCRC {
+ r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, p[:n])
+ // Check CRC here. It would be natural to check it in Close, but
+ // everybody defers Close on the assumption that it doesn't return
+ // anything worth looking at.
+ if r.remain == 0 && r.gotCRC != r.wantCRC {
+ return n, fmt.Errorf("storage: bad CRC on read: got %d, want %d",
+ r.gotCRC, r.wantCRC)
+ }
+ }
+ return n, err
+}
+
+// Size returns the size of the object in bytes.
+// The returned value is always the same and is not affected by
+// calls to Read or Close.
+func (r *Reader) Size() int64 {
+ return r.size
+}
+
+// Remain returns the number of bytes left to read, or -1 if unknown.
+func (r *Reader) Remain() int64 {
+ return r.remain
+}
+
+// ContentType returns the content type of the object.
+func (r *Reader) ContentType() string {
+ return r.contentType
+}
+
+// ContentEncoding returns the content encoding of the object.
+func (r *Reader) ContentEncoding() string {
+ return r.contentEncoding
+}
+
+// CacheControl returns the cache control of the object.
+func (r *Reader) CacheControl() string {
+ return r.cacheControl
+}
diff --git a/vendor/cloud.google.com/go/storage/storage.go b/vendor/cloud.google.com/go/storage/storage.go
new file mode 100644
index 0000000..c6ba1cb
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/storage.go
@@ -0,0 +1,1144 @@
+// Copyright 2014 Google Inc. 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.
+
+package storage
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+
+ "google.golang.org/api/option"
+ htransport "google.golang.org/api/transport/http"
+
+ "cloud.google.com/go/internal/optional"
+ "cloud.google.com/go/internal/version"
+ "golang.org/x/net/context"
+ "google.golang.org/api/googleapi"
+ raw "google.golang.org/api/storage/v1"
+)
+
+var (
+ ErrBucketNotExist = errors.New("storage: bucket doesn't exist")
+ ErrObjectNotExist = errors.New("storage: object doesn't exist")
+)
+
+const userAgent = "gcloud-golang-storage/20151204"
+
+const (
+ // ScopeFullControl grants permissions to manage your
+ // data and permissions in Google Cloud Storage.
+ ScopeFullControl = raw.DevstorageFullControlScope
+
+ // ScopeReadOnly grants permissions to
+ // view your data in Google Cloud Storage.
+ ScopeReadOnly = raw.DevstorageReadOnlyScope
+
+ // ScopeReadWrite grants permissions to manage your
+ // data in Google Cloud Storage.
+ ScopeReadWrite = raw.DevstorageReadWriteScope
+)
+
+var xGoogHeader = fmt.Sprintf("gl-go/%s gccl/%s", version.Go(), version.Repo)
+
+func setClientHeader(headers http.Header) {
+ headers.Set("x-goog-api-client", xGoogHeader)
+}
+
+// Client is a client for interacting with Google Cloud Storage.
+//
+// Clients should be reused instead of created as needed.
+// The methods of Client are safe for concurrent use by multiple goroutines.
+type Client struct {
+ hc *http.Client
+ raw *raw.Service
+}
+
+// NewClient creates a new Google Cloud Storage client.
+// The default scope is ScopeFullControl. To use a different scope, like ScopeReadOnly, use option.WithScopes.
+func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
+ o := []option.ClientOption{
+ option.WithScopes(ScopeFullControl),
+ option.WithUserAgent(userAgent),
+ }
+ opts = append(o, opts...)
+ hc, ep, err := htransport.NewClient(ctx, opts...)
+ if err != nil {
+ return nil, fmt.Errorf("dialing: %v", err)
+ }
+ rawService, err := raw.New(hc)
+ if err != nil {
+ return nil, fmt.Errorf("storage client: %v", err)
+ }
+ if ep != "" {
+ rawService.BasePath = ep
+ }
+ return &Client{
+ hc: hc,
+ raw: rawService,
+ }, nil
+}
+
+// Close closes the Client.
+//
+// Close need not be called at program exit.
+func (c *Client) Close() error {
+ // Set fields to nil so that subsequent uses
+ // will panic.
+ c.hc = nil
+ c.raw = nil
+ return nil
+}
+
+// SignedURLOptions allows you to restrict the access to the signed URL.
+type SignedURLOptions struct {
+ // GoogleAccessID represents the authorizer of the signed URL generation.
+ // It is typically the Google service account client email address from
+ // the Google Developers Console in the form of "xxx@developer.gserviceaccount.com".
+ // Required.
+ GoogleAccessID string
+
+ // PrivateKey is the Google service account private key. It is obtainable
+ // from the Google Developers Console.
+ // At https://console.developers.google.com/project//apiui/credential,
+ // create a service account client ID or reuse one of your existing service account
+ // credentials. Click on the "Generate new P12 key" to generate and download
+ // a new private key. Once you download the P12 file, use the following command
+ // to convert it into a PEM file.
+ //
+ // $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
+ //
+ // Provide the contents of the PEM file as a byte slice.
+ // Exactly one of PrivateKey or SignBytes must be non-nil.
+ PrivateKey []byte
+
+ // SignBytes is a function for implementing custom signing.
+ // If your application is running on Google App Engine, you can use appengine's internal signing function:
+ // ctx := appengine.NewContext(request)
+ // acc, _ := appengine.ServiceAccount(ctx)
+ // url, err := SignedURL("bucket", "object", &SignedURLOptions{
+ // GoogleAccessID: acc,
+ // SignBytes: func(b []byte) ([]byte, error) {
+ // _, signedBytes, err := appengine.SignBytes(ctx, b)
+ // return signedBytes, err
+ // },
+ // // etc.
+ // })
+ //
+ // Exactly one of PrivateKey or SignBytes must be non-nil.
+ SignBytes func([]byte) ([]byte, error)
+
+ // Method is the HTTP method to be used with the signed URL.
+ // Signed URLs can be used with GET, HEAD, PUT, and DELETE requests.
+ // Required.
+ Method string
+
+ // Expires is the expiration time on the signed URL. It must be
+ // a datetime in the future.
+ // Required.
+ Expires time.Time
+
+ // ContentType is the content type header the client must provide
+ // to use the generated signed URL.
+ // Optional.
+ ContentType string
+
+ // Headers is a list of extension headers the client must provide
+ // in order to use the generated signed URL.
+ // Optional.
+ Headers []string
+
+ // MD5 is the base64 encoded MD5 checksum of the file.
+ // If provided, the client should provide the exact value on the request
+ // header in order to use the signed URL.
+ // Optional.
+ MD5 string
+}
+
+// SignedURL returns a URL for the specified object. Signed URLs allow
+// the users access to a restricted resource for a limited time without having a
+// Google account or signing in. For more information about the signed
+// URLs, see https://cloud.google.com/storage/docs/accesscontrol#Signed-URLs.
+func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
+ if opts == nil {
+ return "", errors.New("storage: missing required SignedURLOptions")
+ }
+ if opts.GoogleAccessID == "" {
+ return "", errors.New("storage: missing required GoogleAccessID")
+ }
+ if (opts.PrivateKey == nil) == (opts.SignBytes == nil) {
+ return "", errors.New("storage: exactly one of PrivateKey or SignedBytes must be set")
+ }
+ if opts.Method == "" {
+ return "", errors.New("storage: missing required method option")
+ }
+ if opts.Expires.IsZero() {
+ return "", errors.New("storage: missing required expires option")
+ }
+ if opts.MD5 != "" {
+ md5, err := base64.StdEncoding.DecodeString(opts.MD5)
+ if err != nil || len(md5) != 16 {
+ return "", errors.New("storage: invalid MD5 checksum")
+ }
+ }
+
+ signBytes := opts.SignBytes
+ if opts.PrivateKey != nil {
+ key, err := parseKey(opts.PrivateKey)
+ if err != nil {
+ return "", err
+ }
+ signBytes = func(b []byte) ([]byte, error) {
+ sum := sha256.Sum256(b)
+ return rsa.SignPKCS1v15(
+ rand.Reader,
+ key,
+ crypto.SHA256,
+ sum[:],
+ )
+ }
+ }
+
+ u := &url.URL{
+ Path: fmt.Sprintf("/%s/%s", bucket, name),
+ }
+
+ buf := &bytes.Buffer{}
+ fmt.Fprintf(buf, "%s\n", opts.Method)
+ fmt.Fprintf(buf, "%s\n", opts.MD5)
+ fmt.Fprintf(buf, "%s\n", opts.ContentType)
+ fmt.Fprintf(buf, "%d\n", opts.Expires.Unix())
+ if len(opts.Headers) > 0 {
+ fmt.Fprintf(buf, "%s\n", strings.Join(opts.Headers, "\n"))
+ }
+ fmt.Fprintf(buf, "%s", u.String())
+
+ b, err := signBytes(buf.Bytes())
+ if err != nil {
+ return "", err
+ }
+ encoded := base64.StdEncoding.EncodeToString(b)
+ u.Scheme = "https"
+ u.Host = "storage.googleapis.com"
+ q := u.Query()
+ q.Set("GoogleAccessId", opts.GoogleAccessID)
+ q.Set("Expires", fmt.Sprintf("%d", opts.Expires.Unix()))
+ q.Set("Signature", string(encoded))
+ u.RawQuery = q.Encode()
+ return u.String(), nil
+}
+
+// ObjectHandle provides operations on an object in a Google Cloud Storage bucket.
+// Use BucketHandle.Object to get a handle.
+type ObjectHandle struct {
+ c *Client
+ bucket string
+ object string
+ acl ACLHandle
+ gen int64 // a negative value indicates latest
+ conds *Conditions
+ encryptionKey []byte // AES-256 key
+ userProject string // for requester-pays buckets
+ readCompressed bool // Accept-Encoding: gzip
+}
+
+// ACL provides access to the object's access control list.
+// This controls who can read and write this object.
+// This call does not perform any network operations.
+func (o *ObjectHandle) ACL() *ACLHandle {
+ return &o.acl
+}
+
+// Generation returns a new ObjectHandle that operates on a specific generation
+// of the object.
+// By default, the handle operates on the latest generation. Not
+// all operations work when given a specific generation; check the API
+// endpoints at https://cloud.google.com/storage/docs/json_api/ for details.
+func (o *ObjectHandle) Generation(gen int64) *ObjectHandle {
+ o2 := *o
+ o2.gen = gen
+ return &o2
+}
+
+// If returns a new ObjectHandle that applies a set of preconditions.
+// Preconditions already set on the ObjectHandle are ignored.
+// Operations on the new handle will only occur if the preconditions are
+// satisfied. See https://cloud.google.com/storage/docs/generations-preconditions
+// for more details.
+func (o *ObjectHandle) If(conds Conditions) *ObjectHandle {
+ o2 := *o
+ o2.conds = &conds
+ return &o2
+}
+
+// Key returns a new ObjectHandle that uses the supplied encryption
+// key to encrypt and decrypt the object's contents.
+//
+// Encryption key must be a 32-byte AES-256 key.
+// See https://cloud.google.com/storage/docs/encryption for details.
+func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle {
+ o2 := *o
+ o2.encryptionKey = encryptionKey
+ return &o2
+}
+
+// Attrs returns meta information about the object.
+// ErrObjectNotExist will be returned if the object is not found.
+func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
+ if err := o.validate(); err != nil {
+ return nil, err
+ }
+ call := o.c.raw.Objects.Get(o.bucket, o.object).Projection("full").Context(ctx)
+ if err := applyConds("Attrs", o.gen, o.conds, call); err != nil {
+ return nil, err
+ }
+ if o.userProject != "" {
+ call.UserProject(o.userProject)
+ }
+ if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ var obj *raw.Object
+ var err error
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ return nil, ErrObjectNotExist
+ }
+ if err != nil {
+ return nil, err
+ }
+ return newObject(obj), nil
+}
+
+// Update updates an object with the provided attributes.
+// All zero-value attributes are ignored.
+// ErrObjectNotExist will be returned if the object is not found.
+func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (*ObjectAttrs, error) {
+ if err := o.validate(); err != nil {
+ return nil, err
+ }
+ var attrs ObjectAttrs
+ // Lists of fields to send, and set to null, in the JSON.
+ var forceSendFields, nullFields []string
+ if uattrs.ContentType != nil {
+ attrs.ContentType = optional.ToString(uattrs.ContentType)
+ // For ContentType, sending the empty string is a no-op.
+ // Instead we send a null.
+ if attrs.ContentType == "" {
+ nullFields = append(nullFields, "ContentType")
+ } else {
+ forceSendFields = append(forceSendFields, "ContentType")
+ }
+ }
+ if uattrs.ContentLanguage != nil {
+ attrs.ContentLanguage = optional.ToString(uattrs.ContentLanguage)
+ // For ContentLanguage it's an error to send the empty string.
+ // Instead we send a null.
+ if attrs.ContentLanguage == "" {
+ nullFields = append(nullFields, "ContentLanguage")
+ } else {
+ forceSendFields = append(forceSendFields, "ContentLanguage")
+ }
+ }
+ if uattrs.ContentEncoding != nil {
+ attrs.ContentEncoding = optional.ToString(uattrs.ContentEncoding)
+ forceSendFields = append(forceSendFields, "ContentEncoding")
+ }
+ if uattrs.ContentDisposition != nil {
+ attrs.ContentDisposition = optional.ToString(uattrs.ContentDisposition)
+ forceSendFields = append(forceSendFields, "ContentDisposition")
+ }
+ if uattrs.CacheControl != nil {
+ attrs.CacheControl = optional.ToString(uattrs.CacheControl)
+ forceSendFields = append(forceSendFields, "CacheControl")
+ }
+ if uattrs.Metadata != nil {
+ attrs.Metadata = uattrs.Metadata
+ if len(attrs.Metadata) == 0 {
+ // Sending the empty map is a no-op. We send null instead.
+ nullFields = append(nullFields, "Metadata")
+ } else {
+ forceSendFields = append(forceSendFields, "Metadata")
+ }
+ }
+ if uattrs.ACL != nil {
+ attrs.ACL = uattrs.ACL
+ // It's an error to attempt to delete the ACL, so
+ // we don't append to nullFields here.
+ forceSendFields = append(forceSendFields, "Acl")
+ }
+ rawObj := attrs.toRawObject(o.bucket)
+ rawObj.ForceSendFields = forceSendFields
+ rawObj.NullFields = nullFields
+ call := o.c.raw.Objects.Patch(o.bucket, o.object, rawObj).Projection("full").Context(ctx)
+ if err := applyConds("Update", o.gen, o.conds, call); err != nil {
+ return nil, err
+ }
+ if o.userProject != "" {
+ call.UserProject(o.userProject)
+ }
+ if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ var obj *raw.Object
+ var err error
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ return nil, ErrObjectNotExist
+ }
+ if err != nil {
+ return nil, err
+ }
+ return newObject(obj), nil
+}
+
+// ObjectAttrsToUpdate is used to update the attributes of an object.
+// Only fields set to non-nil values will be updated.
+// Set a field to its zero value to delete it.
+//
+// For example, to change ContentType and delete ContentEncoding and
+// Metadata, use
+// ObjectAttrsToUpdate{
+// ContentType: "text/html",
+// ContentEncoding: "",
+// Metadata: map[string]string{},
+// }
+type ObjectAttrsToUpdate struct {
+ ContentType optional.String
+ ContentLanguage optional.String
+ ContentEncoding optional.String
+ ContentDisposition optional.String
+ CacheControl optional.String
+ Metadata map[string]string // set to map[string]string{} to delete
+ ACL []ACLRule
+}
+
+// Delete deletes the single specified object.
+func (o *ObjectHandle) Delete(ctx context.Context) error {
+ if err := o.validate(); err != nil {
+ return err
+ }
+ call := o.c.raw.Objects.Delete(o.bucket, o.object).Context(ctx)
+ if err := applyConds("Delete", o.gen, o.conds, call); err != nil {
+ return err
+ }
+ if o.userProject != "" {
+ call.UserProject(o.userProject)
+ }
+ // Encryption doesn't apply to Delete.
+ setClientHeader(call.Header())
+ err := runWithRetry(ctx, func() error { return call.Do() })
+ switch e := err.(type) {
+ case nil:
+ return nil
+ case *googleapi.Error:
+ if e.Code == http.StatusNotFound {
+ return ErrObjectNotExist
+ }
+ }
+ return err
+}
+
+// ReadCompressed when true causes the read to happen without decompressing.
+func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle {
+ o2 := *o
+ o2.readCompressed = compressed
+ return &o2
+}
+
+// NewReader creates a new Reader to read the contents of the
+// object.
+// ErrObjectNotExist will be returned if the object is not found.
+//
+// The caller must call Close on the returned Reader when done reading.
+func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
+ return o.NewRangeReader(ctx, 0, -1)
+}
+
+// NewRangeReader reads part of an object, reading at most length bytes
+// starting at the given offset. If length is negative, the object is read
+// until the end.
+func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (*Reader, error) {
+ if err := o.validate(); err != nil {
+ return nil, err
+ }
+ if offset < 0 {
+ return nil, fmt.Errorf("storage: invalid offset %d < 0", offset)
+ }
+ if o.conds != nil {
+ if err := o.conds.validate("NewRangeReader"); err != nil {
+ return nil, err
+ }
+ }
+ u := &url.URL{
+ Scheme: "https",
+ Host: "storage.googleapis.com",
+ Path: fmt.Sprintf("/%s/%s", o.bucket, o.object),
+ RawQuery: conditionsQuery(o.gen, o.conds),
+ }
+ verb := "GET"
+ if length == 0 {
+ verb = "HEAD"
+ }
+ req, err := http.NewRequest(verb, u.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+ req = withContext(req, ctx)
+ if length < 0 && offset > 0 {
+ req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
+ } else if length > 0 {
+ req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1))
+ }
+ if o.userProject != "" {
+ req.Header.Set("X-Goog-User-Project", o.userProject)
+ }
+ if o.readCompressed {
+ req.Header.Set("Accept-Encoding", "gzip")
+ }
+ if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ var res *http.Response
+ err = runWithRetry(ctx, func() error {
+ res, err = o.c.hc.Do(req)
+ if err != nil {
+ return err
+ }
+ if res.StatusCode == http.StatusNotFound {
+ res.Body.Close()
+ return ErrObjectNotExist
+ }
+ if res.StatusCode < 200 || res.StatusCode > 299 {
+ body, _ := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ return &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ Body: string(body),
+ }
+ }
+ if offset > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
+ res.Body.Close()
+ return errors.New("storage: partial request not satisfied")
+ }
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ var size int64 // total size of object, even if a range was requested.
+ if res.StatusCode == http.StatusPartialContent {
+ cr := strings.TrimSpace(res.Header.Get("Content-Range"))
+ if !strings.HasPrefix(cr, "bytes ") || !strings.Contains(cr, "/") {
+ return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
+ }
+ size, err = strconv.ParseInt(cr[strings.LastIndex(cr, "/")+1:], 10, 64)
+ if err != nil {
+ return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
+ }
+ } else {
+ size = res.ContentLength
+ }
+
+ remain := res.ContentLength
+ body := res.Body
+ if length == 0 {
+ remain = 0
+ body.Close()
+ body = emptyBody
+ }
+ var (
+ checkCRC bool
+ crc uint32
+ )
+ // Even if there is a CRC header, we can't compute the hash on partial data.
+ if remain == size {
+ crc, checkCRC = parseCRC32c(res)
+ }
+ return &Reader{
+ body: body,
+ size: size,
+ remain: remain,
+ contentType: res.Header.Get("Content-Type"),
+ contentEncoding: res.Header.Get("Content-Encoding"),
+ cacheControl: res.Header.Get("Cache-Control"),
+ wantCRC: crc,
+ checkCRC: checkCRC,
+ }, nil
+}
+
+func parseCRC32c(res *http.Response) (uint32, bool) {
+ const prefix = "crc32c="
+ for _, spec := range res.Header["X-Goog-Hash"] {
+ if strings.HasPrefix(spec, prefix) {
+ c, err := decodeUint32(spec[len(prefix):])
+ if err == nil {
+ return c, true
+ }
+ }
+ }
+ return 0, false
+}
+
+var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+
+// NewWriter returns a storage Writer that writes to the GCS object
+// associated with this ObjectHandle.
+//
+// A new object will be created unless an object with this name already exists.
+// Otherwise any previous object with the same name will be replaced.
+// The object will not be available (and any previous object will remain)
+// until Close has been called.
+//
+// Attributes can be set on the object by modifying the returned Writer's
+// ObjectAttrs field before the first call to Write. If no ContentType
+// attribute is specified, the content type will be automatically sniffed
+// using net/http.DetectContentType.
+//
+// It is the caller's responsibility to call Close when writing is done.
+func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer {
+ return &Writer{
+ ctx: ctx,
+ o: o,
+ donec: make(chan struct{}),
+ ObjectAttrs: ObjectAttrs{Name: o.object},
+ ChunkSize: googleapi.DefaultUploadChunkSize,
+ }
+}
+
+func (o *ObjectHandle) validate() error {
+ if o.bucket == "" {
+ return errors.New("storage: bucket name is empty")
+ }
+ if o.object == "" {
+ return errors.New("storage: object name is empty")
+ }
+ if !utf8.ValidString(o.object) {
+ return fmt.Errorf("storage: object name %q is not valid UTF-8", o.object)
+ }
+ return nil
+}
+
+// parseKey converts the binary contents of a private key file to an
+// *rsa.PrivateKey. It detects whether the private key is in a PEM container or
+// not. If so, it extracts the private key from PEM container before
+// conversion. It only supports PEM containers with no passphrase.
+func parseKey(key []byte) (*rsa.PrivateKey, error) {
+ if block, _ := pem.Decode(key); block != nil {
+ key = block.Bytes
+ }
+ parsedKey, err := x509.ParsePKCS8PrivateKey(key)
+ if err != nil {
+ parsedKey, err = x509.ParsePKCS1PrivateKey(key)
+ if err != nil {
+ return nil, err
+ }
+ }
+ parsed, ok := parsedKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("oauth2: private key is invalid")
+ }
+ return parsed, nil
+}
+
+func toRawObjectACL(oldACL []ACLRule) []*raw.ObjectAccessControl {
+ var acl []*raw.ObjectAccessControl
+ if len(oldACL) > 0 {
+ acl = make([]*raw.ObjectAccessControl, len(oldACL))
+ for i, rule := range oldACL {
+ acl[i] = &raw.ObjectAccessControl{
+ Entity: string(rule.Entity),
+ Role: string(rule.Role),
+ }
+ }
+ }
+ return acl
+}
+
+// toRawObject copies the editable attributes from o to the raw library's Object type.
+func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object {
+ acl := toRawObjectACL(o.ACL)
+ return &raw.Object{
+ Bucket: bucket,
+ Name: o.Name,
+ ContentType: o.ContentType,
+ ContentEncoding: o.ContentEncoding,
+ ContentLanguage: o.ContentLanguage,
+ CacheControl: o.CacheControl,
+ ContentDisposition: o.ContentDisposition,
+ StorageClass: o.StorageClass,
+ Acl: acl,
+ Metadata: o.Metadata,
+ }
+}
+
+// ObjectAttrs represents the metadata for a Google Cloud Storage (GCS) object.
+type ObjectAttrs struct {
+ // Bucket is the name of the bucket containing this GCS object.
+ // This field is read-only.
+ Bucket string
+
+ // Name is the name of the object within the bucket.
+ // This field is read-only.
+ Name string
+
+ // ContentType is the MIME type of the object's content.
+ ContentType string
+
+ // ContentLanguage is the content language of the object's content.
+ ContentLanguage string
+
+ // CacheControl is the Cache-Control header to be sent in the response
+ // headers when serving the object data.
+ CacheControl string
+
+ // ACL is the list of access control rules for the object.
+ ACL []ACLRule
+
+ // Owner is the owner of the object. This field is read-only.
+ //
+ // If non-zero, it is in the form of "user-".
+ Owner string
+
+ // Size is the length of the object's content. This field is read-only.
+ Size int64
+
+ // ContentEncoding is the encoding of the object's content.
+ ContentEncoding string
+
+ // ContentDisposition is the optional Content-Disposition header of the object
+ // sent in the response headers.
+ ContentDisposition string
+
+ // MD5 is the MD5 hash of the object's content. This field is read-only,
+ // except when used from a Writer. If set on a Writer, the uploaded
+ // data is rejected if its MD5 hash does not match this field.
+ MD5 []byte
+
+ // CRC32C is the CRC32 checksum of the object's content using
+ // the Castagnoli93 polynomial. This field is read-only, except when
+ // used from a Writer. If set on a Writer and Writer.SendCRC32C
+ // is true, the uploaded data is rejected if its CRC32c hash does not
+ // match this field.
+ CRC32C uint32
+
+ // MediaLink is an URL to the object's content. This field is read-only.
+ MediaLink string
+
+ // Metadata represents user-provided metadata, in key/value pairs.
+ // It can be nil if no metadata is provided.
+ Metadata map[string]string
+
+ // Generation is the generation number of the object's content.
+ // This field is read-only.
+ Generation int64
+
+ // Metageneration is the version of the metadata for this
+ // object at this generation. This field is used for preconditions
+ // and for detecting changes in metadata. A metageneration number
+ // is only meaningful in the context of a particular generation
+ // of a particular object. This field is read-only.
+ Metageneration int64
+
+ // StorageClass is the storage class of the object.
+ // This value defines how objects in the bucket are stored and
+ // determines the SLA and the cost of storage. Typical values are
+ // "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD"
+ // and "DURABLE_REDUCED_AVAILABILITY".
+ // It defaults to "STANDARD", which is equivalent to "MULTI_REGIONAL"
+ // or "REGIONAL" depending on the bucket's location settings.
+ StorageClass string
+
+ // Created is the time the object was created. This field is read-only.
+ Created time.Time
+
+ // Deleted is the time the object was deleted.
+ // If not deleted, it is the zero value. This field is read-only.
+ Deleted time.Time
+
+ // Updated is the creation or modification time of the object.
+ // For buckets with versioning enabled, changing an object's
+ // metadata does not change this property. This field is read-only.
+ Updated time.Time
+
+ // CustomerKeySHA256 is the base64-encoded SHA-256 hash of the
+ // customer-supplied encryption key for the object. It is empty if there is
+ // no customer-supplied encryption key.
+ // See // https://cloud.google.com/storage/docs/encryption for more about
+ // encryption in Google Cloud Storage.
+ CustomerKeySHA256 string
+
+ // Prefix is set only for ObjectAttrs which represent synthetic "directory
+ // entries" when iterating over buckets using Query.Delimiter. See
+ // ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
+ // populated.
+ Prefix string
+}
+
+// convertTime converts a time in RFC3339 format to time.Time.
+// If any error occurs in parsing, the zero-value time.Time is silently returned.
+func convertTime(t string) time.Time {
+ var r time.Time
+ if t != "" {
+ r, _ = time.Parse(time.RFC3339, t)
+ }
+ return r
+}
+
+func newObject(o *raw.Object) *ObjectAttrs {
+ if o == nil {
+ return nil
+ }
+ acl := make([]ACLRule, len(o.Acl))
+ for i, rule := range o.Acl {
+ acl[i] = ACLRule{
+ Entity: ACLEntity(rule.Entity),
+ Role: ACLRole(rule.Role),
+ }
+ }
+ owner := ""
+ if o.Owner != nil {
+ owner = o.Owner.Entity
+ }
+ md5, _ := base64.StdEncoding.DecodeString(o.Md5Hash)
+ crc32c, _ := decodeUint32(o.Crc32c)
+ var sha256 string
+ if o.CustomerEncryption != nil {
+ sha256 = o.CustomerEncryption.KeySha256
+ }
+ return &ObjectAttrs{
+ Bucket: o.Bucket,
+ Name: o.Name,
+ ContentType: o.ContentType,
+ ContentLanguage: o.ContentLanguage,
+ CacheControl: o.CacheControl,
+ ACL: acl,
+ Owner: owner,
+ ContentEncoding: o.ContentEncoding,
+ ContentDisposition: o.ContentDisposition,
+ Size: int64(o.Size),
+ MD5: md5,
+ CRC32C: crc32c,
+ MediaLink: o.MediaLink,
+ Metadata: o.Metadata,
+ Generation: o.Generation,
+ Metageneration: o.Metageneration,
+ StorageClass: o.StorageClass,
+ CustomerKeySHA256: sha256,
+ Created: convertTime(o.TimeCreated),
+ Deleted: convertTime(o.TimeDeleted),
+ Updated: convertTime(o.Updated),
+ }
+}
+
+// Decode a uint32 encoded in Base64 in big-endian byte order.
+func decodeUint32(b64 string) (uint32, error) {
+ d, err := base64.StdEncoding.DecodeString(b64)
+ if err != nil {
+ return 0, err
+ }
+ if len(d) != 4 {
+ return 0, fmt.Errorf("storage: %q does not encode a 32-bit value", d)
+ }
+ return uint32(d[0])<<24 + uint32(d[1])<<16 + uint32(d[2])<<8 + uint32(d[3]), nil
+}
+
+// Encode a uint32 as Base64 in big-endian byte order.
+func encodeUint32(u uint32) string {
+ b := []byte{byte(u >> 24), byte(u >> 16), byte(u >> 8), byte(u)}
+ return base64.StdEncoding.EncodeToString(b)
+}
+
+// Query represents a query to filter objects from a bucket.
+type Query struct {
+ // Delimiter returns results in a directory-like fashion.
+ // Results will contain only objects whose names, aside from the
+ // prefix, do not contain delimiter. Objects whose names,
+ // aside from the prefix, contain delimiter will have their name,
+ // truncated after the delimiter, returned in prefixes.
+ // Duplicate prefixes are omitted.
+ // Optional.
+ Delimiter string
+
+ // Prefix is the prefix filter to query objects
+ // whose names begin with this prefix.
+ // Optional.
+ Prefix string
+
+ // Versions indicates whether multiple versions of the same
+ // object will be included in the results.
+ Versions bool
+}
+
+// contentTyper implements ContentTyper to enable an
+// io.ReadCloser to specify its MIME type.
+type contentTyper struct {
+ io.Reader
+ t string
+}
+
+func (c *contentTyper) ContentType() string {
+ return c.t
+}
+
+// Conditions constrain methods to act on specific generations of
+// objects.
+//
+// The zero value is an empty set of constraints. Not all conditions or
+// combinations of conditions are applicable to all methods.
+// See https://cloud.google.com/storage/docs/generations-preconditions
+// for details on how these operate.
+type Conditions struct {
+ // Generation constraints.
+ // At most one of the following can be set to a non-zero value.
+
+ // GenerationMatch specifies that the object must have the given generation
+ // for the operation to occur.
+ // If GenerationMatch is zero, it has no effect.
+ // Use DoesNotExist to specify that the object does not exist in the bucket.
+ GenerationMatch int64
+
+ // GenerationNotMatch specifies that the object must not have the given
+ // generation for the operation to occur.
+ // If GenerationNotMatch is zero, it has no effect.
+ GenerationNotMatch int64
+
+ // DoesNotExist specifies that the object must not exist in the bucket for
+ // the operation to occur.
+ // If DoesNotExist is false, it has no effect.
+ DoesNotExist bool
+
+ // Metadata generation constraints.
+ // At most one of the following can be set to a non-zero value.
+
+ // MetagenerationMatch specifies that the object must have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationMatch is zero, it has no effect.
+ MetagenerationMatch int64
+
+ // MetagenerationNotMatch specifies that the object must not have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationNotMatch is zero, it has no effect.
+ MetagenerationNotMatch int64
+}
+
+func (c *Conditions) validate(method string) error {
+ if *c == (Conditions{}) {
+ return fmt.Errorf("storage: %s: empty conditions", method)
+ }
+ if !c.isGenerationValid() {
+ return fmt.Errorf("storage: %s: multiple conditions specified for generation", method)
+ }
+ if !c.isMetagenerationValid() {
+ return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
+ }
+ return nil
+}
+
+func (c *Conditions) isGenerationValid() bool {
+ n := 0
+ if c.GenerationMatch != 0 {
+ n++
+ }
+ if c.GenerationNotMatch != 0 {
+ n++
+ }
+ if c.DoesNotExist {
+ n++
+ }
+ return n <= 1
+}
+
+func (c *Conditions) isMetagenerationValid() bool {
+ return c.MetagenerationMatch == 0 || c.MetagenerationNotMatch == 0
+}
+
+// applyConds modifies the provided call using the conditions in conds.
+// call is something that quacks like a *raw.WhateverCall.
+func applyConds(method string, gen int64, conds *Conditions, call interface{}) error {
+ cval := reflect.ValueOf(call)
+ if gen >= 0 {
+ if !setConditionField(cval, "Generation", gen) {
+ return fmt.Errorf("storage: %s: generation not supported", method)
+ }
+ }
+ if conds == nil {
+ return nil
+ }
+ if err := conds.validate(method); err != nil {
+ return err
+ }
+ switch {
+ case conds.GenerationMatch != 0:
+ if !setConditionField(cval, "IfGenerationMatch", conds.GenerationMatch) {
+ return fmt.Errorf("storage: %s: ifGenerationMatch not supported", method)
+ }
+ case conds.GenerationNotMatch != 0:
+ if !setConditionField(cval, "IfGenerationNotMatch", conds.GenerationNotMatch) {
+ return fmt.Errorf("storage: %s: ifGenerationNotMatch not supported", method)
+ }
+ case conds.DoesNotExist:
+ if !setConditionField(cval, "IfGenerationMatch", int64(0)) {
+ return fmt.Errorf("storage: %s: DoesNotExist not supported", method)
+ }
+ }
+ switch {
+ case conds.MetagenerationMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
+ }
+ case conds.MetagenerationNotMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
+ }
+ }
+ return nil
+}
+
+func applySourceConds(gen int64, conds *Conditions, call *raw.ObjectsRewriteCall) error {
+ if gen >= 0 {
+ call.SourceGeneration(gen)
+ }
+ if conds == nil {
+ return nil
+ }
+ if err := conds.validate("CopyTo source"); err != nil {
+ return err
+ }
+ switch {
+ case conds.GenerationMatch != 0:
+ call.IfSourceGenerationMatch(conds.GenerationMatch)
+ case conds.GenerationNotMatch != 0:
+ call.IfSourceGenerationNotMatch(conds.GenerationNotMatch)
+ case conds.DoesNotExist:
+ call.IfSourceGenerationMatch(0)
+ }
+ switch {
+ case conds.MetagenerationMatch != 0:
+ call.IfSourceMetagenerationMatch(conds.MetagenerationMatch)
+ case conds.MetagenerationNotMatch != 0:
+ call.IfSourceMetagenerationNotMatch(conds.MetagenerationNotMatch)
+ }
+ return nil
+}
+
+// setConditionField sets a field on a *raw.WhateverCall.
+// We can't use anonymous interfaces because the return type is
+// different, since the field setters are builders.
+func setConditionField(call reflect.Value, name string, value interface{}) bool {
+ m := call.MethodByName(name)
+ if !m.IsValid() {
+ return false
+ }
+ m.Call([]reflect.Value{reflect.ValueOf(value)})
+ return true
+}
+
+// conditionsQuery returns the generation and conditions as a URL query
+// string suitable for URL.RawQuery. It assumes that the conditions
+// have been validated.
+func conditionsQuery(gen int64, conds *Conditions) string {
+ // URL escapes are elided because integer strings are URL-safe.
+ var buf []byte
+
+ appendParam := func(s string, n int64) {
+ if len(buf) > 0 {
+ buf = append(buf, '&')
+ }
+ buf = append(buf, s...)
+ buf = strconv.AppendInt(buf, n, 10)
+ }
+
+ if gen >= 0 {
+ appendParam("generation=", gen)
+ }
+ if conds == nil {
+ return string(buf)
+ }
+ switch {
+ case conds.GenerationMatch != 0:
+ appendParam("ifGenerationMatch=", conds.GenerationMatch)
+ case conds.GenerationNotMatch != 0:
+ appendParam("ifGenerationNotMatch=", conds.GenerationNotMatch)
+ case conds.DoesNotExist:
+ appendParam("ifGenerationMatch=", 0)
+ }
+ switch {
+ case conds.MetagenerationMatch != 0:
+ appendParam("ifMetagenerationMatch=", conds.MetagenerationMatch)
+ case conds.MetagenerationNotMatch != 0:
+ appendParam("ifMetagenerationNotMatch=", conds.MetagenerationNotMatch)
+ }
+ return string(buf)
+}
+
+// composeSourceObj wraps a *raw.ComposeRequestSourceObjects, but adds the methods
+// that modifyCall searches for by name.
+type composeSourceObj struct {
+ src *raw.ComposeRequestSourceObjects
+}
+
+func (c composeSourceObj) Generation(gen int64) {
+ c.src.Generation = gen
+}
+
+func (c composeSourceObj) IfGenerationMatch(gen int64) {
+ // It's safe to overwrite ObjectPreconditions, since its only field is
+ // IfGenerationMatch.
+ c.src.ObjectPreconditions = &raw.ComposeRequestSourceObjectsObjectPreconditions{
+ IfGenerationMatch: gen,
+ }
+}
+
+func setEncryptionHeaders(headers http.Header, key []byte, copySource bool) error {
+ if key == nil {
+ return nil
+ }
+ // TODO(jbd): Ask the API team to return a more user-friendly error
+ // and avoid doing this check at the client level.
+ if len(key) != 32 {
+ return errors.New("storage: not a 32-byte AES-256 key")
+ }
+ var cs string
+ if copySource {
+ cs = "copy-source-"
+ }
+ headers.Set("x-goog-"+cs+"encryption-algorithm", "AES256")
+ headers.Set("x-goog-"+cs+"encryption-key", base64.StdEncoding.EncodeToString(key))
+ keyHash := sha256.Sum256(key)
+ headers.Set("x-goog-"+cs+"encryption-key-sha256", base64.StdEncoding.EncodeToString(keyHash[:]))
+ return nil
+}
+
+// TODO(jbd): Add storage.objects.watch.
diff --git a/vendor/cloud.google.com/go/storage/writer.go b/vendor/cloud.google.com/go/storage/writer.go
new file mode 100644
index 0000000..28eb74a
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/writer.go
@@ -0,0 +1,201 @@
+// Copyright 2014 Google Inc. 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.
+
+package storage
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "unicode/utf8"
+
+ "golang.org/x/net/context"
+ "google.golang.org/api/googleapi"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// A Writer writes a Cloud Storage object.
+type Writer struct {
+ // ObjectAttrs are optional attributes to set on the object. Any attributes
+ // must be initialized before the first Write call. Nil or zero-valued
+ // attributes are ignored.
+ ObjectAttrs
+
+ // SendCRC specifies whether to transmit a CRC32C field. It should be set
+ // to true in addition to setting the Writer's CRC32C field, because zero
+ // is a valid CRC and normally a zero would not be transmitted.
+ // If a CRC32C is sent, and the data written does not match the checksum,
+ // the write will be rejected.
+ SendCRC32C bool
+
+ // ChunkSize controls the maximum number of bytes of the object that the
+ // Writer will attempt to send to the server in a single request. Objects
+ // smaller than the size will be sent in a single request, while larger
+ // objects will be split over multiple requests. The size will be rounded up
+ // to the nearest multiple of 256K. If zero, chunking will be disabled and
+ // the object will be uploaded in a single request.
+ //
+ // ChunkSize will default to a reasonable value. Any custom configuration
+ // must be done before the first Write call.
+ ChunkSize int
+
+ // ProgressFunc can be used to monitor the progress of a large write.
+ // operation. If ProgressFunc is not nil and writing requires multiple
+ // calls to the underlying service (see
+ // https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload),
+ // then ProgressFunc will be invoked after each call with the number of bytes of
+ // content copied so far.
+ //
+ // ProgressFunc should return quickly without blocking.
+ ProgressFunc func(int64)
+
+ ctx context.Context
+ o *ObjectHandle
+
+ opened bool
+ pw *io.PipeWriter
+
+ donec chan struct{} // closed after err and obj are set.
+ err error
+ obj *ObjectAttrs
+}
+
+func (w *Writer) open() error {
+ attrs := w.ObjectAttrs
+ // Check the developer didn't change the object Name (this is unfortunate, but
+ // we don't want to store an object under the wrong name).
+ if attrs.Name != w.o.object {
+ return fmt.Errorf("storage: Writer.Name %q does not match object name %q", attrs.Name, w.o.object)
+ }
+ if !utf8.ValidString(attrs.Name) {
+ return fmt.Errorf("storage: object name %q is not valid UTF-8", attrs.Name)
+ }
+ pr, pw := io.Pipe()
+ w.pw = pw
+ w.opened = true
+
+ if w.ChunkSize < 0 {
+ return errors.New("storage: Writer.ChunkSize must be non-negative")
+ }
+ mediaOpts := []googleapi.MediaOption{
+ googleapi.ChunkSize(w.ChunkSize),
+ }
+ if c := attrs.ContentType; c != "" {
+ mediaOpts = append(mediaOpts, googleapi.ContentType(c))
+ }
+
+ go func() {
+ defer close(w.donec)
+
+ rawObj := attrs.toRawObject(w.o.bucket)
+ if w.SendCRC32C {
+ rawObj.Crc32c = encodeUint32(attrs.CRC32C)
+ }
+ if w.MD5 != nil {
+ rawObj.Md5Hash = base64.StdEncoding.EncodeToString(w.MD5)
+ }
+ call := w.o.c.raw.Objects.Insert(w.o.bucket, rawObj).
+ Media(pr, mediaOpts...).
+ Projection("full").
+ Context(w.ctx)
+ if w.ProgressFunc != nil {
+ call.ProgressUpdater(func(n, _ int64) { w.ProgressFunc(n) })
+ }
+ if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
+ w.err = err
+ pr.CloseWithError(w.err)
+ return
+ }
+ var resp *raw.Object
+ err := applyConds("NewWriter", w.o.gen, w.o.conds, call)
+ if err == nil {
+ if w.o.userProject != "" {
+ call.UserProject(w.o.userProject)
+ }
+ setClientHeader(call.Header())
+ // If the chunk size is zero, then no chunking is done on the Reader,
+ // which means we cannot retry: the first call will read the data, and if
+ // it fails, there is no way to re-read.
+ if w.ChunkSize == 0 {
+ resp, err = call.Do()
+ } else {
+ // We will only retry here if the initial POST, which obtains a URI for
+ // the resumable upload, fails with a retryable error. The upload itself
+ // has its own retry logic.
+ err = runWithRetry(w.ctx, func() error {
+ var err2 error
+ resp, err2 = call.Do()
+ return err2
+ })
+ }
+ }
+ if err != nil {
+ w.err = err
+ pr.CloseWithError(w.err)
+ return
+ }
+ w.obj = newObject(resp)
+ }()
+ return nil
+}
+
+// Write appends to w. It implements the io.Writer interface.
+//
+// Since writes happen asynchronously, Write may return a nil
+// error even though the write failed (or will fail). Always
+// use the error returned from Writer.Close to determine if
+// the upload was successful.
+func (w *Writer) Write(p []byte) (n int, err error) {
+ if w.err != nil {
+ return 0, w.err
+ }
+ if !w.opened {
+ if err := w.open(); err != nil {
+ return 0, err
+ }
+ }
+ return w.pw.Write(p)
+}
+
+// Close completes the write operation and flushes any buffered data.
+// If Close doesn't return an error, metadata about the written object
+// can be retrieved by calling Attrs.
+func (w *Writer) Close() error {
+ if !w.opened {
+ if err := w.open(); err != nil {
+ return err
+ }
+ }
+ if err := w.pw.Close(); err != nil {
+ return err
+ }
+ <-w.donec
+ return w.err
+}
+
+// CloseWithError aborts the write operation with the provided error.
+// CloseWithError always returns nil.
+func (w *Writer) CloseWithError(err error) error {
+ if !w.opened {
+ return nil
+ }
+ return w.pw.CloseWithError(err)
+}
+
+// Attrs returns metadata about a successfully-written object.
+// It's only valid to call it after Close returns nil.
+func (w *Writer) Attrs() *ObjectAttrs {
+ return w.obj
+}
diff --git a/vendor/github.com/beorn7/perks/LICENSE b/vendor/github.com/beorn7/perks/LICENSE
new file mode 100644
index 0000000..339177b
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/LICENSE
@@ -0,0 +1,20 @@
+Copyright (C) 2013 Blake Mizerany
+
+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.
diff --git a/vendor/github.com/beorn7/perks/quantile/exampledata.txt b/vendor/github.com/beorn7/perks/quantile/exampledata.txt
new file mode 100644
index 0000000..1602287
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/quantile/exampledata.txt
@@ -0,0 +1,2388 @@
+8
+5
+26
+12
+5
+235
+13
+6
+28
+30
+3
+3
+3
+3
+5
+2
+33
+7
+2
+4
+7
+12
+14
+5
+8
+3
+10
+4
+5
+3
+6
+6
+209
+20
+3
+10
+14
+3
+4
+6
+8
+5
+11
+7
+3
+2
+3
+3
+212
+5
+222
+4
+10
+10
+5
+6
+3
+8
+3
+10
+254
+220
+2
+3
+5
+24
+5
+4
+222
+7
+3
+3
+223
+8
+15
+12
+14
+14
+3
+2
+2
+3
+13
+3
+11
+4
+4
+6
+5
+7
+13
+5
+3
+5
+2
+5
+3
+5
+2
+7
+15
+17
+14
+3
+6
+6
+3
+17
+5
+4
+7
+6
+4
+4
+8
+6
+8
+3
+9
+3
+6
+3
+4
+5
+3
+3
+660
+4
+6
+10
+3
+6
+3
+2
+5
+13
+2
+4
+4
+10
+4
+8
+4
+3
+7
+9
+9
+3
+10
+37
+3
+13
+4
+12
+3
+6
+10
+8
+5
+21
+2
+3
+8
+3
+2
+3
+3
+4
+12
+2
+4
+8
+8
+4
+3
+2
+20
+1
+6
+32
+2
+11
+6
+18
+3
+8
+11
+3
+212
+3
+4
+2
+6
+7
+12
+11
+3
+2
+16
+10
+6
+4
+6
+3
+2
+7
+3
+2
+2
+2
+2
+5
+6
+4
+3
+10
+3
+4
+6
+5
+3
+4
+4
+5
+6
+4
+3
+4
+4
+5
+7
+5
+5
+3
+2
+7
+2
+4
+12
+4
+5
+6
+2
+4
+4
+8
+4
+15
+13
+7
+16
+5
+3
+23
+5
+5
+7
+3
+2
+9
+8
+7
+5
+8
+11
+4
+10
+76
+4
+47
+4
+3
+2
+7
+4
+2
+3
+37
+10
+4
+2
+20
+5
+4
+4
+10
+10
+4
+3
+7
+23
+240
+7
+13
+5
+5
+3
+3
+2
+5
+4
+2
+8
+7
+19
+2
+23
+8
+7
+2
+5
+3
+8
+3
+8
+13
+5
+5
+5
+2
+3
+23
+4
+9
+8
+4
+3
+3
+5
+220
+2
+3
+4
+6
+14
+3
+53
+6
+2
+5
+18
+6
+3
+219
+6
+5
+2
+5
+3
+6
+5
+15
+4
+3
+17
+3
+2
+4
+7
+2
+3
+3
+4
+4
+3
+2
+664
+6
+3
+23
+5
+5
+16
+5
+8
+2
+4
+2
+24
+12
+3
+2
+3
+5
+8
+3
+5
+4
+3
+14
+3
+5
+8
+2
+3
+7
+9
+4
+2
+3
+6
+8
+4
+3
+4
+6
+5
+3
+3
+6
+3
+19
+4
+4
+6
+3
+6
+3
+5
+22
+5
+4
+4
+3
+8
+11
+4
+9
+7
+6
+13
+4
+4
+4
+6
+17
+9
+3
+3
+3
+4
+3
+221
+5
+11
+3
+4
+2
+12
+6
+3
+5
+7
+5
+7
+4
+9
+7
+14
+37
+19
+217
+16
+3
+5
+2
+2
+7
+19
+7
+6
+7
+4
+24
+5
+11
+4
+7
+7
+9
+13
+3
+4
+3
+6
+28
+4
+4
+5
+5
+2
+5
+6
+4
+4
+6
+10
+5
+4
+3
+2
+3
+3
+6
+5
+5
+4
+3
+2
+3
+7
+4
+6
+18
+16
+8
+16
+4
+5
+8
+6
+9
+13
+1545
+6
+215
+6
+5
+6
+3
+45
+31
+5
+2
+2
+4
+3
+3
+2
+5
+4
+3
+5
+7
+7
+4
+5
+8
+5
+4
+749
+2
+31
+9
+11
+2
+11
+5
+4
+4
+7
+9
+11
+4
+5
+4
+7
+3
+4
+6
+2
+15
+3
+4
+3
+4
+3
+5
+2
+13
+5
+5
+3
+3
+23
+4
+4
+5
+7
+4
+13
+2
+4
+3
+4
+2
+6
+2
+7
+3
+5
+5
+3
+29
+5
+4
+4
+3
+10
+2
+3
+79
+16
+6
+6
+7
+7
+3
+5
+5
+7
+4
+3
+7
+9
+5
+6
+5
+9
+6
+3
+6
+4
+17
+2
+10
+9
+3
+6
+2
+3
+21
+22
+5
+11
+4
+2
+17
+2
+224
+2
+14
+3
+4
+4
+2
+4
+4
+4
+4
+5
+3
+4
+4
+10
+2
+6
+3
+3
+5
+7
+2
+7
+5
+6
+3
+218
+2
+2
+5
+2
+6
+3
+5
+222
+14
+6
+33
+3
+2
+5
+3
+3
+3
+9
+5
+3
+3
+2
+7
+4
+3
+4
+3
+5
+6
+5
+26
+4
+13
+9
+7
+3
+221
+3
+3
+4
+4
+4
+4
+2
+18
+5
+3
+7
+9
+6
+8
+3
+10
+3
+11
+9
+5
+4
+17
+5
+5
+6
+6
+3
+2
+4
+12
+17
+6
+7
+218
+4
+2
+4
+10
+3
+5
+15
+3
+9
+4
+3
+3
+6
+29
+3
+3
+4
+5
+5
+3
+8
+5
+6
+6
+7
+5
+3
+5
+3
+29
+2
+31
+5
+15
+24
+16
+5
+207
+4
+3
+3
+2
+15
+4
+4
+13
+5
+5
+4
+6
+10
+2
+7
+8
+4
+6
+20
+5
+3
+4
+3
+12
+12
+5
+17
+7
+3
+3
+3
+6
+10
+3
+5
+25
+80
+4
+9
+3
+2
+11
+3
+3
+2
+3
+8
+7
+5
+5
+19
+5
+3
+3
+12
+11
+2
+6
+5
+5
+5
+3
+3
+3
+4
+209
+14
+3
+2
+5
+19
+4
+4
+3
+4
+14
+5
+6
+4
+13
+9
+7
+4
+7
+10
+2
+9
+5
+7
+2
+8
+4
+6
+5
+5
+222
+8
+7
+12
+5
+216
+3
+4
+4
+6
+3
+14
+8
+7
+13
+4
+3
+3
+3
+3
+17
+5
+4
+3
+33
+6
+6
+33
+7
+5
+3
+8
+7
+5
+2
+9
+4
+2
+233
+24
+7
+4
+8
+10
+3
+4
+15
+2
+16
+3
+3
+13
+12
+7
+5
+4
+207
+4
+2
+4
+27
+15
+2
+5
+2
+25
+6
+5
+5
+6
+13
+6
+18
+6
+4
+12
+225
+10
+7
+5
+2
+2
+11
+4
+14
+21
+8
+10
+3
+5
+4
+232
+2
+5
+5
+3
+7
+17
+11
+6
+6
+23
+4
+6
+3
+5
+4
+2
+17
+3
+6
+5
+8
+3
+2
+2
+14
+9
+4
+4
+2
+5
+5
+3
+7
+6
+12
+6
+10
+3
+6
+2
+2
+19
+5
+4
+4
+9
+2
+4
+13
+3
+5
+6
+3
+6
+5
+4
+9
+6
+3
+5
+7
+3
+6
+6
+4
+3
+10
+6
+3
+221
+3
+5
+3
+6
+4
+8
+5
+3
+6
+4
+4
+2
+54
+5
+6
+11
+3
+3
+4
+4
+4
+3
+7
+3
+11
+11
+7
+10
+6
+13
+223
+213
+15
+231
+7
+3
+7
+228
+2
+3
+4
+4
+5
+6
+7
+4
+13
+3
+4
+5
+3
+6
+4
+6
+7
+2
+4
+3
+4
+3
+3
+6
+3
+7
+3
+5
+18
+5
+6
+8
+10
+3
+3
+3
+2
+4
+2
+4
+4
+5
+6
+6
+4
+10
+13
+3
+12
+5
+12
+16
+8
+4
+19
+11
+2
+4
+5
+6
+8
+5
+6
+4
+18
+10
+4
+2
+216
+6
+6
+6
+2
+4
+12
+8
+3
+11
+5
+6
+14
+5
+3
+13
+4
+5
+4
+5
+3
+28
+6
+3
+7
+219
+3
+9
+7
+3
+10
+6
+3
+4
+19
+5
+7
+11
+6
+15
+19
+4
+13
+11
+3
+7
+5
+10
+2
+8
+11
+2
+6
+4
+6
+24
+6
+3
+3
+3
+3
+6
+18
+4
+11
+4
+2
+5
+10
+8
+3
+9
+5
+3
+4
+5
+6
+2
+5
+7
+4
+4
+14
+6
+4
+4
+5
+5
+7
+2
+4
+3
+7
+3
+3
+6
+4
+5
+4
+4
+4
+3
+3
+3
+3
+8
+14
+2
+3
+5
+3
+2
+4
+5
+3
+7
+3
+3
+18
+3
+4
+4
+5
+7
+3
+3
+3
+13
+5
+4
+8
+211
+5
+5
+3
+5
+2
+5
+4
+2
+655
+6
+3
+5
+11
+2
+5
+3
+12
+9
+15
+11
+5
+12
+217
+2
+6
+17
+3
+3
+207
+5
+5
+4
+5
+9
+3
+2
+8
+5
+4
+3
+2
+5
+12
+4
+14
+5
+4
+2
+13
+5
+8
+4
+225
+4
+3
+4
+5
+4
+3
+3
+6
+23
+9
+2
+6
+7
+233
+4
+4
+6
+18
+3
+4
+6
+3
+4
+4
+2
+3
+7
+4
+13
+227
+4
+3
+5
+4
+2
+12
+9
+17
+3
+7
+14
+6
+4
+5
+21
+4
+8
+9
+2
+9
+25
+16
+3
+6
+4
+7
+8
+5
+2
+3
+5
+4
+3
+3
+5
+3
+3
+3
+2
+3
+19
+2
+4
+3
+4
+2
+3
+4
+4
+2
+4
+3
+3
+3
+2
+6
+3
+17
+5
+6
+4
+3
+13
+5
+3
+3
+3
+4
+9
+4
+2
+14
+12
+4
+5
+24
+4
+3
+37
+12
+11
+21
+3
+4
+3
+13
+4
+2
+3
+15
+4
+11
+4
+4
+3
+8
+3
+4
+4
+12
+8
+5
+3
+3
+4
+2
+220
+3
+5
+223
+3
+3
+3
+10
+3
+15
+4
+241
+9
+7
+3
+6
+6
+23
+4
+13
+7
+3
+4
+7
+4
+9
+3
+3
+4
+10
+5
+5
+1
+5
+24
+2
+4
+5
+5
+6
+14
+3
+8
+2
+3
+5
+13
+13
+3
+5
+2
+3
+15
+3
+4
+2
+10
+4
+4
+4
+5
+5
+3
+5
+3
+4
+7
+4
+27
+3
+6
+4
+15
+3
+5
+6
+6
+5
+4
+8
+3
+9
+2
+6
+3
+4
+3
+7
+4
+18
+3
+11
+3
+3
+8
+9
+7
+24
+3
+219
+7
+10
+4
+5
+9
+12
+2
+5
+4
+4
+4
+3
+3
+19
+5
+8
+16
+8
+6
+22
+3
+23
+3
+242
+9
+4
+3
+3
+5
+7
+3
+3
+5
+8
+3
+7
+5
+14
+8
+10
+3
+4
+3
+7
+4
+6
+7
+4
+10
+4
+3
+11
+3
+7
+10
+3
+13
+6
+8
+12
+10
+5
+7
+9
+3
+4
+7
+7
+10
+8
+30
+9
+19
+4
+3
+19
+15
+4
+13
+3
+215
+223
+4
+7
+4
+8
+17
+16
+3
+7
+6
+5
+5
+4
+12
+3
+7
+4
+4
+13
+4
+5
+2
+5
+6
+5
+6
+6
+7
+10
+18
+23
+9
+3
+3
+6
+5
+2
+4
+2
+7
+3
+3
+2
+5
+5
+14
+10
+224
+6
+3
+4
+3
+7
+5
+9
+3
+6
+4
+2
+5
+11
+4
+3
+3
+2
+8
+4
+7
+4
+10
+7
+3
+3
+18
+18
+17
+3
+3
+3
+4
+5
+3
+3
+4
+12
+7
+3
+11
+13
+5
+4
+7
+13
+5
+4
+11
+3
+12
+3
+6
+4
+4
+21
+4
+6
+9
+5
+3
+10
+8
+4
+6
+4
+4
+6
+5
+4
+8
+6
+4
+6
+4
+4
+5
+9
+6
+3
+4
+2
+9
+3
+18
+2
+4
+3
+13
+3
+6
+6
+8
+7
+9
+3
+2
+16
+3
+4
+6
+3
+2
+33
+22
+14
+4
+9
+12
+4
+5
+6
+3
+23
+9
+4
+3
+5
+5
+3
+4
+5
+3
+5
+3
+10
+4
+5
+5
+8
+4
+4
+6
+8
+5
+4
+3
+4
+6
+3
+3
+3
+5
+9
+12
+6
+5
+9
+3
+5
+3
+2
+2
+2
+18
+3
+2
+21
+2
+5
+4
+6
+4
+5
+10
+3
+9
+3
+2
+10
+7
+3
+6
+6
+4
+4
+8
+12
+7
+3
+7
+3
+3
+9
+3
+4
+5
+4
+4
+5
+5
+10
+15
+4
+4
+14
+6
+227
+3
+14
+5
+216
+22
+5
+4
+2
+2
+6
+3
+4
+2
+9
+9
+4
+3
+28
+13
+11
+4
+5
+3
+3
+2
+3
+3
+5
+3
+4
+3
+5
+23
+26
+3
+4
+5
+6
+4
+6
+3
+5
+5
+3
+4
+3
+2
+2
+2
+7
+14
+3
+6
+7
+17
+2
+2
+15
+14
+16
+4
+6
+7
+13
+6
+4
+5
+6
+16
+3
+3
+28
+3
+6
+15
+3
+9
+2
+4
+6
+3
+3
+22
+4
+12
+6
+7
+2
+5
+4
+10
+3
+16
+6
+9
+2
+5
+12
+7
+5
+5
+5
+5
+2
+11
+9
+17
+4
+3
+11
+7
+3
+5
+15
+4
+3
+4
+211
+8
+7
+5
+4
+7
+6
+7
+6
+3
+6
+5
+6
+5
+3
+4
+4
+26
+4
+6
+10
+4
+4
+3
+2
+3
+3
+4
+5
+9
+3
+9
+4
+4
+5
+5
+8
+2
+4
+2
+3
+8
+4
+11
+19
+5
+8
+6
+3
+5
+6
+12
+3
+2
+4
+16
+12
+3
+4
+4
+8
+6
+5
+6
+6
+219
+8
+222
+6
+16
+3
+13
+19
+5
+4
+3
+11
+6
+10
+4
+7
+7
+12
+5
+3
+3
+5
+6
+10
+3
+8
+2
+5
+4
+7
+2
+4
+4
+2
+12
+9
+6
+4
+2
+40
+2
+4
+10
+4
+223
+4
+2
+20
+6
+7
+24
+5
+4
+5
+2
+20
+16
+6
+5
+13
+2
+3
+3
+19
+3
+2
+4
+5
+6
+7
+11
+12
+5
+6
+7
+7
+3
+5
+3
+5
+3
+14
+3
+4
+4
+2
+11
+1
+7
+3
+9
+6
+11
+12
+5
+8
+6
+221
+4
+2
+12
+4
+3
+15
+4
+5
+226
+7
+218
+7
+5
+4
+5
+18
+4
+5
+9
+4
+4
+2
+9
+18
+18
+9
+5
+6
+6
+3
+3
+7
+3
+5
+4
+4
+4
+12
+3
+6
+31
+5
+4
+7
+3
+6
+5
+6
+5
+11
+2
+2
+11
+11
+6
+7
+5
+8
+7
+10
+5
+23
+7
+4
+3
+5
+34
+2
+5
+23
+7
+3
+6
+8
+4
+4
+4
+2
+5
+3
+8
+5
+4
+8
+25
+2
+3
+17
+8
+3
+4
+8
+7
+3
+15
+6
+5
+7
+21
+9
+5
+6
+6
+5
+3
+2
+3
+10
+3
+6
+3
+14
+7
+4
+4
+8
+7
+8
+2
+6
+12
+4
+213
+6
+5
+21
+8
+2
+5
+23
+3
+11
+2
+3
+6
+25
+2
+3
+6
+7
+6
+6
+4
+4
+6
+3
+17
+9
+7
+6
+4
+3
+10
+7
+2
+3
+3
+3
+11
+8
+3
+7
+6
+4
+14
+36
+3
+4
+3
+3
+22
+13
+21
+4
+2
+7
+4
+4
+17
+15
+3
+7
+11
+2
+4
+7
+6
+209
+6
+3
+2
+2
+24
+4
+9
+4
+3
+3
+3
+29
+2
+2
+4
+3
+3
+5
+4
+6
+3
+3
+2
+4
diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go
new file mode 100644
index 0000000..f4cabd6
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/quantile/stream.go
@@ -0,0 +1,292 @@
+// Package quantile computes approximate quantiles over an unbounded data
+// stream within low memory and CPU bounds.
+//
+// A small amount of accuracy is traded to achieve the above properties.
+//
+// Multiple streams can be merged before calling Query to generate a single set
+// of results. This is meaningful when the streams represent the same type of
+// data. See Merge and Samples.
+//
+// For more detailed information about the algorithm used, see:
+//
+// Effective Computation of Biased Quantiles over Data Streams
+//
+// http://www.cs.rutgers.edu/~muthu/bquant.pdf
+package quantile
+
+import (
+ "math"
+ "sort"
+)
+
+// Sample holds an observed value and meta information for compression. JSON
+// tags have been added for convenience.
+type Sample struct {
+ Value float64 `json:",string"`
+ Width float64 `json:",string"`
+ Delta float64 `json:",string"`
+}
+
+// Samples represents a slice of samples. It implements sort.Interface.
+type Samples []Sample
+
+func (a Samples) Len() int { return len(a) }
+func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value }
+func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type invariant func(s *stream, r float64) float64
+
+// NewLowBiased returns an initialized Stream for low-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the lower ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within (1±Epsilon)*Quantile.
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewLowBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * r
+ }
+ return newStream(ƒ)
+}
+
+// NewHighBiased returns an initialized Stream for high-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the higher ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewHighBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * (s.n - r)
+ }
+ return newStream(ƒ)
+}
+
+// NewTargeted returns an initialized Stream concerned with a particular set of
+// quantile values that are supplied a priori. Knowing these a priori reduces
+// space and computation time. The targets map maps the desired quantiles to
+// their absolute errors, i.e. the true quantile of a value returned by a query
+// is guaranteed to be within (Quantile±Epsilon).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
+func NewTargeted(targets map[float64]float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ var m = math.MaxFloat64
+ var f float64
+ for quantile, epsilon := range targets {
+ if quantile*s.n <= r {
+ f = (2 * epsilon * r) / quantile
+ } else {
+ f = (2 * epsilon * (s.n - r)) / (1 - quantile)
+ }
+ if f < m {
+ m = f
+ }
+ }
+ return m
+ }
+ return newStream(ƒ)
+}
+
+// Stream computes quantiles for a stream of float64s. It is not thread-safe by
+// design. Take care when using across multiple goroutines.
+type Stream struct {
+ *stream
+ b Samples
+ sorted bool
+}
+
+func newStream(ƒ invariant) *Stream {
+ x := &stream{ƒ: ƒ}
+ return &Stream{x, make(Samples, 0, 500), true}
+}
+
+// Insert inserts v into the stream.
+func (s *Stream) Insert(v float64) {
+ s.insert(Sample{Value: v, Width: 1})
+}
+
+func (s *Stream) insert(sample Sample) {
+ s.b = append(s.b, sample)
+ s.sorted = false
+ if len(s.b) == cap(s.b) {
+ s.flush()
+ }
+}
+
+// Query returns the computed qth percentiles value. If s was created with
+// NewTargeted, and q is not in the set of quantiles provided a priori, Query
+// will return an unspecified result.
+func (s *Stream) Query(q float64) float64 {
+ if !s.flushed() {
+ // Fast path when there hasn't been enough data for a flush;
+ // this also yields better accuracy for small sets of data.
+ l := len(s.b)
+ if l == 0 {
+ return 0
+ }
+ i := int(math.Ceil(float64(l) * q))
+ if i > 0 {
+ i -= 1
+ }
+ s.maybeSort()
+ return s.b[i].Value
+ }
+ s.flush()
+ return s.stream.query(q)
+}
+
+// Merge merges samples into the underlying streams samples. This is handy when
+// merging multiple streams from separate threads, database shards, etc.
+//
+// ATTENTION: This method is broken and does not yield correct results. The
+// underlying algorithm is not capable of merging streams correctly.
+func (s *Stream) Merge(samples Samples) {
+ sort.Sort(samples)
+ s.stream.merge(samples)
+}
+
+// Reset reinitializes and clears the list reusing the samples buffer memory.
+func (s *Stream) Reset() {
+ s.stream.reset()
+ s.b = s.b[:0]
+}
+
+// Samples returns stream samples held by s.
+func (s *Stream) Samples() Samples {
+ if !s.flushed() {
+ return s.b
+ }
+ s.flush()
+ return s.stream.samples()
+}
+
+// Count returns the total number of samples observed in the stream
+// since initialization.
+func (s *Stream) Count() int {
+ return len(s.b) + s.stream.count()
+}
+
+func (s *Stream) flush() {
+ s.maybeSort()
+ s.stream.merge(s.b)
+ s.b = s.b[:0]
+}
+
+func (s *Stream) maybeSort() {
+ if !s.sorted {
+ s.sorted = true
+ sort.Sort(s.b)
+ }
+}
+
+func (s *Stream) flushed() bool {
+ return len(s.stream.l) > 0
+}
+
+type stream struct {
+ n float64
+ l []Sample
+ ƒ invariant
+}
+
+func (s *stream) reset() {
+ s.l = s.l[:0]
+ s.n = 0
+}
+
+func (s *stream) insert(v float64) {
+ s.merge(Samples{{v, 1, 0}})
+}
+
+func (s *stream) merge(samples Samples) {
+ // TODO(beorn7): This tries to merge not only individual samples, but
+ // whole summaries. The paper doesn't mention merging summaries at
+ // all. Unittests show that the merging is inaccurate. Find out how to
+ // do merges properly.
+ var r float64
+ i := 0
+ for _, sample := range samples {
+ for ; i < len(s.l); i++ {
+ c := s.l[i]
+ if c.Value > sample.Value {
+ // Insert at position i.
+ s.l = append(s.l, Sample{})
+ copy(s.l[i+1:], s.l[i:])
+ s.l[i] = Sample{
+ sample.Value,
+ sample.Width,
+ math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1),
+ // TODO(beorn7): How to calculate delta correctly?
+ }
+ i++
+ goto inserted
+ }
+ r += c.Width
+ }
+ s.l = append(s.l, Sample{sample.Value, sample.Width, 0})
+ i++
+ inserted:
+ s.n += sample.Width
+ r += sample.Width
+ }
+ s.compress()
+}
+
+func (s *stream) count() int {
+ return int(s.n)
+}
+
+func (s *stream) query(q float64) float64 {
+ t := math.Ceil(q * s.n)
+ t += math.Ceil(s.ƒ(s, t) / 2)
+ p := s.l[0]
+ var r float64
+ for _, c := range s.l[1:] {
+ r += p.Width
+ if r+c.Width+c.Delta > t {
+ return p.Value
+ }
+ p = c
+ }
+ return p.Value
+}
+
+func (s *stream) compress() {
+ if len(s.l) < 2 {
+ return
+ }
+ x := s.l[len(s.l)-1]
+ xi := len(s.l) - 1
+ r := s.n - 1 - x.Width
+
+ for i := len(s.l) - 2; i >= 0; i-- {
+ c := s.l[i]
+ if c.Width+x.Width+x.Delta <= s.ƒ(s, r) {
+ x.Width += c.Width
+ s.l[xi] = x
+ // Remove element at i.
+ copy(s.l[i:], s.l[i+1:])
+ s.l = s.l[:len(s.l)-1]
+ xi -= 1
+ } else {
+ x = c
+ xi = i
+ }
+ r -= c.Width
+ }
+}
+
+func (s *stream) samples() Samples {
+ samples := make(Samples, len(s.l))
+ copy(samples, s.l)
+ return samples
+}
diff --git a/vendor/github.com/bmizerany/pat/mux.go b/vendor/github.com/bmizerany/pat/mux.go
index ec86fcd..3009e97 100644
--- a/vendor/github.com/bmizerany/pat/mux.go
+++ b/vendor/github.com/bmizerany/pat/mux.go
@@ -110,7 +110,7 @@ func New() *PatternServeMux {
// described above.
func (p *PatternServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, ph := range p.handlers[r.Method] {
- if params, ok := ph.try(r.URL.Path); ok {
+ if params, ok := ph.try(r.URL.EscapedPath()); ok {
if len(params) > 0 && !ph.redirect {
r.URL.RawQuery = url.Values(params).Encode() + "&" + r.URL.RawQuery
}
@@ -131,7 +131,7 @@ func (p *PatternServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
for _, ph := range handlers {
- if _, ok := ph.try(r.URL.Path); ok {
+ if _, ok := ph.try(r.URL.EscapedPath()); ok {
allowed = append(allowed, meth)
}
}
@@ -266,7 +266,11 @@ func (ph *patHandler) try(path string) (url.Values, bool) {
var nextc byte
name, nextc, j = match(ph.pat, isAlnum, j+1)
val, _, i = match(path, matchPart(nextc), i)
- p.Add(":"+name, val)
+ escval, err := url.QueryUnescape(val)
+ if err != nil {
+ return nil, false
+ }
+ p.Add(":"+name, escval)
case path[i] == ph.pat[j]:
i++
j++
diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE
index bb67332..bc52e96 100644
--- a/vendor/github.com/davecgh/go-spew/LICENSE
+++ b/vendor/github.com/davecgh/go-spew/LICENSE
@@ -1,8 +1,8 @@
ISC License
-Copyright (c) 2012-2013 Dave Collins
+Copyright (c) 2012-2016 Dave Collins
-Permission to use, copy, modify, and distribute this software for any
+Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go
index d42a0bc..7f166c3 100644
--- a/vendor/github.com/davecgh/go-spew/spew/bypass.go
+++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Dave Collins
+// Copyright (c) 2015-2016 Dave Collins
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -41,9 +41,9 @@ var (
// after commit 82f48826c6c7 which changed the format again to mirror
// the original format. Code in the init function updates these offsets
// as necessary.
- offsetPtr = uintptr(ptrSize)
+ offsetPtr = ptrSize
offsetScalar = uintptr(0)
- offsetFlag = uintptr(ptrSize * 2)
+ offsetFlag = ptrSize * 2
// flagKindWidth and flagKindShift indicate various bits that the
// reflect package uses internally to track kind information.
@@ -58,7 +58,7 @@ var (
// changed their positions. Code in the init function updates these
// flags as necessary.
flagKindWidth = uintptr(5)
- flagKindShift = uintptr(flagKindWidth - 1)
+ flagKindShift = flagKindWidth - 1
flagRO = uintptr(1 << 0)
flagIndir = uintptr(1 << 1)
)
diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
index e47a4e7..1fe3cf3 100644
--- a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
+++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Dave Collins
+// Copyright (c) 2015-2016 Dave Collins
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go
index 14f02dc..1be8ce9 100644
--- a/vendor/github.com/davecgh/go-spew/spew/common.go
+++ b/vendor/github.com/davecgh/go-spew/spew/common.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Dave Collins
+ * Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) {
w.Write(closeParenBytes)
}
-// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
+// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
// prefix to Writer w.
func printHexPtr(w io.Writer, p uintptr) {
// Null pointer.
diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/davecgh/go-spew/spew/config.go
index 5552827..2e3d22f 100644
--- a/vendor/github.com/davecgh/go-spew/spew/config.go
+++ b/vendor/github.com/davecgh/go-spew/spew/config.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Dave Collins
+ * Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -67,6 +67,15 @@ type ConfigState struct {
// Google App Engine or with the "safe" build tag specified.
DisablePointerMethods bool
+ // DisablePointerAddresses specifies whether to disable the printing of
+ // pointer addresses. This is useful when diffing data structures in tests.
+ DisablePointerAddresses bool
+
+ // DisableCapacities specifies whether to disable the printing of capacities
+ // for arrays, slices, maps and channels. This is useful when diffing
+ // data structures in tests.
+ DisableCapacities bool
+
// ContinueOnMethod specifies whether or not recursion should continue once
// a custom error or Stringer interface is invoked. The default, false,
// means it will print the results of invoking the custom error or Stringer
diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/davecgh/go-spew/spew/doc.go
index 5be0c40..aacaac6 100644
--- a/vendor/github.com/davecgh/go-spew/spew/doc.go
+++ b/vendor/github.com/davecgh/go-spew/spew/doc.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Dave Collins
+ * Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -91,6 +91,15 @@ The following configuration options are available:
which only accept pointer receivers from non-pointer variables.
Pointer method invocation is enabled by default.
+ * DisablePointerAddresses
+ DisablePointerAddresses specifies whether to disable the printing of
+ pointer addresses. This is useful when diffing data structures in tests.
+
+ * DisableCapacities
+ DisableCapacities specifies whether to disable the printing of
+ capacities for arrays, slices, maps and channels. This is useful when
+ diffing data structures in tests.
+
* ContinueOnMethod
Enables recursion into types after invoking error and Stringer interface
methods. Recursion after method invocation is disabled by default.
diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go
index a0ff95e..f78d89f 100644
--- a/vendor/github.com/davecgh/go-spew/spew/dump.go
+++ b/vendor/github.com/davecgh/go-spew/spew/dump.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Dave Collins
+ * Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -35,16 +35,16 @@ var (
// cCharRE is a regular expression that matches a cgo char.
// It is used to detect character arrays to hexdump them.
- cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
+ cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
// char. It is used to detect unsigned character arrays to hexdump
// them.
- cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
+ cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
// It is used to detect uint8_t arrays to hexdump them.
- cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
+ cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
)
// dumpState contains information about the state of a dump operation.
@@ -129,7 +129,7 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
d.w.Write(closeParenBytes)
// Display pointer information.
- if len(pointerChain) > 0 {
+ if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
d.w.Write(openParenBytes)
for i, addr := range pointerChain {
if i > 0 {
@@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
// Display dereferenced value.
d.w.Write(openParenBytes)
switch {
- case nilFound == true:
+ case nilFound:
d.w.Write(nilAngleBytes)
- case cycleFound == true:
+ case cycleFound:
d.w.Write(circularBytes)
default:
@@ -282,13 +282,13 @@ func (d *dumpState) dump(v reflect.Value) {
case reflect.Map, reflect.String:
valueLen = v.Len()
}
- if valueLen != 0 || valueCap != 0 {
+ if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
d.w.Write(openParenBytes)
if valueLen != 0 {
d.w.Write(lenEqualsBytes)
printInt(d.w, int64(valueLen), 10)
}
- if valueCap != 0 {
+ if !d.cs.DisableCapacities && valueCap != 0 {
if valueLen != 0 {
d.w.Write(spaceBytes)
}
diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go
index ecf3b80..b04edb7 100644
--- a/vendor/github.com/davecgh/go-spew/spew/format.go
+++ b/vendor/github.com/davecgh/go-spew/spew/format.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Dave Collins
+ * Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) {
// Display dereferenced value.
switch {
- case nilFound == true:
+ case nilFound:
f.fs.Write(nilAngleBytes)
- case cycleFound == true:
+ case cycleFound:
f.fs.Write(circularShortBytes)
default:
diff --git a/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/davecgh/go-spew/spew/spew.go
index d8233f5..32c0e33 100644
--- a/vendor/github.com/davecgh/go-spew/spew/spew.go
+++ b/vendor/github.com/davecgh/go-spew/spew/spew.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Dave Collins
+ * Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/vendor/github.com/golang/glog/LICENSE b/vendor/github.com/golang/glog/LICENSE
new file mode 100644
index 0000000..37ec93a
--- /dev/null
+++ b/vendor/github.com/golang/glog/LICENSE
@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "[]" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/vendor/github.com/golang/glog/README b/vendor/github.com/golang/glog/README
new file mode 100644
index 0000000..387b4eb
--- /dev/null
+++ b/vendor/github.com/golang/glog/README
@@ -0,0 +1,44 @@
+glog
+====
+
+Leveled execution logs for Go.
+
+This is an efficient pure Go implementation of leveled logs in the
+manner of the open source C++ package
+ https://github.com/google/glog
+
+By binding methods to booleans it is possible to use the log package
+without paying the expense of evaluating the arguments to the log.
+Through the -vmodule flag, the package also provides fine-grained
+control over logging at the file level.
+
+The comment from glog.go introduces the ideas:
+
+ Package glog implements logging analogous to the Google-internal
+ C++ INFO/ERROR/V setup. It provides functions Info, Warning,
+ Error, Fatal, plus formatting variants such as Infof. It
+ also provides V-style logging controlled by the -v and
+ -vmodule=file=2 flags.
+
+ Basic examples:
+
+ glog.Info("Prepare to repel boarders")
+
+ glog.Fatalf("Initialization failed: %s", err)
+
+ See the documentation for the V function for an explanation
+ of these examples:
+
+ if glog.V(2) {
+ glog.Info("Starting transaction...")
+ }
+
+ glog.V(2).Infoln("Processed", nItems, "elements")
+
+
+The repository contains an open source version of the log package
+used inside Google. The master copy of the source lives inside
+Google, not here. The code in this repo is for export only and is not itself
+under development. Feature requests will be ignored.
+
+Send bug reports to golang-nuts@googlegroups.com.
diff --git a/vendor/github.com/golang/glog/glog.go b/vendor/github.com/golang/glog/glog.go
new file mode 100644
index 0000000..54bd7af
--- /dev/null
+++ b/vendor/github.com/golang/glog/glog.go
@@ -0,0 +1,1180 @@
+// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
+//
+// Copyright 2013 Google Inc. 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.
+
+// Package glog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup.
+// It provides functions Info, Warning, Error, Fatal, plus formatting variants such as
+// Infof. It also provides V-style logging controlled by the -v and -vmodule=file=2 flags.
+//
+// Basic examples:
+//
+// glog.Info("Prepare to repel boarders")
+//
+// glog.Fatalf("Initialization failed: %s", err)
+//
+// See the documentation for the V function for an explanation of these examples:
+//
+// if glog.V(2) {
+// glog.Info("Starting transaction...")
+// }
+//
+// glog.V(2).Infoln("Processed", nItems, "elements")
+//
+// Log output is buffered and written periodically using Flush. Programs
+// should call Flush before exiting to guarantee all log output is written.
+//
+// By default, all log statements write to files in a temporary directory.
+// This package provides several flags that modify this behavior.
+// As a result, flag.Parse must be called before any logging is done.
+//
+// -logtostderr=false
+// Logs are written to standard error instead of to files.
+// -alsologtostderr=false
+// Logs are written to standard error as well as to files.
+// -stderrthreshold=ERROR
+// Log events at or above this severity are logged to standard
+// error as well as to files.
+// -log_dir=""
+// Log files will be written to this directory instead of the
+// default temporary directory.
+//
+// Other flags provide aids to debugging.
+//
+// -log_backtrace_at=""
+// When set to a file and line number holding a logging statement,
+// such as
+// -log_backtrace_at=gopherflakes.go:234
+// a stack trace will be written to the Info log whenever execution
+// hits that statement. (Unlike with -vmodule, the ".go" must be
+// present.)
+// -v=0
+// Enable V-leveled logging at the specified level.
+// -vmodule=""
+// The syntax of the argument is a comma-separated list of pattern=N,
+// where pattern is a literal file name (minus the ".go" suffix) or
+// "glob" pattern and N is a V level. For instance,
+// -vmodule=gopher*=3
+// sets the V level to 3 in all Go files whose names begin "gopher".
+//
+package glog
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ stdLog "log"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+// severity identifies the sort of log: info, warning etc. It also implements
+// the flag.Value interface. The -stderrthreshold flag is of type severity and
+// should be modified only through the flag.Value interface. The values match
+// the corresponding constants in C++.
+type severity int32 // sync/atomic int32
+
+// These constants identify the log levels in order of increasing severity.
+// A message written to a high-severity log file is also written to each
+// lower-severity log file.
+const (
+ infoLog severity = iota
+ warningLog
+ errorLog
+ fatalLog
+ numSeverity = 4
+)
+
+const severityChar = "IWEF"
+
+var severityName = []string{
+ infoLog: "INFO",
+ warningLog: "WARNING",
+ errorLog: "ERROR",
+ fatalLog: "FATAL",
+}
+
+// get returns the value of the severity.
+func (s *severity) get() severity {
+ return severity(atomic.LoadInt32((*int32)(s)))
+}
+
+// set sets the value of the severity.
+func (s *severity) set(val severity) {
+ atomic.StoreInt32((*int32)(s), int32(val))
+}
+
+// String is part of the flag.Value interface.
+func (s *severity) String() string {
+ return strconv.FormatInt(int64(*s), 10)
+}
+
+// Get is part of the flag.Value interface.
+func (s *severity) Get() interface{} {
+ return *s
+}
+
+// Set is part of the flag.Value interface.
+func (s *severity) Set(value string) error {
+ var threshold severity
+ // Is it a known name?
+ if v, ok := severityByName(value); ok {
+ threshold = v
+ } else {
+ v, err := strconv.Atoi(value)
+ if err != nil {
+ return err
+ }
+ threshold = severity(v)
+ }
+ logging.stderrThreshold.set(threshold)
+ return nil
+}
+
+func severityByName(s string) (severity, bool) {
+ s = strings.ToUpper(s)
+ for i, name := range severityName {
+ if name == s {
+ return severity(i), true
+ }
+ }
+ return 0, false
+}
+
+// OutputStats tracks the number of output lines and bytes written.
+type OutputStats struct {
+ lines int64
+ bytes int64
+}
+
+// Lines returns the number of lines written.
+func (s *OutputStats) Lines() int64 {
+ return atomic.LoadInt64(&s.lines)
+}
+
+// Bytes returns the number of bytes written.
+func (s *OutputStats) Bytes() int64 {
+ return atomic.LoadInt64(&s.bytes)
+}
+
+// Stats tracks the number of lines of output and number of bytes
+// per severity level. Values must be read with atomic.LoadInt64.
+var Stats struct {
+ Info, Warning, Error OutputStats
+}
+
+var severityStats = [numSeverity]*OutputStats{
+ infoLog: &Stats.Info,
+ warningLog: &Stats.Warning,
+ errorLog: &Stats.Error,
+}
+
+// Level is exported because it appears in the arguments to V and is
+// the type of the v flag, which can be set programmatically.
+// It's a distinct type because we want to discriminate it from logType.
+// Variables of type level are only changed under logging.mu.
+// The -v flag is read only with atomic ops, so the state of the logging
+// module is consistent.
+
+// Level is treated as a sync/atomic int32.
+
+// Level specifies a level of verbosity for V logs. *Level implements
+// flag.Value; the -v flag is of type Level and should be modified
+// only through the flag.Value interface.
+type Level int32
+
+// get returns the value of the Level.
+func (l *Level) get() Level {
+ return Level(atomic.LoadInt32((*int32)(l)))
+}
+
+// set sets the value of the Level.
+func (l *Level) set(val Level) {
+ atomic.StoreInt32((*int32)(l), int32(val))
+}
+
+// String is part of the flag.Value interface.
+func (l *Level) String() string {
+ return strconv.FormatInt(int64(*l), 10)
+}
+
+// Get is part of the flag.Value interface.
+func (l *Level) Get() interface{} {
+ return *l
+}
+
+// Set is part of the flag.Value interface.
+func (l *Level) Set(value string) error {
+ v, err := strconv.Atoi(value)
+ if err != nil {
+ return err
+ }
+ logging.mu.Lock()
+ defer logging.mu.Unlock()
+ logging.setVState(Level(v), logging.vmodule.filter, false)
+ return nil
+}
+
+// moduleSpec represents the setting of the -vmodule flag.
+type moduleSpec struct {
+ filter []modulePat
+}
+
+// modulePat contains a filter for the -vmodule flag.
+// It holds a verbosity level and a file pattern to match.
+type modulePat struct {
+ pattern string
+ literal bool // The pattern is a literal string
+ level Level
+}
+
+// match reports whether the file matches the pattern. It uses a string
+// comparison if the pattern contains no metacharacters.
+func (m *modulePat) match(file string) bool {
+ if m.literal {
+ return file == m.pattern
+ }
+ match, _ := filepath.Match(m.pattern, file)
+ return match
+}
+
+func (m *moduleSpec) String() string {
+ // Lock because the type is not atomic. TODO: clean this up.
+ logging.mu.Lock()
+ defer logging.mu.Unlock()
+ var b bytes.Buffer
+ for i, f := range m.filter {
+ if i > 0 {
+ b.WriteRune(',')
+ }
+ fmt.Fprintf(&b, "%s=%d", f.pattern, f.level)
+ }
+ return b.String()
+}
+
+// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the
+// struct is not exported.
+func (m *moduleSpec) Get() interface{} {
+ return nil
+}
+
+var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N")
+
+// Syntax: -vmodule=recordio=2,file=1,gfs*=3
+func (m *moduleSpec) Set(value string) error {
+ var filter []modulePat
+ for _, pat := range strings.Split(value, ",") {
+ if len(pat) == 0 {
+ // Empty strings such as from a trailing comma can be ignored.
+ continue
+ }
+ patLev := strings.Split(pat, "=")
+ if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
+ return errVmoduleSyntax
+ }
+ pattern := patLev[0]
+ v, err := strconv.Atoi(patLev[1])
+ if err != nil {
+ return errors.New("syntax error: expect comma-separated list of filename=N")
+ }
+ if v < 0 {
+ return errors.New("negative value for vmodule level")
+ }
+ if v == 0 {
+ continue // Ignore. It's harmless but no point in paying the overhead.
+ }
+ // TODO: check syntax of filter?
+ filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
+ }
+ logging.mu.Lock()
+ defer logging.mu.Unlock()
+ logging.setVState(logging.verbosity, filter, true)
+ return nil
+}
+
+// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters
+// that require filepath.Match to be called to match the pattern.
+func isLiteral(pattern string) bool {
+ return !strings.ContainsAny(pattern, `\*?[]`)
+}
+
+// traceLocation represents the setting of the -log_backtrace_at flag.
+type traceLocation struct {
+ file string
+ line int
+}
+
+// isSet reports whether the trace location has been specified.
+// logging.mu is held.
+func (t *traceLocation) isSet() bool {
+ return t.line > 0
+}
+
+// match reports whether the specified file and line matches the trace location.
+// The argument file name is the full path, not the basename specified in the flag.
+// logging.mu is held.
+func (t *traceLocation) match(file string, line int) bool {
+ if t.line != line {
+ return false
+ }
+ if i := strings.LastIndex(file, "/"); i >= 0 {
+ file = file[i+1:]
+ }
+ return t.file == file
+}
+
+func (t *traceLocation) String() string {
+ // Lock because the type is not atomic. TODO: clean this up.
+ logging.mu.Lock()
+ defer logging.mu.Unlock()
+ return fmt.Sprintf("%s:%d", t.file, t.line)
+}
+
+// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the
+// struct is not exported
+func (t *traceLocation) Get() interface{} {
+ return nil
+}
+
+var errTraceSyntax = errors.New("syntax error: expect file.go:234")
+
+// Syntax: -log_backtrace_at=gopherflakes.go:234
+// Note that unlike vmodule the file extension is included here.
+func (t *traceLocation) Set(value string) error {
+ if value == "" {
+ // Unset.
+ t.line = 0
+ t.file = ""
+ }
+ fields := strings.Split(value, ":")
+ if len(fields) != 2 {
+ return errTraceSyntax
+ }
+ file, line := fields[0], fields[1]
+ if !strings.Contains(file, ".") {
+ return errTraceSyntax
+ }
+ v, err := strconv.Atoi(line)
+ if err != nil {
+ return errTraceSyntax
+ }
+ if v <= 0 {
+ return errors.New("negative or zero value for level")
+ }
+ logging.mu.Lock()
+ defer logging.mu.Unlock()
+ t.line = v
+ t.file = file
+ return nil
+}
+
+// flushSyncWriter is the interface satisfied by logging destinations.
+type flushSyncWriter interface {
+ Flush() error
+ Sync() error
+ io.Writer
+}
+
+func init() {
+ flag.BoolVar(&logging.toStderr, "logtostderr", false, "log to standard error instead of files")
+ flag.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files")
+ flag.Var(&logging.verbosity, "v", "log level for V logs")
+ flag.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr")
+ flag.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
+ flag.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
+
+ // Default stderrThreshold is ERROR.
+ logging.stderrThreshold = errorLog
+
+ logging.setVState(0, nil, false)
+ go logging.flushDaemon()
+}
+
+// Flush flushes all pending log I/O.
+func Flush() {
+ logging.lockAndFlushAll()
+}
+
+// loggingT collects all the global state of the logging setup.
+type loggingT struct {
+ // Boolean flags. Not handled atomically because the flag.Value interface
+ // does not let us avoid the =true, and that shorthand is necessary for
+ // compatibility. TODO: does this matter enough to fix? Seems unlikely.
+ toStderr bool // The -logtostderr flag.
+ alsoToStderr bool // The -alsologtostderr flag.
+
+ // Level flag. Handled atomically.
+ stderrThreshold severity // The -stderrthreshold flag.
+
+ // freeList is a list of byte buffers, maintained under freeListMu.
+ freeList *buffer
+ // freeListMu maintains the free list. It is separate from the main mutex
+ // so buffers can be grabbed and printed to without holding the main lock,
+ // for better parallelization.
+ freeListMu sync.Mutex
+
+ // mu protects the remaining elements of this structure and is
+ // used to synchronize logging.
+ mu sync.Mutex
+ // file holds writer for each of the log types.
+ file [numSeverity]flushSyncWriter
+ // pcs is used in V to avoid an allocation when computing the caller's PC.
+ pcs [1]uintptr
+ // vmap is a cache of the V Level for each V() call site, identified by PC.
+ // It is wiped whenever the vmodule flag changes state.
+ vmap map[uintptr]Level
+ // filterLength stores the length of the vmodule filter chain. If greater
+ // than zero, it means vmodule is enabled. It may be read safely
+ // using sync.LoadInt32, but is only modified under mu.
+ filterLength int32
+ // traceLocation is the state of the -log_backtrace_at flag.
+ traceLocation traceLocation
+ // These flags are modified only under lock, although verbosity may be fetched
+ // safely using atomic.LoadInt32.
+ vmodule moduleSpec // The state of the -vmodule flag.
+ verbosity Level // V logging level, the value of the -v flag/
+}
+
+// buffer holds a byte Buffer for reuse. The zero value is ready for use.
+type buffer struct {
+ bytes.Buffer
+ tmp [64]byte // temporary byte array for creating headers.
+ next *buffer
+}
+
+var logging loggingT
+
+// setVState sets a consistent state for V logging.
+// l.mu is held.
+func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) {
+ // Turn verbosity off so V will not fire while we are in transition.
+ logging.verbosity.set(0)
+ // Ditto for filter length.
+ atomic.StoreInt32(&logging.filterLength, 0)
+
+ // Set the new filters and wipe the pc->Level map if the filter has changed.
+ if setFilter {
+ logging.vmodule.filter = filter
+ logging.vmap = make(map[uintptr]Level)
+ }
+
+ // Things are consistent now, so enable filtering and verbosity.
+ // They are enabled in order opposite to that in V.
+ atomic.StoreInt32(&logging.filterLength, int32(len(filter)))
+ logging.verbosity.set(verbosity)
+}
+
+// getBuffer returns a new, ready-to-use buffer.
+func (l *loggingT) getBuffer() *buffer {
+ l.freeListMu.Lock()
+ b := l.freeList
+ if b != nil {
+ l.freeList = b.next
+ }
+ l.freeListMu.Unlock()
+ if b == nil {
+ b = new(buffer)
+ } else {
+ b.next = nil
+ b.Reset()
+ }
+ return b
+}
+
+// putBuffer returns a buffer to the free list.
+func (l *loggingT) putBuffer(b *buffer) {
+ if b.Len() >= 256 {
+ // Let big buffers die a natural death.
+ return
+ }
+ l.freeListMu.Lock()
+ b.next = l.freeList
+ l.freeList = b
+ l.freeListMu.Unlock()
+}
+
+var timeNow = time.Now // Stubbed out for testing.
+
+/*
+header formats a log header as defined by the C++ implementation.
+It returns a buffer containing the formatted header and the user's file and line number.
+The depth specifies how many stack frames above lives the source line to be identified in the log message.
+
+Log lines have this form:
+ Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
+where the fields are defined as follows:
+ L A single character, representing the log level (eg 'I' for INFO)
+ mm The month (zero padded; ie May is '05')
+ dd The day (zero padded)
+ hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
+ threadid The space-padded thread ID as returned by GetTID()
+ file The file name
+ line The line number
+ msg The user-supplied message
+*/
+func (l *loggingT) header(s severity, depth int) (*buffer, string, int) {
+ _, file, line, ok := runtime.Caller(3 + depth)
+ if !ok {
+ file = "???"
+ line = 1
+ } else {
+ slash := strings.LastIndex(file, "/")
+ if slash >= 0 {
+ file = file[slash+1:]
+ }
+ }
+ return l.formatHeader(s, file, line), file, line
+}
+
+// formatHeader formats a log header using the provided file name and line number.
+func (l *loggingT) formatHeader(s severity, file string, line int) *buffer {
+ now := timeNow()
+ if line < 0 {
+ line = 0 // not a real line number, but acceptable to someDigits
+ }
+ if s > fatalLog {
+ s = infoLog // for safety.
+ }
+ buf := l.getBuffer()
+
+ // Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
+ // It's worth about 3X. Fprintf is hard.
+ _, month, day := now.Date()
+ hour, minute, second := now.Clock()
+ // Lmmdd hh:mm:ss.uuuuuu threadid file:line]
+ buf.tmp[0] = severityChar[s]
+ buf.twoDigits(1, int(month))
+ buf.twoDigits(3, day)
+ buf.tmp[5] = ' '
+ buf.twoDigits(6, hour)
+ buf.tmp[8] = ':'
+ buf.twoDigits(9, minute)
+ buf.tmp[11] = ':'
+ buf.twoDigits(12, second)
+ buf.tmp[14] = '.'
+ buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
+ buf.tmp[21] = ' '
+ buf.nDigits(7, 22, pid, ' ') // TODO: should be TID
+ buf.tmp[29] = ' '
+ buf.Write(buf.tmp[:30])
+ buf.WriteString(file)
+ buf.tmp[0] = ':'
+ n := buf.someDigits(1, line)
+ buf.tmp[n+1] = ']'
+ buf.tmp[n+2] = ' '
+ buf.Write(buf.tmp[:n+3])
+ return buf
+}
+
+// Some custom tiny helper functions to print the log header efficiently.
+
+const digits = "0123456789"
+
+// twoDigits formats a zero-prefixed two-digit integer at buf.tmp[i].
+func (buf *buffer) twoDigits(i, d int) {
+ buf.tmp[i+1] = digits[d%10]
+ d /= 10
+ buf.tmp[i] = digits[d%10]
+}
+
+// nDigits formats an n-digit integer at buf.tmp[i],
+// padding with pad on the left.
+// It assumes d >= 0.
+func (buf *buffer) nDigits(n, i, d int, pad byte) {
+ j := n - 1
+ for ; j >= 0 && d > 0; j-- {
+ buf.tmp[i+j] = digits[d%10]
+ d /= 10
+ }
+ for ; j >= 0; j-- {
+ buf.tmp[i+j] = pad
+ }
+}
+
+// someDigits formats a zero-prefixed variable-width integer at buf.tmp[i].
+func (buf *buffer) someDigits(i, d int) int {
+ // Print into the top, then copy down. We know there's space for at least
+ // a 10-digit number.
+ j := len(buf.tmp)
+ for {
+ j--
+ buf.tmp[j] = digits[d%10]
+ d /= 10
+ if d == 0 {
+ break
+ }
+ }
+ return copy(buf.tmp[i:], buf.tmp[j:])
+}
+
+func (l *loggingT) println(s severity, args ...interface{}) {
+ buf, file, line := l.header(s, 0)
+ fmt.Fprintln(buf, args...)
+ l.output(s, buf, file, line, false)
+}
+
+func (l *loggingT) print(s severity, args ...interface{}) {
+ l.printDepth(s, 1, args...)
+}
+
+func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) {
+ buf, file, line := l.header(s, depth)
+ fmt.Fprint(buf, args...)
+ if buf.Bytes()[buf.Len()-1] != '\n' {
+ buf.WriteByte('\n')
+ }
+ l.output(s, buf, file, line, false)
+}
+
+func (l *loggingT) printf(s severity, format string, args ...interface{}) {
+ buf, file, line := l.header(s, 0)
+ fmt.Fprintf(buf, format, args...)
+ if buf.Bytes()[buf.Len()-1] != '\n' {
+ buf.WriteByte('\n')
+ }
+ l.output(s, buf, file, line, false)
+}
+
+// printWithFileLine behaves like print but uses the provided file and line number. If
+// alsoLogToStderr is true, the log message always appears on standard error; it
+// will also appear in the log file unless --logtostderr is set.
+func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) {
+ buf := l.formatHeader(s, file, line)
+ fmt.Fprint(buf, args...)
+ if buf.Bytes()[buf.Len()-1] != '\n' {
+ buf.WriteByte('\n')
+ }
+ l.output(s, buf, file, line, alsoToStderr)
+}
+
+// output writes the data to the log files and releases the buffer.
+func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) {
+ l.mu.Lock()
+ if l.traceLocation.isSet() {
+ if l.traceLocation.match(file, line) {
+ buf.Write(stacks(false))
+ }
+ }
+ data := buf.Bytes()
+ if !flag.Parsed() {
+ os.Stderr.Write([]byte("ERROR: logging before flag.Parse: "))
+ os.Stderr.Write(data)
+ } else if l.toStderr {
+ os.Stderr.Write(data)
+ } else {
+ if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() {
+ os.Stderr.Write(data)
+ }
+ if l.file[s] == nil {
+ if err := l.createFiles(s); err != nil {
+ os.Stderr.Write(data) // Make sure the message appears somewhere.
+ l.exit(err)
+ }
+ }
+ switch s {
+ case fatalLog:
+ l.file[fatalLog].Write(data)
+ fallthrough
+ case errorLog:
+ l.file[errorLog].Write(data)
+ fallthrough
+ case warningLog:
+ l.file[warningLog].Write(data)
+ fallthrough
+ case infoLog:
+ l.file[infoLog].Write(data)
+ }
+ }
+ if s == fatalLog {
+ // If we got here via Exit rather than Fatal, print no stacks.
+ if atomic.LoadUint32(&fatalNoStacks) > 0 {
+ l.mu.Unlock()
+ timeoutFlush(10 * time.Second)
+ os.Exit(1)
+ }
+ // Dump all goroutine stacks before exiting.
+ // First, make sure we see the trace for the current goroutine on standard error.
+ // If -logtostderr has been specified, the loop below will do that anyway
+ // as the first stack in the full dump.
+ if !l.toStderr {
+ os.Stderr.Write(stacks(false))
+ }
+ // Write the stack trace for all goroutines to the files.
+ trace := stacks(true)
+ logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
+ for log := fatalLog; log >= infoLog; log-- {
+ if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
+ f.Write(trace)
+ }
+ }
+ l.mu.Unlock()
+ timeoutFlush(10 * time.Second)
+ os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
+ }
+ l.putBuffer(buf)
+ l.mu.Unlock()
+ if stats := severityStats[s]; stats != nil {
+ atomic.AddInt64(&stats.lines, 1)
+ atomic.AddInt64(&stats.bytes, int64(len(data)))
+ }
+}
+
+// timeoutFlush calls Flush and returns when it completes or after timeout
+// elapses, whichever happens first. This is needed because the hooks invoked
+// by Flush may deadlock when glog.Fatal is called from a hook that holds
+// a lock.
+func timeoutFlush(timeout time.Duration) {
+ done := make(chan bool, 1)
+ go func() {
+ Flush() // calls logging.lockAndFlushAll()
+ done <- true
+ }()
+ select {
+ case <-done:
+ case <-time.After(timeout):
+ fmt.Fprintln(os.Stderr, "glog: Flush took longer than", timeout)
+ }
+}
+
+// stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines.
+func stacks(all bool) []byte {
+ // We don't know how big the traces are, so grow a few times if they don't fit. Start large, though.
+ n := 10000
+ if all {
+ n = 100000
+ }
+ var trace []byte
+ for i := 0; i < 5; i++ {
+ trace = make([]byte, n)
+ nbytes := runtime.Stack(trace, all)
+ if nbytes < len(trace) {
+ return trace[:nbytes]
+ }
+ n *= 2
+ }
+ return trace
+}
+
+// logExitFunc provides a simple mechanism to override the default behavior
+// of exiting on error. Used in testing and to guarantee we reach a required exit
+// for fatal logs. Instead, exit could be a function rather than a method but that
+// would make its use clumsier.
+var logExitFunc func(error)
+
+// exit is called if there is trouble creating or writing log files.
+// It flushes the logs and exits the program; there's no point in hanging around.
+// l.mu is held.
+func (l *loggingT) exit(err error) {
+ fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err)
+ // If logExitFunc is set, we do that instead of exiting.
+ if logExitFunc != nil {
+ logExitFunc(err)
+ return
+ }
+ l.flushAll()
+ os.Exit(2)
+}
+
+// syncBuffer joins a bufio.Writer to its underlying file, providing access to the
+// file's Sync method and providing a wrapper for the Write method that provides log
+// file rotation. There are conflicting methods, so the file cannot be embedded.
+// l.mu is held for all its methods.
+type syncBuffer struct {
+ logger *loggingT
+ *bufio.Writer
+ file *os.File
+ sev severity
+ nbytes uint64 // The number of bytes written to this file
+}
+
+func (sb *syncBuffer) Sync() error {
+ return sb.file.Sync()
+}
+
+func (sb *syncBuffer) Write(p []byte) (n int, err error) {
+ if sb.nbytes+uint64(len(p)) >= MaxSize {
+ if err := sb.rotateFile(time.Now()); err != nil {
+ sb.logger.exit(err)
+ }
+ }
+ n, err = sb.Writer.Write(p)
+ sb.nbytes += uint64(n)
+ if err != nil {
+ sb.logger.exit(err)
+ }
+ return
+}
+
+// rotateFile closes the syncBuffer's file and starts a new one.
+func (sb *syncBuffer) rotateFile(now time.Time) error {
+ if sb.file != nil {
+ sb.Flush()
+ sb.file.Close()
+ }
+ var err error
+ sb.file, _, err = create(severityName[sb.sev], now)
+ sb.nbytes = 0
+ if err != nil {
+ return err
+ }
+
+ sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)
+
+ // Write header.
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
+ fmt.Fprintf(&buf, "Running on machine: %s\n", host)
+ fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
+ fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
+ n, err := sb.file.Write(buf.Bytes())
+ sb.nbytes += uint64(n)
+ return err
+}
+
+// bufferSize sizes the buffer associated with each log file. It's large
+// so that log records can accumulate without the logging thread blocking
+// on disk I/O. The flushDaemon will block instead.
+const bufferSize = 256 * 1024
+
+// createFiles creates all the log files for severity from sev down to infoLog.
+// l.mu is held.
+func (l *loggingT) createFiles(sev severity) error {
+ now := time.Now()
+ // Files are created in decreasing severity order, so as soon as we find one
+ // has already been created, we can stop.
+ for s := sev; s >= infoLog && l.file[s] == nil; s-- {
+ sb := &syncBuffer{
+ logger: l,
+ sev: s,
+ }
+ if err := sb.rotateFile(now); err != nil {
+ return err
+ }
+ l.file[s] = sb
+ }
+ return nil
+}
+
+const flushInterval = 30 * time.Second
+
+// flushDaemon periodically flushes the log file buffers.
+func (l *loggingT) flushDaemon() {
+ for _ = range time.NewTicker(flushInterval).C {
+ l.lockAndFlushAll()
+ }
+}
+
+// lockAndFlushAll is like flushAll but locks l.mu first.
+func (l *loggingT) lockAndFlushAll() {
+ l.mu.Lock()
+ l.flushAll()
+ l.mu.Unlock()
+}
+
+// flushAll flushes all the logs and attempts to "sync" their data to disk.
+// l.mu is held.
+func (l *loggingT) flushAll() {
+ // Flush from fatal down, in case there's trouble flushing.
+ for s := fatalLog; s >= infoLog; s-- {
+ file := l.file[s]
+ if file != nil {
+ file.Flush() // ignore error
+ file.Sync() // ignore error
+ }
+ }
+}
+
+// CopyStandardLogTo arranges for messages written to the Go "log" package's
+// default logs to also appear in the Google logs for the named and lower
+// severities. Subsequent changes to the standard log's default output location
+// or format may break this behavior.
+//
+// Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not
+// recognized, CopyStandardLogTo panics.
+func CopyStandardLogTo(name string) {
+ sev, ok := severityByName(name)
+ if !ok {
+ panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name))
+ }
+ // Set a log format that captures the user's file and line:
+ // d.go:23: message
+ stdLog.SetFlags(stdLog.Lshortfile)
+ stdLog.SetOutput(logBridge(sev))
+}
+
+// logBridge provides the Write method that enables CopyStandardLogTo to connect
+// Go's standard logs to the logs provided by this package.
+type logBridge severity
+
+// Write parses the standard logging line and passes its components to the
+// logger for severity(lb).
+func (lb logBridge) Write(b []byte) (n int, err error) {
+ var (
+ file = "???"
+ line = 1
+ text string
+ )
+ // Split "d.go:23: message" into "d.go", "23", and "message".
+ if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 {
+ text = fmt.Sprintf("bad log format: %s", b)
+ } else {
+ file = string(parts[0])
+ text = string(parts[2][1:]) // skip leading space
+ line, err = strconv.Atoi(string(parts[1]))
+ if err != nil {
+ text = fmt.Sprintf("bad line number: %s", b)
+ line = 1
+ }
+ }
+ // printWithFileLine with alsoToStderr=true, so standard log messages
+ // always appear on standard error.
+ logging.printWithFileLine(severity(lb), file, line, true, text)
+ return len(b), nil
+}
+
+// setV computes and remembers the V level for a given PC
+// when vmodule is enabled.
+// File pattern matching takes the basename of the file, stripped
+// of its .go suffix, and uses filepath.Match, which is a little more
+// general than the *? matching used in C++.
+// l.mu is held.
+func (l *loggingT) setV(pc uintptr) Level {
+ fn := runtime.FuncForPC(pc)
+ file, _ := fn.FileLine(pc)
+ // The file is something like /a/b/c/d.go. We want just the d.
+ if strings.HasSuffix(file, ".go") {
+ file = file[:len(file)-3]
+ }
+ if slash := strings.LastIndex(file, "/"); slash >= 0 {
+ file = file[slash+1:]
+ }
+ for _, filter := range l.vmodule.filter {
+ if filter.match(file) {
+ l.vmap[pc] = filter.level
+ return filter.level
+ }
+ }
+ l.vmap[pc] = 0
+ return 0
+}
+
+// Verbose is a boolean type that implements Infof (like Printf) etc.
+// See the documentation of V for more information.
+type Verbose bool
+
+// V reports whether verbosity at the call site is at least the requested level.
+// The returned value is a boolean of type Verbose, which implements Info, Infoln
+// and Infof. These methods will write to the Info log if called.
+// Thus, one may write either
+// if glog.V(2) { glog.Info("log this") }
+// or
+// glog.V(2).Info("log this")
+// The second form is shorter but the first is cheaper if logging is off because it does
+// not evaluate its arguments.
+//
+// Whether an individual call to V generates a log record depends on the setting of
+// the -v and --vmodule flags; both are off by default. If the level in the call to
+// V is at least the value of -v, or of -vmodule for the source file containing the
+// call, the V call will log.
+func V(level Level) Verbose {
+ // This function tries hard to be cheap unless there's work to do.
+ // The fast path is two atomic loads and compares.
+
+ // Here is a cheap but safe test to see if V logging is enabled globally.
+ if logging.verbosity.get() >= level {
+ return Verbose(true)
+ }
+
+ // It's off globally but it vmodule may still be set.
+ // Here is another cheap but safe test to see if vmodule is enabled.
+ if atomic.LoadInt32(&logging.filterLength) > 0 {
+ // Now we need a proper lock to use the logging structure. The pcs field
+ // is shared so we must lock before accessing it. This is fairly expensive,
+ // but if V logging is enabled we're slow anyway.
+ logging.mu.Lock()
+ defer logging.mu.Unlock()
+ if runtime.Callers(2, logging.pcs[:]) == 0 {
+ return Verbose(false)
+ }
+ v, ok := logging.vmap[logging.pcs[0]]
+ if !ok {
+ v = logging.setV(logging.pcs[0])
+ }
+ return Verbose(v >= level)
+ }
+ return Verbose(false)
+}
+
+// Info is equivalent to the global Info function, guarded by the value of v.
+// See the documentation of V for usage.
+func (v Verbose) Info(args ...interface{}) {
+ if v {
+ logging.print(infoLog, args...)
+ }
+}
+
+// Infoln is equivalent to the global Infoln function, guarded by the value of v.
+// See the documentation of V for usage.
+func (v Verbose) Infoln(args ...interface{}) {
+ if v {
+ logging.println(infoLog, args...)
+ }
+}
+
+// Infof is equivalent to the global Infof function, guarded by the value of v.
+// See the documentation of V for usage.
+func (v Verbose) Infof(format string, args ...interface{}) {
+ if v {
+ logging.printf(infoLog, format, args...)
+ }
+}
+
+// Info logs to the INFO log.
+// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
+func Info(args ...interface{}) {
+ logging.print(infoLog, args...)
+}
+
+// InfoDepth acts as Info but uses depth to determine which call frame to log.
+// InfoDepth(0, "msg") is the same as Info("msg").
+func InfoDepth(depth int, args ...interface{}) {
+ logging.printDepth(infoLog, depth, args...)
+}
+
+// Infoln logs to the INFO log.
+// Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
+func Infoln(args ...interface{}) {
+ logging.println(infoLog, args...)
+}
+
+// Infof logs to the INFO log.
+// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
+func Infof(format string, args ...interface{}) {
+ logging.printf(infoLog, format, args...)
+}
+
+// Warning logs to the WARNING and INFO logs.
+// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
+func Warning(args ...interface{}) {
+ logging.print(warningLog, args...)
+}
+
+// WarningDepth acts as Warning but uses depth to determine which call frame to log.
+// WarningDepth(0, "msg") is the same as Warning("msg").
+func WarningDepth(depth int, args ...interface{}) {
+ logging.printDepth(warningLog, depth, args...)
+}
+
+// Warningln logs to the WARNING and INFO logs.
+// Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
+func Warningln(args ...interface{}) {
+ logging.println(warningLog, args...)
+}
+
+// Warningf logs to the WARNING and INFO logs.
+// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
+func Warningf(format string, args ...interface{}) {
+ logging.printf(warningLog, format, args...)
+}
+
+// Error logs to the ERROR, WARNING, and INFO logs.
+// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
+func Error(args ...interface{}) {
+ logging.print(errorLog, args...)
+}
+
+// ErrorDepth acts as Error but uses depth to determine which call frame to log.
+// ErrorDepth(0, "msg") is the same as Error("msg").
+func ErrorDepth(depth int, args ...interface{}) {
+ logging.printDepth(errorLog, depth, args...)
+}
+
+// Errorln logs to the ERROR, WARNING, and INFO logs.
+// Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
+func Errorln(args ...interface{}) {
+ logging.println(errorLog, args...)
+}
+
+// Errorf logs to the ERROR, WARNING, and INFO logs.
+// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
+func Errorf(format string, args ...interface{}) {
+ logging.printf(errorLog, format, args...)
+}
+
+// Fatal logs to the FATAL, ERROR, WARNING, and INFO logs,
+// including a stack trace of all running goroutines, then calls os.Exit(255).
+// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
+func Fatal(args ...interface{}) {
+ logging.print(fatalLog, args...)
+}
+
+// FatalDepth acts as Fatal but uses depth to determine which call frame to log.
+// FatalDepth(0, "msg") is the same as Fatal("msg").
+func FatalDepth(depth int, args ...interface{}) {
+ logging.printDepth(fatalLog, depth, args...)
+}
+
+// Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs,
+// including a stack trace of all running goroutines, then calls os.Exit(255).
+// Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
+func Fatalln(args ...interface{}) {
+ logging.println(fatalLog, args...)
+}
+
+// Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
+// including a stack trace of all running goroutines, then calls os.Exit(255).
+// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
+func Fatalf(format string, args ...interface{}) {
+ logging.printf(fatalLog, format, args...)
+}
+
+// fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks.
+// It allows Exit and relatives to use the Fatal logs.
+var fatalNoStacks uint32
+
+// Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
+// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
+func Exit(args ...interface{}) {
+ atomic.StoreUint32(&fatalNoStacks, 1)
+ logging.print(fatalLog, args...)
+}
+
+// ExitDepth acts as Exit but uses depth to determine which call frame to log.
+// ExitDepth(0, "msg") is the same as Exit("msg").
+func ExitDepth(depth int, args ...interface{}) {
+ atomic.StoreUint32(&fatalNoStacks, 1)
+ logging.printDepth(fatalLog, depth, args...)
+}
+
+// Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
+func Exitln(args ...interface{}) {
+ atomic.StoreUint32(&fatalNoStacks, 1)
+ logging.println(fatalLog, args...)
+}
+
+// Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
+// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
+func Exitf(format string, args ...interface{}) {
+ atomic.StoreUint32(&fatalNoStacks, 1)
+ logging.printf(fatalLog, format, args...)
+}
diff --git a/vendor/github.com/golang/glog/glog_file.go b/vendor/github.com/golang/glog/glog_file.go
new file mode 100644
index 0000000..65075d2
--- /dev/null
+++ b/vendor/github.com/golang/glog/glog_file.go
@@ -0,0 +1,124 @@
+// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
+//
+// Copyright 2013 Google Inc. 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 I/O for logs.
+
+package glog
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "os"
+ "os/user"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+)
+
+// MaxSize is the maximum size of a log file in bytes.
+var MaxSize uint64 = 1024 * 1024 * 1800
+
+// logDirs lists the candidate directories for new log files.
+var logDirs []string
+
+// If non-empty, overrides the choice of directory in which to write logs.
+// See createLogDirs for the full list of possible destinations.
+var logDir = flag.String("log_dir", "", "If non-empty, write log files in this directory")
+
+func createLogDirs() {
+ if *logDir != "" {
+ logDirs = append(logDirs, *logDir)
+ }
+ logDirs = append(logDirs, os.TempDir())
+}
+
+var (
+ pid = os.Getpid()
+ program = filepath.Base(os.Args[0])
+ host = "unknownhost"
+ userName = "unknownuser"
+)
+
+func init() {
+ h, err := os.Hostname()
+ if err == nil {
+ host = shortHostname(h)
+ }
+
+ current, err := user.Current()
+ if err == nil {
+ userName = current.Username
+ }
+
+ // Sanitize userName since it may contain filepath separators on Windows.
+ userName = strings.Replace(userName, `\`, "_", -1)
+}
+
+// shortHostname returns its argument, truncating at the first period.
+// For instance, given "www.google.com" it returns "www".
+func shortHostname(hostname string) string {
+ if i := strings.Index(hostname, "."); i >= 0 {
+ return hostname[:i]
+ }
+ return hostname
+}
+
+// logName returns a new log file name containing tag, with start time t, and
+// the name for the symlink for tag.
+func logName(tag string, t time.Time) (name, link string) {
+ name = fmt.Sprintf("%s.%s.%s.log.%s.%04d%02d%02d-%02d%02d%02d.%d",
+ program,
+ host,
+ userName,
+ tag,
+ t.Year(),
+ t.Month(),
+ t.Day(),
+ t.Hour(),
+ t.Minute(),
+ t.Second(),
+ pid)
+ return name, program + "." + tag
+}
+
+var onceLogDirs sync.Once
+
+// create creates a new log file and returns the file and its filename, which
+// contains tag ("INFO", "FATAL", etc.) and t. If the file is created
+// successfully, create also attempts to update the symlink for that tag, ignoring
+// errors.
+func create(tag string, t time.Time) (f *os.File, filename string, err error) {
+ onceLogDirs.Do(createLogDirs)
+ if len(logDirs) == 0 {
+ return nil, "", errors.New("log: no log dirs")
+ }
+ name, link := logName(tag, t)
+ var lastErr error
+ for _, dir := range logDirs {
+ fname := filepath.Join(dir, name)
+ f, err := os.Create(fname)
+ if err == nil {
+ symlink := filepath.Join(dir, link)
+ os.Remove(symlink) // ignore err
+ os.Symlink(name, symlink) // ignore err
+ return f, fname, nil
+ }
+ lastErr = err
+ }
+ return nil, "", fmt.Errorf("log: cannot create log: %v", lastErr)
+}
diff --git a/vendor/github.com/golang/mock/gomock/call.go b/vendor/github.com/golang/mock/gomock/call.go
index c560197..05c5ff9 100644
--- a/vendor/github.com/golang/mock/gomock/call.go
+++ b/vendor/github.com/golang/mock/gomock/call.go
@@ -17,6 +17,7 @@ package gomock
import (
"fmt"
"reflect"
+ "strconv"
"strings"
)
@@ -24,10 +25,11 @@ import (
type Call struct {
t TestReporter // for triggering test failures on invalid call setup
- receiver interface{} // the receiver of the method call
- method string // the name of the method
- args []Matcher // the args
- rets []interface{} // the return values (if any)
+ receiver interface{} // the receiver of the method call
+ method string // the name of the method
+ methodType reflect.Type // the type of the method
+ args []Matcher // the args
+ origin string // file and line number of call setup
preReqs []*Call // prerequisite calls
@@ -36,9 +38,44 @@ type Call struct {
numCalls int // actual number made
- // Actions
- doFunc reflect.Value
- setArgs map[int]reflect.Value
+ // actions are called when this Call is called. Each action gets the args and
+ // can set the return values by returning a non-nil slice. Actions run in the
+ // order they are created.
+ actions []func([]interface{}) []interface{}
+}
+
+// newCall creates a *Call. It requires the method type in order to support
+// unexported methods.
+func newCall(t TestReporter, receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
+ if h, ok := t.(testHelper); ok {
+ h.Helper()
+ }
+
+ // TODO: check arity, types.
+ margs := make([]Matcher, len(args))
+ for i, arg := range args {
+ if m, ok := arg.(Matcher); ok {
+ margs[i] = m
+ } else if arg == nil {
+ // Handle nil specially so that passing a nil interface value
+ // will match the typed nils of concrete args.
+ margs[i] = Nil()
+ } else {
+ margs[i] = Eq(arg)
+ }
+ }
+
+ origin := callerInfo(3)
+ actions := []func([]interface{}) []interface{}{func([]interface{}) []interface{} {
+ // Synthesize the zero value for each of the return args' types.
+ rets := make([]interface{}, methodType.NumOut())
+ for i := 0; i < methodType.NumOut(); i++ {
+ rets[i] = reflect.Zero(methodType.Out(i)).Interface()
+ }
+ return rets
+ }}
+ return &Call{t: t, receiver: receiver, method: method, methodType: methodType,
+ args: margs, origin: origin, minCalls: 1, maxCalls: 1, actions: actions}
}
// AnyTimes allows the expectation to be called 0 or more times
@@ -67,19 +104,69 @@ func (c *Call) MaxTimes(n int) *Call {
return c
}
-// Do declares the action to run when the call is matched.
+// DoAndReturn declares the action to run when the call is matched.
+// The return values from this function are returned by the mocked function.
// It takes an interface{} argument to support n-arity functions.
-func (c *Call) Do(f interface{}) *Call {
+func (c *Call) DoAndReturn(f interface{}) *Call {
// TODO: Check arity and types here, rather than dying badly elsewhere.
- c.doFunc = reflect.ValueOf(f)
+ v := reflect.ValueOf(f)
+
+ c.addAction(func(args []interface{}) []interface{} {
+ vargs := make([]reflect.Value, len(args))
+ ft := v.Type()
+ for i := 0; i < len(args); i++ {
+ if args[i] != nil {
+ vargs[i] = reflect.ValueOf(args[i])
+ } else {
+ // Use the zero value for the arg.
+ vargs[i] = reflect.Zero(ft.In(i))
+ }
+ }
+ vrets := v.Call(vargs)
+ rets := make([]interface{}, len(vrets))
+ for i, ret := range vrets {
+ rets[i] = ret.Interface()
+ }
+ return rets
+ })
return c
}
+// Do declares the action to run when the call is matched. The function's
+// return values are ignored to retain backward compatibility. To use the
+// return values call DoAndReturn.
+// It takes an interface{} argument to support n-arity functions.
+func (c *Call) Do(f interface{}) *Call {
+ // TODO: Check arity and types here, rather than dying badly elsewhere.
+ v := reflect.ValueOf(f)
+
+ c.addAction(func(args []interface{}) []interface{} {
+ vargs := make([]reflect.Value, len(args))
+ ft := v.Type()
+ for i := 0; i < len(args); i++ {
+ if args[i] != nil {
+ vargs[i] = reflect.ValueOf(args[i])
+ } else {
+ // Use the zero value for the arg.
+ vargs[i] = reflect.Zero(ft.In(i))
+ }
+ }
+ v.Call(vargs)
+ return nil
+ })
+ return c
+}
+
+// Return declares the values to be returned by the mocked function call.
func (c *Call) Return(rets ...interface{}) *Call {
- mt := c.methodType()
+ if h, ok := c.t.(testHelper); ok {
+ h.Helper()
+ }
+
+ mt := c.methodType
if len(rets) != mt.NumOut() {
- c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d",
- c.receiver, c.method, len(rets), mt.NumOut())
+ c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
+ c.receiver, c.method, len(rets), mt.NumOut(), c.origin)
}
for i, ret := range rets {
if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
@@ -90,8 +177,8 @@ func (c *Call) Return(rets ...interface{}) *Call {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
// ok
default:
- c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable",
- i, c.receiver, c.method, want)
+ c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
+ i, c.receiver, c.method, want, c.origin)
}
} else if got.AssignableTo(want) {
// Assignable type relation. Make the assignment now so that the generated code
@@ -100,31 +187,38 @@ func (c *Call) Return(rets ...interface{}) *Call {
v.Set(reflect.ValueOf(ret))
rets[i] = v.Interface()
} else {
- c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v",
- i, c.receiver, c.method, got, want)
+ c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
+ i, c.receiver, c.method, got, want, c.origin)
}
}
- c.rets = rets
+ c.addAction(func([]interface{}) []interface{} {
+ return rets
+ })
+
return c
}
+// Times declares the exact number of times a function call is expected to be executed.
func (c *Call) Times(n int) *Call {
c.minCalls, c.maxCalls = n, n
return c
}
// SetArg declares an action that will set the nth argument's value,
-// indirected through a pointer.
+// indirected through a pointer. Or, in the case of a slice, SetArg
+// will copy value's elements into the nth argument.
func (c *Call) SetArg(n int, value interface{}) *Call {
- if c.setArgs == nil {
- c.setArgs = make(map[int]reflect.Value)
+ if h, ok := c.t.(testHelper); ok {
+ h.Helper()
}
- mt := c.methodType()
+
+ mt := c.methodType
// TODO: This will break on variadic methods.
// We will need to check those at invocation time.
if n < 0 || n >= mt.NumIn() {
- c.t.Fatalf("SetArg(%d, ...) called for a method with %d args", n, mt.NumIn())
+ c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
+ n, mt.NumIn(), c.origin)
}
// Permit setting argument through an interface.
// In the interface case, we don't (nay, can't) check the type here.
@@ -133,14 +227,28 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
case reflect.Ptr:
dt := at.Elem()
if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
- c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v", n, vt, dt)
+ c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
+ n, vt, dt, c.origin)
}
case reflect.Interface:
// nothing to do
+ case reflect.Slice:
+ // nothing to do
default:
- c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v", n, at)
+ c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]",
+ n, at, c.origin)
}
- c.setArgs[n] = reflect.ValueOf(value)
+
+ c.addAction(func(args []interface{}) []interface{} {
+ v := reflect.ValueOf(value)
+ switch reflect.TypeOf(args[n]).Kind() {
+ case reflect.Slice:
+ setSlice(args[n], v)
+ default:
+ reflect.ValueOf(args[n]).Elem().Set(v)
+ }
+ return nil
+ })
return c
}
@@ -156,19 +264,22 @@ func (c *Call) isPreReq(other *Call) bool {
// After declares that the call may only match after preReq has been exhausted.
func (c *Call) After(preReq *Call) *Call {
+ if h, ok := c.t.(testHelper); ok {
+ h.Helper()
+ }
+
+ if c == preReq {
+ c.t.Fatalf("A call isn't allowed to be its own prerequisite")
+ }
if preReq.isPreReq(c) {
- msg := fmt.Sprintf(
- "Loop in call order: %v is a prerequisite to %v (possibly indirectly).",
- c, preReq,
- )
- panic(msg)
+ c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq)
}
c.preReqs = append(c.preReqs, preReq)
return c
}
-// Returns true iff the minimum number of calls have been made.
+// Returns true if the minimum number of calls have been made.
func (c *Call) satisfied() bool {
return c.numCalls >= c.minCalls
}
@@ -184,31 +295,105 @@ func (c *Call) String() string {
args[i] = arg.String()
}
arguments := strings.Join(args, ", ")
- return fmt.Sprintf("%T.%v(%s)", c.receiver, c.method, arguments)
+ return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin)
}
// Tests if the given call matches the expected call.
-func (c *Call) matches(args []interface{}) bool {
- if len(args) != len(c.args) {
- return false
- }
- for i, m := range c.args {
- if !m.Matches(args[i]) {
- return false
+// If yes, returns nil. If no, returns error with message explaining why it does not match.
+func (c *Call) matches(args []interface{}) error {
+ if !c.methodType.IsVariadic() {
+ if len(args) != len(c.args) {
+ return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
+ c.origin, len(args), len(c.args))
+ }
+
+ for i, m := range c.args {
+ if !m.Matches(args[i]) {
+ return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
+ c.origin, strconv.Itoa(i), args[i], m)
+ }
+ }
+ } else {
+ if len(c.args) < c.methodType.NumIn()-1 {
+ return fmt.Errorf("Expected call at %s has the wrong number of matchers. Got: %d, want: %d",
+ c.origin, len(c.args), c.methodType.NumIn()-1)
+ }
+ if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) {
+ return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
+ c.origin, len(args), len(c.args))
+ }
+ if len(args) < len(c.args)-1 {
+ return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
+ c.origin, len(args), len(c.args)-1)
+ }
+
+ for i, m := range c.args {
+ if i == len(c.args)-1 {
+ // The last arg has a possibility of a variadic argument, so let it branch
+
+ // sample: Foo(a int, b int, c ...int)
+
+ if len(c.args) == len(args) {
+ if m.Matches(args[i]) {
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, gomock.Any())
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, someSliceMatcher)
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC)
+ // Got Foo(a, b) want Foo(matcherA, matcherB)
+ // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD)
+ break
+ }
+ }
+ // The number of actual args don't match the number of matchers.
+ // If this function still matches it is because the last matcher
+ // matches all the remaining arguments or the lack of any.
+ // Convert the remaining arguments, if any, into a slice of the
+ // expected type.
+ vargsType := c.methodType.In(c.methodType.NumIn() - 1)
+ vargs := reflect.MakeSlice(vargsType, 0, len(args)-i)
+ for _, arg := range args[i:] {
+ vargs = reflect.Append(vargs, reflect.ValueOf(arg))
+ }
+ if m.Matches(vargs.Interface()) {
+ // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, gomock.Any())
+ // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, someSliceMatcher)
+ // Got Foo(a, b) want Foo(matcherA, matcherB, gomock.Any())
+ // Got Foo(a, b) want Foo(matcherA, matcherB, someEmptySliceMatcher)
+ break
+ }
+ // Wrong number of matchers or not match. Fail.
+ // Got Foo(a, b) want Foo(matcherA, matcherB, matcherC, matcherD)
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC, matcherD)
+ // Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD, matcherE)
+ // Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, matcherC, matcherD)
+ // Got Foo(a, b, c) want Foo(matcherA, matcherB)
+ return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
+ c.origin, strconv.Itoa(i), args[i:], c.args[i])
+ }
+
+ if !m.Matches(args[i]) {
+ return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
+ c.origin, strconv.Itoa(i), args[i], m)
+ }
}
}
// Check that all prerequisite calls have been satisfied.
for _, preReqCall := range c.preReqs {
if !preReqCall.satisfied() {
- return false
+ return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
+ c.origin, preReqCall, c)
}
}
- return true
+ // Check that the call is not exhausted.
+ if c.exhausted() {
+ return fmt.Errorf("Expected call at %s has already been called the max number of times.", c.origin)
+ }
+
+ return nil
}
-// dropPrereqs tells the expected Call to not re-check prerequite calls any
+// dropPrereqs tells the expected Call to not re-check prerequisite calls any
// longer, and to return its current set.
func (c *Call) dropPrereqs() (preReqs []*Call) {
preReqs = c.preReqs
@@ -216,48 +401,9 @@ func (c *Call) dropPrereqs() (preReqs []*Call) {
return
}
-func (c *Call) call(args []interface{}) (rets []interface{}, action func()) {
+func (c *Call) call(args []interface{}) []func([]interface{}) []interface{} {
c.numCalls++
-
- // Actions
- if c.doFunc.IsValid() {
- doArgs := make([]reflect.Value, len(args))
- ft := c.doFunc.Type()
- for i := 0; i < ft.NumIn(); i++ {
- if args[i] != nil {
- doArgs[i] = reflect.ValueOf(args[i])
- } else {
- // Use the zero value for the arg.
- doArgs[i] = reflect.Zero(ft.In(i))
- }
- }
- action = func() { c.doFunc.Call(doArgs) }
- }
- for n, v := range c.setArgs {
- reflect.ValueOf(args[n]).Elem().Set(v)
- }
-
- rets = c.rets
- if rets == nil {
- // Synthesize the zero value for each of the return args' types.
- mt := c.methodType()
- rets = make([]interface{}, mt.NumOut())
- for i := 0; i < mt.NumOut(); i++ {
- rets[i] = reflect.Zero(mt.Out(i)).Interface()
- }
- }
-
- return
-}
-
-func (c *Call) methodType() reflect.Type {
- recv := reflect.ValueOf(c.receiver)
- for i := 0; i < recv.Type().NumMethod(); i++ {
- if recv.Type().Method(i).Name == c.method {
- return recv.Method(i).Type()
- }
- }
- panic(fmt.Sprintf("gomock: failed finding method %s on %T", c.method, c.receiver))
+ return c.actions
}
// InOrder declares that the given calls should occur in order.
@@ -266,3 +412,14 @@ func InOrder(calls ...*Call) {
calls[i].After(calls[i-1])
}
}
+
+func setSlice(arg interface{}, v reflect.Value) {
+ va := reflect.ValueOf(arg)
+ for i := 0; i < v.Len(); i++ {
+ va.Index(i).Set(v.Index(i))
+ }
+}
+
+func (c *Call) addAction(action func([]interface{}) []interface{}) {
+ c.actions = append(c.actions, action)
+}
diff --git a/vendor/github.com/golang/mock/gomock/callset.go b/vendor/github.com/golang/mock/gomock/callset.go
index 1b7de4c..c44a8a5 100644
--- a/vendor/github.com/golang/mock/gomock/callset.go
+++ b/vendor/github.com/golang/mock/gomock/callset.go
@@ -14,63 +14,95 @@
package gomock
+import (
+ "bytes"
+ "fmt"
+)
+
// callSet represents a set of expected calls, indexed by receiver and method
// name.
-type callSet map[interface{}]map[string][]*Call
+type callSet struct {
+ // Calls that are still expected.
+ expected map[callSetKey][]*Call
+ // Calls that have been exhausted.
+ exhausted map[callSetKey][]*Call
+}
+
+// callSetKey is the key in the maps in callSet
+type callSetKey struct {
+ receiver interface{}
+ fname string
+}
+
+func newCallSet() *callSet {
+ return &callSet{make(map[callSetKey][]*Call), make(map[callSetKey][]*Call)}
+}
// Add adds a new expected call.
func (cs callSet) Add(call *Call) {
- methodMap, ok := cs[call.receiver]
- if !ok {
- methodMap = make(map[string][]*Call)
- cs[call.receiver] = methodMap
+ key := callSetKey{call.receiver, call.method}
+ m := cs.expected
+ if call.exhausted() {
+ m = cs.exhausted
}
- methodMap[call.method] = append(methodMap[call.method], call)
+ m[key] = append(m[key], call)
}
// Remove removes an expected call.
func (cs callSet) Remove(call *Call) {
- methodMap, ok := cs[call.receiver]
- if !ok {
- return
- }
- sl := methodMap[call.method]
- for i, c := range sl {
+ key := callSetKey{call.receiver, call.method}
+ calls := cs.expected[key]
+ for i, c := range calls {
if c == call {
- // quick removal; we don't need to maintain call order
- if len(sl) > 1 {
- sl[i] = sl[len(sl)-1]
- }
- methodMap[call.method] = sl[:len(sl)-1]
+ // maintain order for remaining calls
+ cs.expected[key] = append(calls[:i], calls[i+1:]...)
+ cs.exhausted[key] = append(cs.exhausted[key], call)
break
}
}
}
-// FindMatch searches for a matching call. Returns nil if no call matched.
-func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) *Call {
- methodMap, ok := cs[receiver]
- if !ok {
- return nil
- }
- calls, ok := methodMap[method]
- if !ok {
- return nil
- }
+// FindMatch searches for a matching call. Returns error with explanation message if no call matched.
+func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) (*Call, error) {
+ key := callSetKey{receiver, method}
- // Search through the unordered set of calls expected on a method on a
- // receiver.
- for _, call := range calls {
- // A call should not normally still be here if exhausted,
- // but it can happen if, for instance, .Times(0) was used.
- // Pretend the call doesn't match.
- if call.exhausted() {
- continue
- }
- if call.matches(args) {
- return call
+ // Search through the expected calls.
+ expected := cs.expected[key]
+ var callsErrors bytes.Buffer
+ for _, call := range expected {
+ err := call.matches(args)
+ if err != nil {
+ fmt.Fprintf(&callsErrors, "\n%v", err)
+ } else {
+ return call, nil
}
}
- return nil
+ // If we haven't found a match then search through the exhausted calls so we
+ // get useful error messages.
+ exhausted := cs.exhausted[key]
+ for _, call := range exhausted {
+ if err := call.matches(args); err != nil {
+ fmt.Fprintf(&callsErrors, "\n%v", err)
+ }
+ }
+
+ if len(expected)+len(exhausted) == 0 {
+ fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
+ }
+
+ return nil, fmt.Errorf(callsErrors.String())
+}
+
+// Failures returns the calls that are not satisfied.
+func (cs callSet) Failures() []*Call {
+ failures := make([]*Call, 0, len(cs.expected))
+ for _, calls := range cs.expected {
+ for _, call := range calls {
+ if !call.satisfied() {
+ failures = append(failures, call)
+ }
+ }
+ }
+ return failures
}
diff --git a/vendor/github.com/golang/mock/gomock/controller.go b/vendor/github.com/golang/mock/gomock/controller.go
index 6ca9528..d019961 100644
--- a/vendor/github.com/golang/mock/gomock/controller.go
+++ b/vendor/github.com/golang/mock/gomock/controller.go
@@ -55,7 +55,13 @@
// - Handle different argument/return types (e.g. ..., chan, map, interface).
package gomock
-import "sync"
+import (
+ "fmt"
+ "golang.org/x/net/context"
+ "reflect"
+ "runtime"
+ "sync"
+)
// A TestReporter is something that can be used to report test failures.
// It is satisfied by the standard library's *testing.T.
@@ -70,76 +76,109 @@ type TestReporter interface {
type Controller struct {
mu sync.Mutex
t TestReporter
- expectedCalls callSet
+ expectedCalls *callSet
}
func NewController(t TestReporter) *Controller {
return &Controller{
t: t,
- expectedCalls: make(callSet),
+ expectedCalls: newCallSet(),
}
}
+type cancelReporter struct {
+ t TestReporter
+ cancel func()
+}
+
+func (r *cancelReporter) Errorf(format string, args ...interface{}) { r.t.Errorf(format, args...) }
+func (r *cancelReporter) Fatalf(format string, args ...interface{}) {
+ defer r.cancel()
+ r.t.Fatalf(format, args...)
+}
+
+// WithContext returns a new Controller and a Context, which is cancelled on any
+// fatal failure.
+func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context) {
+ ctx, cancel := context.WithCancel(ctx)
+ return NewController(&cancelReporter{t, cancel}), ctx
+}
+
func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
- // TODO: check arity, types.
- margs := make([]Matcher, len(args))
- for i, arg := range args {
- if m, ok := arg.(Matcher); ok {
- margs[i] = m
- } else if arg == nil {
- // Handle nil specially so that passing a nil interface value
- // will match the typed nils of concrete args.
- margs[i] = Nil()
- } else {
- margs[i] = Eq(arg)
+ if h, ok := ctrl.t.(testHelper); ok {
+ h.Helper()
+ }
+
+ recv := reflect.ValueOf(receiver)
+ for i := 0; i < recv.Type().NumMethod(); i++ {
+ if recv.Type().Method(i).Name == method {
+ return ctrl.RecordCallWithMethodType(receiver, method, recv.Method(i).Type(), args...)
}
}
+ ctrl.t.Fatalf("gomock: failed finding method %s on %T", method, receiver)
+ panic("unreachable")
+}
+
+func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method string, methodType reflect.Type, args ...interface{}) *Call {
+ if h, ok := ctrl.t.(testHelper); ok {
+ h.Helper()
+ }
+
+ call := newCall(ctrl.t, receiver, method, methodType, args...)
ctrl.mu.Lock()
defer ctrl.mu.Unlock()
-
- call := &Call{t: ctrl.t, receiver: receiver, method: method, args: margs, minCalls: 1, maxCalls: 1}
-
ctrl.expectedCalls.Add(call)
+
return call
}
func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
- ctrl.mu.Lock()
- defer ctrl.mu.Unlock()
-
- expected := ctrl.expectedCalls.FindMatch(receiver, method, args)
- if expected == nil {
- ctrl.t.Fatalf("no matching expected call: %T.%v(%v)", receiver, method, args)
+ if h, ok := ctrl.t.(testHelper); ok {
+ h.Helper()
}
- // Two things happen here:
- // * the matching call no longer needs to check prerequite calls,
- // * and the prerequite calls are no longer expected, so remove them.
- preReqCalls := expected.dropPrereqs()
- for _, preReqCall := range preReqCalls {
- ctrl.expectedCalls.Remove(preReqCall)
- }
+ // Nest this code so we can use defer to make sure the lock is released.
+ actions := func() []func([]interface{}) []interface{} {
+ ctrl.mu.Lock()
+ defer ctrl.mu.Unlock()
- rets, action := expected.call(args)
- if expected.exhausted() {
- ctrl.expectedCalls.Remove(expected)
- }
+ expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args)
+ if err != nil {
+ origin := callerInfo(2)
+ ctrl.t.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err)
+ }
- // Don't hold the lock while doing the call's action (if any)
- // so that actions may execute concurrently.
- // We use the deferred Unlock to capture any panics that happen above;
- // here we add a deferred Lock to balance it.
- ctrl.mu.Unlock()
- defer ctrl.mu.Lock()
- if action != nil {
- action()
+ // Two things happen here:
+ // * the matching call no longer needs to check prerequite calls,
+ // * and the prerequite calls are no longer expected, so remove them.
+ preReqCalls := expected.dropPrereqs()
+ for _, preReqCall := range preReqCalls {
+ ctrl.expectedCalls.Remove(preReqCall)
+ }
+
+ actions := expected.call(args)
+ if expected.exhausted() {
+ ctrl.expectedCalls.Remove(expected)
+ }
+ return actions
+ }()
+
+ var rets []interface{}
+ for _, action := range actions {
+ if r := action(args); r != nil {
+ rets = r
+ }
}
return rets
}
func (ctrl *Controller) Finish() {
+ if h, ok := ctrl.t.(testHelper); ok {
+ h.Helper()
+ }
+
ctrl.mu.Lock()
defer ctrl.mu.Unlock()
@@ -150,18 +189,23 @@ func (ctrl *Controller) Finish() {
}
// Check that all remaining expected calls are satisfied.
- failures := false
- for _, methodMap := range ctrl.expectedCalls {
- for _, calls := range methodMap {
- for _, call := range calls {
- if !call.satisfied() {
- ctrl.t.Errorf("missing call(s) to %v", call)
- failures = true
- }
- }
- }
+ failures := ctrl.expectedCalls.Failures()
+ for _, call := range failures {
+ ctrl.t.Errorf("missing call(s) to %v", call)
}
- if failures {
+ if len(failures) != 0 {
ctrl.t.Fatalf("aborting test due to missing call(s)")
}
}
+
+func callerInfo(skip int) string {
+ if _, file, line, ok := runtime.Caller(skip + 1); ok {
+ return fmt.Sprintf("%s:%d", file, line)
+ }
+ return "unknown file"
+}
+
+type testHelper interface {
+ TestReporter
+ Helper()
+}
diff --git a/vendor/github.com/golang/mock/gomock/matchers.go b/vendor/github.com/golang/mock/gomock/matchers.go
index 32628ae..e8b1ddc 100644
--- a/vendor/github.com/golang/mock/gomock/matchers.go
+++ b/vendor/github.com/golang/mock/gomock/matchers.go
@@ -1,3 +1,5 @@
+//go:generate mockgen -destination mock_matcher/mock_matcher.go github.com/golang/mock/gomock Matcher
+
// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,7 +24,7 @@ import (
// A Matcher is a representation of a class of values.
// It is used to represent the valid or expected arguments to a mocked method.
type Matcher interface {
- // Matches returns whether y is a match.
+ // Matches returns whether x is a match.
Matches(x interface{}) bool
// String describes what the matcher matches.
diff --git a/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go b/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go
new file mode 100644
index 0000000..7e4b4c8
--- /dev/null
+++ b/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go
@@ -0,0 +1,57 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/golang/mock/gomock (interfaces: Matcher)
+
+// Package mock_gomock is a generated GoMock package.
+package mock_gomock
+
+import (
+ gomock "github.com/golang/mock/gomock"
+ reflect "reflect"
+)
+
+// MockMatcher is a mock of Matcher interface
+type MockMatcher struct {
+ ctrl *gomock.Controller
+ recorder *MockMatcherMockRecorder
+}
+
+// MockMatcherMockRecorder is the mock recorder for MockMatcher
+type MockMatcherMockRecorder struct {
+ mock *MockMatcher
+}
+
+// NewMockMatcher creates a new mock instance
+func NewMockMatcher(ctrl *gomock.Controller) *MockMatcher {
+ mock := &MockMatcher{ctrl: ctrl}
+ mock.recorder = &MockMatcherMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use
+func (m *MockMatcher) EXPECT() *MockMatcherMockRecorder {
+ return m.recorder
+}
+
+// Matches mocks base method
+func (m *MockMatcher) Matches(arg0 interface{}) bool {
+ ret := m.ctrl.Call(m, "Matches", arg0)
+ ret0, _ := ret[0].(bool)
+ return ret0
+}
+
+// Matches indicates an expected call of Matches
+func (mr *MockMatcherMockRecorder) Matches(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Matches", reflect.TypeOf((*MockMatcher)(nil).Matches), arg0)
+}
+
+// String mocks base method
+func (m *MockMatcher) String() string {
+ ret := m.ctrl.Call(m, "String")
+ ret0, _ := ret[0].(string)
+ return ret0
+}
+
+// String indicates an expected call of String
+func (mr *MockMatcherMockRecorder) String() *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "String", reflect.TypeOf((*MockMatcher)(nil).String))
+}
diff --git a/vendor/github.com/golang/protobuf/LICENSE b/vendor/github.com/golang/protobuf/LICENSE
new file mode 100644
index 0000000..1b1b192
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/LICENSE
@@ -0,0 +1,31 @@
+Go support for Protocol Buffers - Google's data interchange format
+
+Copyright 2010 The Go Authors. All rights reserved.
+https://github.com/golang/protobuf
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/vendor/github.com/golang/protobuf/proto/Makefile b/vendor/github.com/golang/protobuf/proto/Makefile
new file mode 100644
index 0000000..e2e0651
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/Makefile
@@ -0,0 +1,43 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+install:
+ go install
+
+test: install generate-test-pbs
+ go test
+
+
+generate-test-pbs:
+ make install
+ make -C testdata
+ protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
+ make
diff --git a/vendor/github.com/golang/protobuf/proto/clone.go b/vendor/github.com/golang/protobuf/proto/clone.go
new file mode 100644
index 0000000..e392575
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/clone.go
@@ -0,0 +1,229 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Protocol buffer deep copy and merge.
+// TODO: RawMessage.
+
+package proto
+
+import (
+ "log"
+ "reflect"
+ "strings"
+)
+
+// Clone returns a deep copy of a protocol buffer.
+func Clone(pb Message) Message {
+ in := reflect.ValueOf(pb)
+ if in.IsNil() {
+ return pb
+ }
+
+ out := reflect.New(in.Type().Elem())
+ // out is empty so a merge is a deep copy.
+ mergeStruct(out.Elem(), in.Elem())
+ return out.Interface().(Message)
+}
+
+// Merge merges src into dst.
+// Required and optional fields that are set in src will be set to that value in dst.
+// Elements of repeated fields will be appended.
+// Merge panics if src and dst are not the same type, or if dst is nil.
+func Merge(dst, src Message) {
+ in := reflect.ValueOf(src)
+ out := reflect.ValueOf(dst)
+ if out.IsNil() {
+ panic("proto: nil destination")
+ }
+ if in.Type() != out.Type() {
+ // Explicit test prior to mergeStruct so that mistyped nils will fail
+ panic("proto: type mismatch")
+ }
+ if in.IsNil() {
+ // Merging nil into non-nil is a quiet no-op
+ return
+ }
+ mergeStruct(out.Elem(), in.Elem())
+}
+
+func mergeStruct(out, in reflect.Value) {
+ sprop := GetProperties(in.Type())
+ for i := 0; i < in.NumField(); i++ {
+ f := in.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
+ }
+
+ if emIn, ok := extendable(in.Addr().Interface()); ok {
+ emOut, _ := extendable(out.Addr().Interface())
+ mIn, muIn := emIn.extensionsRead()
+ if mIn != nil {
+ mOut := emOut.extensionsWrite()
+ muIn.Lock()
+ mergeExtension(mOut, mIn)
+ muIn.Unlock()
+ }
+ }
+
+ uf := in.FieldByName("XXX_unrecognized")
+ if !uf.IsValid() {
+ return
+ }
+ uin := uf.Bytes()
+ if len(uin) > 0 {
+ out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
+ }
+}
+
+// mergeAny performs a merge between two values of the same type.
+// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
+// prop is set if this is a struct field (it may be nil).
+func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
+ if in.Type() == protoMessageType {
+ if !in.IsNil() {
+ if out.IsNil() {
+ out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
+ } else {
+ Merge(out.Interface().(Message), in.Interface().(Message))
+ }
+ }
+ return
+ }
+ switch in.Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64:
+ if !viaPtr && isProto3Zero(in) {
+ return
+ }
+ out.Set(in)
+ case reflect.Interface:
+ // Probably a oneof field; copy non-nil values.
+ if in.IsNil() {
+ return
+ }
+ // Allocate destination if it is not set, or set to a different type.
+ // Otherwise we will merge as normal.
+ if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
+ out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
+ }
+ mergeAny(out.Elem(), in.Elem(), false, nil)
+ case reflect.Map:
+ if in.Len() == 0 {
+ return
+ }
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(in.Type()))
+ }
+ // For maps with value types of *T or []byte we need to deep copy each value.
+ elemKind := in.Type().Elem().Kind()
+ for _, key := range in.MapKeys() {
+ var val reflect.Value
+ switch elemKind {
+ case reflect.Ptr:
+ val = reflect.New(in.Type().Elem().Elem())
+ mergeAny(val, in.MapIndex(key), false, nil)
+ case reflect.Slice:
+ val = in.MapIndex(key)
+ val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
+ default:
+ val = in.MapIndex(key)
+ }
+ out.SetMapIndex(key, val)
+ }
+ case reflect.Ptr:
+ if in.IsNil() {
+ return
+ }
+ if out.IsNil() {
+ out.Set(reflect.New(in.Elem().Type()))
+ }
+ mergeAny(out.Elem(), in.Elem(), true, nil)
+ case reflect.Slice:
+ if in.IsNil() {
+ return
+ }
+ if in.Type().Elem().Kind() == reflect.Uint8 {
+ // []byte is a scalar bytes field, not a repeated field.
+
+ // Edge case: if this is in a proto3 message, a zero length
+ // bytes field is considered the zero value, and should not
+ // be merged.
+ if prop != nil && prop.proto3 && in.Len() == 0 {
+ return
+ }
+
+ // Make a deep copy.
+ // Append to []byte{} instead of []byte(nil) so that we never end up
+ // with a nil result.
+ out.SetBytes(append([]byte{}, in.Bytes()...))
+ return
+ }
+ n := in.Len()
+ if out.IsNil() {
+ out.Set(reflect.MakeSlice(in.Type(), 0, n))
+ }
+ switch in.Type().Elem().Kind() {
+ case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
+ reflect.String, reflect.Uint32, reflect.Uint64:
+ out.Set(reflect.AppendSlice(out, in))
+ default:
+ for i := 0; i < n; i++ {
+ x := reflect.Indirect(reflect.New(in.Type().Elem()))
+ mergeAny(x, in.Index(i), false, nil)
+ out.Set(reflect.Append(out, x))
+ }
+ }
+ case reflect.Struct:
+ mergeStruct(out, in)
+ default:
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to copy %v", in)
+ }
+}
+
+func mergeExtension(out, in map[int32]Extension) {
+ for extNum, eIn := range in {
+ eOut := Extension{desc: eIn.desc}
+ if eIn.value != nil {
+ v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
+ mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
+ eOut.value = v.Interface()
+ }
+ if eIn.enc != nil {
+ eOut.enc = make([]byte, len(eIn.enc))
+ copy(eOut.enc, eIn.enc)
+ }
+
+ out[extNum] = eOut
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/proto/decode.go b/vendor/github.com/golang/protobuf/proto/decode.go
new file mode 100644
index 0000000..aa20729
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/decode.go
@@ -0,0 +1,970 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for decoding protocol buffer data to construct in-memory representations.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "reflect"
+)
+
+// errOverflow is returned when an integer is too large to be represented.
+var errOverflow = errors.New("proto: integer overflow")
+
+// ErrInternalBadWireType is returned by generated code when an incorrect
+// wire type is encountered. It does not get returned to user code.
+var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
+
+// The fundamental decoders that interpret bytes on the wire.
+// Those that take integer types all return uint64 and are
+// therefore of type valueDecoder.
+
+// DecodeVarint reads a varint-encoded integer from the slice.
+// It returns the integer and the number of bytes consumed, or
+// zero if there is not enough.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func DecodeVarint(buf []byte) (x uint64, n int) {
+ for shift := uint(0); shift < 64; shift += 7 {
+ if n >= len(buf) {
+ return 0, 0
+ }
+ b := uint64(buf[n])
+ n++
+ x |= (b & 0x7F) << shift
+ if (b & 0x80) == 0 {
+ return x, n
+ }
+ }
+
+ // The number is too large to represent in a 64-bit value.
+ return 0, 0
+}
+
+func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
+ i := p.index
+ l := len(p.buf)
+
+ for shift := uint(0); shift < 64; shift += 7 {
+ if i >= l {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ b := p.buf[i]
+ i++
+ x |= (uint64(b) & 0x7F) << shift
+ if b < 0x80 {
+ p.index = i
+ return
+ }
+ }
+
+ // The number is too large to represent in a 64-bit value.
+ err = errOverflow
+ return
+}
+
+// DecodeVarint reads a varint-encoded integer from the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) DecodeVarint() (x uint64, err error) {
+ i := p.index
+ buf := p.buf
+
+ if i >= len(buf) {
+ return 0, io.ErrUnexpectedEOF
+ } else if buf[i] < 0x80 {
+ p.index++
+ return uint64(buf[i]), nil
+ } else if len(buf)-i < 10 {
+ return p.decodeVarintSlow()
+ }
+
+ var b uint64
+ // we already checked the first byte
+ x = uint64(buf[i]) - 0x80
+ i++
+
+ b = uint64(buf[i])
+ i++
+ x += b << 7
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 7
+
+ b = uint64(buf[i])
+ i++
+ x += b << 14
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 14
+
+ b = uint64(buf[i])
+ i++
+ x += b << 21
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 21
+
+ b = uint64(buf[i])
+ i++
+ x += b << 28
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 28
+
+ b = uint64(buf[i])
+ i++
+ x += b << 35
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 35
+
+ b = uint64(buf[i])
+ i++
+ x += b << 42
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 42
+
+ b = uint64(buf[i])
+ i++
+ x += b << 49
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 49
+
+ b = uint64(buf[i])
+ i++
+ x += b << 56
+ if b&0x80 == 0 {
+ goto done
+ }
+ x -= 0x80 << 56
+
+ b = uint64(buf[i])
+ i++
+ x += b << 63
+ if b&0x80 == 0 {
+ goto done
+ }
+ // x -= 0x80 << 63 // Always zero.
+
+ return 0, errOverflow
+
+done:
+ p.index = i
+ return x, nil
+}
+
+// DecodeFixed64 reads a 64-bit integer from the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) DecodeFixed64() (x uint64, err error) {
+ // x, err already 0
+ i := p.index + 8
+ if i < 0 || i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-8])
+ x |= uint64(p.buf[i-7]) << 8
+ x |= uint64(p.buf[i-6]) << 16
+ x |= uint64(p.buf[i-5]) << 24
+ x |= uint64(p.buf[i-4]) << 32
+ x |= uint64(p.buf[i-3]) << 40
+ x |= uint64(p.buf[i-2]) << 48
+ x |= uint64(p.buf[i-1]) << 56
+ return
+}
+
+// DecodeFixed32 reads a 32-bit integer from the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) DecodeFixed32() (x uint64, err error) {
+ // x, err already 0
+ i := p.index + 4
+ if i < 0 || i > len(p.buf) {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+ p.index = i
+
+ x = uint64(p.buf[i-4])
+ x |= uint64(p.buf[i-3]) << 8
+ x |= uint64(p.buf[i-2]) << 16
+ x |= uint64(p.buf[i-1]) << 24
+ return
+}
+
+// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
+// from the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
+ return
+}
+
+// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
+// from the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
+ x, err = p.DecodeVarint()
+ if err != nil {
+ return
+ }
+ x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
+ return
+}
+
+// These are not ValueDecoders: they produce an array of bytes or a string.
+// bytes, embedded messages
+
+// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
+ n, err := p.DecodeVarint()
+ if err != nil {
+ return nil, err
+ }
+
+ nb := int(n)
+ if nb < 0 {
+ return nil, fmt.Errorf("proto: bad byte length %d", nb)
+ }
+ end := p.index + nb
+ if end < p.index || end > len(p.buf) {
+ return nil, io.ErrUnexpectedEOF
+ }
+
+ if !alloc {
+ // todo: check if can get more uses of alloc=false
+ buf = p.buf[p.index:end]
+ p.index += nb
+ return
+ }
+
+ buf = make([]byte, nb)
+ copy(buf, p.buf[p.index:])
+ p.index += nb
+ return
+}
+
+// DecodeStringBytes reads an encoded string from the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) DecodeStringBytes() (s string, err error) {
+ buf, err := p.DecodeRawBytes(false)
+ if err != nil {
+ return
+ }
+ return string(buf), nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+// If the protocol buffer has extensions, and the field matches, add it as an extension.
+// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
+func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
+ oi := o.index
+
+ err := o.skip(t, tag, wire)
+ if err != nil {
+ return err
+ }
+
+ if !unrecField.IsValid() {
+ return nil
+ }
+
+ ptr := structPointer_Bytes(base, unrecField)
+
+ // Add the skipped field to struct field
+ obuf := o.buf
+
+ o.buf = *ptr
+ o.EncodeVarint(uint64(tag<<3 | wire))
+ *ptr = append(o.buf, obuf[oi:o.index]...)
+
+ o.buf = obuf
+
+ return nil
+}
+
+// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
+func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
+
+ var u uint64
+ var err error
+
+ switch wire {
+ case WireVarint:
+ _, err = o.DecodeVarint()
+ case WireFixed64:
+ _, err = o.DecodeFixed64()
+ case WireBytes:
+ _, err = o.DecodeRawBytes(false)
+ case WireFixed32:
+ _, err = o.DecodeFixed32()
+ case WireStartGroup:
+ for {
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ fwire := int(u & 0x7)
+ if fwire == WireEndGroup {
+ break
+ }
+ ftag := int(u >> 3)
+ err = o.skip(t, ftag, fwire)
+ if err != nil {
+ break
+ }
+ }
+ default:
+ err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
+ }
+ return err
+}
+
+// Unmarshaler is the interface representing objects that can
+// unmarshal themselves. The method should reset the receiver before
+// decoding starts. The argument points to data that may be
+// overwritten, so implementations should not keep references to the
+// buffer.
+type Unmarshaler interface {
+ Unmarshal([]byte) error
+}
+
+// Unmarshal parses the protocol buffer representation in buf and places the
+// decoded result in pb. If the struct underlying pb does not match
+// the data in buf, the results can be unpredictable.
+//
+// Unmarshal resets pb before starting to unmarshal, so any
+// existing data in pb is always removed. Use UnmarshalMerge
+// to preserve and append to existing data.
+func Unmarshal(buf []byte, pb Message) error {
+ pb.Reset()
+ return UnmarshalMerge(buf, pb)
+}
+
+// UnmarshalMerge parses the protocol buffer representation in buf and
+// writes the decoded result to pb. If the struct underlying pb does not match
+// the data in buf, the results can be unpredictable.
+//
+// UnmarshalMerge merges into existing data in pb.
+// Most code should use Unmarshal instead.
+func UnmarshalMerge(buf []byte, pb Message) error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ return u.Unmarshal(buf)
+ }
+ return NewBuffer(buf).Unmarshal(pb)
+}
+
+// DecodeMessage reads a count-delimited message from the Buffer.
+func (p *Buffer) DecodeMessage(pb Message) error {
+ enc, err := p.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+ return NewBuffer(enc).Unmarshal(pb)
+}
+
+// DecodeGroup reads a tag-delimited group from the Buffer.
+func (p *Buffer) DecodeGroup(pb Message) error {
+ typ, base, err := getbase(pb)
+ if err != nil {
+ return err
+ }
+ return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
+}
+
+// Unmarshal parses the protocol buffer representation in the
+// Buffer and places the decoded result in pb. If the struct
+// underlying pb does not match the data in the buffer, the results can be
+// unpredictable.
+//
+// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
+func (p *Buffer) Unmarshal(pb Message) error {
+ // If the object can unmarshal itself, let it.
+ if u, ok := pb.(Unmarshaler); ok {
+ err := u.Unmarshal(p.buf[p.index:])
+ p.index = len(p.buf)
+ return err
+ }
+
+ typ, base, err := getbase(pb)
+ if err != nil {
+ return err
+ }
+
+ err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
+
+ if collectStats {
+ stats.Decode++
+ }
+
+ return err
+}
+
+// unmarshalType does the work of unmarshaling a structure.
+func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
+ var state errorState
+ required, reqFields := prop.reqCount, uint64(0)
+
+ var err error
+ for err == nil && o.index < len(o.buf) {
+ oi := o.index
+ var u uint64
+ u, err = o.DecodeVarint()
+ if err != nil {
+ break
+ }
+ wire := int(u & 0x7)
+ if wire == WireEndGroup {
+ if is_group {
+ if required > 0 {
+ // Not enough information to determine the exact field.
+ // (See below.)
+ return &RequiredNotSetError{"{Unknown}"}
+ }
+ return nil // input is satisfied
+ }
+ return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
+ }
+ tag := int(u >> 3)
+ if tag <= 0 {
+ return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
+ }
+ fieldnum, ok := prop.decoderTags.get(tag)
+ if !ok {
+ // Maybe it's an extension?
+ if prop.extendable {
+ if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
+ if err = o.skip(st, tag, wire); err == nil {
+ extmap := e.extensionsWrite()
+ ext := extmap[int32(tag)] // may be missing
+ ext.enc = append(ext.enc, o.buf[oi:o.index]...)
+ extmap[int32(tag)] = ext
+ }
+ continue
+ }
+ }
+ // Maybe it's a oneof?
+ if prop.oneofUnmarshaler != nil {
+ m := structPointer_Interface(base, st).(Message)
+ // First return value indicates whether tag is a oneof field.
+ ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
+ if err == ErrInternalBadWireType {
+ // Map the error to something more descriptive.
+ // Do the formatting here to save generated code space.
+ err = fmt.Errorf("bad wiretype for oneof field in %T", m)
+ }
+ if ok {
+ continue
+ }
+ }
+ err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
+ continue
+ }
+ p := prop.Prop[fieldnum]
+
+ if p.dec == nil {
+ fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
+ continue
+ }
+ dec := p.dec
+ if wire != WireStartGroup && wire != p.WireType {
+ if wire == WireBytes && p.packedDec != nil {
+ // a packable field
+ dec = p.packedDec
+ } else {
+ err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
+ continue
+ }
+ }
+ decErr := dec(o, p, base)
+ if decErr != nil && !state.shouldContinue(decErr, p) {
+ err = decErr
+ }
+ if err == nil && p.Required {
+ // Successfully decoded a required field.
+ if tag <= 64 {
+ // use bitmap for fields 1-64 to catch field reuse.
+ var mask uint64 = 1 << uint64(tag-1)
+ if reqFields&mask == 0 {
+ // new required field
+ reqFields |= mask
+ required--
+ }
+ } else {
+ // This is imprecise. It can be fooled by a required field
+ // with a tag > 64 that is encoded twice; that's very rare.
+ // A fully correct implementation would require allocating
+ // a data structure, which we would like to avoid.
+ required--
+ }
+ }
+ }
+ if err == nil {
+ if is_group {
+ return io.ErrUnexpectedEOF
+ }
+ if state.err != nil {
+ return state.err
+ }
+ if required > 0 {
+ // Not enough information to determine the exact field. If we use extra
+ // CPU, we could determine the field only if the missing required field
+ // has a tag <= 64 and we check reqFields.
+ return &RequiredNotSetError{"{Unknown}"}
+ }
+ }
+ return err
+}
+
+// Individual type decoders
+// For each,
+// u is the decoded value,
+// v is a pointer to the field (pointer) in the struct
+
+// Sizes of the pools to allocate inside the Buffer.
+// The goal is modest amortization and allocation
+// on at least 16-byte boundaries.
+const (
+ boolPoolSize = 16
+ uint32PoolSize = 8
+ uint64PoolSize = 4
+)
+
+// Decode a bool.
+func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ if len(o.bools) == 0 {
+ o.bools = make([]bool, boolPoolSize)
+ }
+ o.bools[0] = u != 0
+ *structPointer_Bool(base, p.field) = &o.bools[0]
+ o.bools = o.bools[1:]
+ return nil
+}
+
+func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ *structPointer_BoolVal(base, p.field) = u != 0
+ return nil
+}
+
+// Decode an int32.
+func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
+ return nil
+}
+
+func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
+ return nil
+}
+
+// Decode an int64.
+func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word64_Set(structPointer_Word64(base, p.field), o, u)
+ return nil
+}
+
+func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
+ return nil
+}
+
+// Decode a string.
+func (o *Buffer) dec_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ *structPointer_String(base, p.field) = &s
+ return nil
+}
+
+func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ *structPointer_StringVal(base, p.field) = s
+ return nil
+}
+
+// Decode a slice of bytes ([]byte).
+func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ *structPointer_Bytes(base, p.field) = b
+ return nil
+}
+
+// Decode a slice of bools ([]bool).
+func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v := structPointer_BoolSlice(base, p.field)
+ *v = append(*v, u != 0)
+ return nil
+}
+
+// Decode a slice of bools ([]bool) in packed format.
+func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
+ v := structPointer_BoolSlice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded bools
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+
+ y := *v
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ y = append(y, u != 0)
+ }
+
+ *v = y
+ return nil
+}
+
+// Decode a slice of int32s ([]int32).
+func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ structPointer_Word32Slice(base, p.field).Append(uint32(u))
+ return nil
+}
+
+// Decode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Slice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int32s
+
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v.Append(uint32(u))
+ }
+ return nil
+}
+
+// Decode a slice of int64s ([]int64).
+func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+
+ structPointer_Word64Slice(base, p.field).Append(u)
+ return nil
+}
+
+// Decode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64Slice(base, p.field)
+
+ nn, err := o.DecodeVarint()
+ if err != nil {
+ return err
+ }
+ nb := int(nn) // number of bytes of encoded int64s
+
+ fin := o.index + nb
+ if fin < o.index {
+ return errOverflow
+ }
+ for o.index < fin {
+ u, err := p.valDec(o)
+ if err != nil {
+ return err
+ }
+ v.Append(u)
+ }
+ return nil
+}
+
+// Decode a slice of strings ([]string).
+func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
+ s, err := o.DecodeStringBytes()
+ if err != nil {
+ return err
+ }
+ v := structPointer_StringSlice(base, p.field)
+ *v = append(*v, s)
+ return nil
+}
+
+// Decode a slice of slice of bytes ([][]byte).
+func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
+ b, err := o.DecodeRawBytes(true)
+ if err != nil {
+ return err
+ }
+ v := structPointer_BytesSlice(base, p.field)
+ *v = append(*v, b)
+ return nil
+}
+
+// Decode a map field.
+func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
+ raw, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+ oi := o.index // index at the end of this map entry
+ o.index -= len(raw) // move buffer back to start of map entry
+
+ mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
+ if mptr.Elem().IsNil() {
+ mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
+ }
+ v := mptr.Elem() // map[K]V
+
+ // Prepare addressable doubly-indirect placeholders for the key and value types.
+ // See enc_new_map for why.
+ keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
+ keybase := toStructPointer(keyptr.Addr()) // **K
+
+ var valbase structPointer
+ var valptr reflect.Value
+ switch p.mtype.Elem().Kind() {
+ case reflect.Slice:
+ // []byte
+ var dummy []byte
+ valptr = reflect.ValueOf(&dummy) // *[]byte
+ valbase = toStructPointer(valptr) // *[]byte
+ case reflect.Ptr:
+ // message; valptr is **Msg; need to allocate the intermediate pointer
+ valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+ valptr.Set(reflect.New(valptr.Type().Elem()))
+ valbase = toStructPointer(valptr)
+ default:
+ // everything else
+ valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
+ valbase = toStructPointer(valptr.Addr()) // **V
+ }
+
+ // Decode.
+ // This parses a restricted wire format, namely the encoding of a message
+ // with two fields. See enc_new_map for the format.
+ for o.index < oi {
+ // tagcode for key and value properties are always a single byte
+ // because they have tags 1 and 2.
+ tagcode := o.buf[o.index]
+ o.index++
+ switch tagcode {
+ case p.mkeyprop.tagcode[0]:
+ if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
+ return err
+ }
+ case p.mvalprop.tagcode[0]:
+ if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
+ return err
+ }
+ default:
+ // TODO: Should we silently skip this instead?
+ return fmt.Errorf("proto: bad map data tag %d", raw[0])
+ }
+ }
+ keyelem, valelem := keyptr.Elem(), valptr.Elem()
+ if !keyelem.IsValid() {
+ keyelem = reflect.Zero(p.mtype.Key())
+ }
+ if !valelem.IsValid() {
+ valelem = reflect.Zero(p.mtype.Elem())
+ }
+
+ v.SetMapIndex(keyelem, valelem)
+ return nil
+}
+
+// Decode a group.
+func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
+ bas := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(bas) {
+ // allocate new nested message
+ bas = toStructPointer(reflect.New(p.stype))
+ structPointer_SetStructPointer(base, p.field, bas)
+ }
+ return o.unmarshalType(p.stype, p.sprop, true, bas)
+}
+
+// Decode an embedded message.
+func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
+ raw, e := o.DecodeRawBytes(false)
+ if e != nil {
+ return e
+ }
+
+ bas := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(bas) {
+ // allocate new nested message
+ bas = toStructPointer(reflect.New(p.stype))
+ structPointer_SetStructPointer(base, p.field, bas)
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ iv := structPointer_Interface(bas, p.stype)
+ return iv.(Unmarshaler).Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, p.sprop, false, bas)
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
+
+// Decode a slice of embedded messages.
+func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
+ return o.dec_slice_struct(p, false, base)
+}
+
+// Decode a slice of embedded groups.
+func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
+ return o.dec_slice_struct(p, true, base)
+}
+
+// Decode a slice of structs ([]*struct).
+func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
+ v := reflect.New(p.stype)
+ bas := toStructPointer(v)
+ structPointer_StructPointerSlice(base, p.field).Append(bas)
+
+ if is_group {
+ err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
+ return err
+ }
+
+ raw, err := o.DecodeRawBytes(false)
+ if err != nil {
+ return err
+ }
+
+ // If the object can unmarshal itself, let it.
+ if p.isUnmarshaler {
+ iv := v.Interface()
+ return iv.(Unmarshaler).Unmarshal(raw)
+ }
+
+ obuf := o.buf
+ oi := o.index
+ o.buf = raw
+ o.index = 0
+
+ err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
+
+ o.buf = obuf
+ o.index = oi
+
+ return err
+}
diff --git a/vendor/github.com/golang/protobuf/proto/encode.go b/vendor/github.com/golang/protobuf/proto/encode.go
new file mode 100644
index 0000000..8b84d1b
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/encode.go
@@ -0,0 +1,1362 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// RequiredNotSetError is the error returned if Marshal is called with
+// a protocol buffer struct whose required fields have not
+// all been initialized. It is also the error returned if Unmarshal is
+// called with an encoded protocol buffer that does not include all the
+// required fields.
+//
+// When printed, RequiredNotSetError reports the first unset required field in a
+// message. If the field cannot be precisely determined, it is reported as
+// "{Unknown}".
+type RequiredNotSetError struct {
+ field string
+}
+
+func (e *RequiredNotSetError) Error() string {
+ return fmt.Sprintf("proto: required field %q not set", e.field)
+}
+
+var (
+ // errRepeatedHasNil is the error returned if Marshal is called with
+ // a struct with a repeated field containing a nil element.
+ errRepeatedHasNil = errors.New("proto: repeated field has nil element")
+
+ // errOneofHasNil is the error returned if Marshal is called with
+ // a struct with a oneof field containing a nil element.
+ errOneofHasNil = errors.New("proto: oneof field has nil value")
+
+ // ErrNil is the error returned if Marshal is called with nil.
+ ErrNil = errors.New("proto: Marshal called with nil")
+
+ // ErrTooLarge is the error returned if Marshal is called with a
+ // message that encodes to >2GB.
+ ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
+)
+
+// The fundamental encoders that put bytes on the wire.
+// Those that take integer types all accept uint64 and are
+// therefore of type valueEncoder.
+
+const maxVarintBytes = 10 // maximum length of a varint
+
+// maxMarshalSize is the largest allowed size of an encoded protobuf,
+// since C++ and Java use signed int32s for the size.
+const maxMarshalSize = 1<<31 - 1
+
+// EncodeVarint returns the varint encoding of x.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+// Not used by the package itself, but helpful to clients
+// wishing to use the same encoding.
+func EncodeVarint(x uint64) []byte {
+ var buf [maxVarintBytes]byte
+ var n int
+ for n = 0; x > 127; n++ {
+ buf[n] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ buf[n] = uint8(x)
+ n++
+ return buf[0:n]
+}
+
+// EncodeVarint writes a varint-encoded integer to the Buffer.
+// This is the format for the
+// int32, int64, uint32, uint64, bool, and enum
+// protocol buffer types.
+func (p *Buffer) EncodeVarint(x uint64) error {
+ for x >= 1<<7 {
+ p.buf = append(p.buf, uint8(x&0x7f|0x80))
+ x >>= 7
+ }
+ p.buf = append(p.buf, uint8(x))
+ return nil
+}
+
+// SizeVarint returns the varint encoding size of an integer.
+func SizeVarint(x uint64) int {
+ return sizeVarint(x)
+}
+
+func sizeVarint(x uint64) (n int) {
+ for {
+ n++
+ x >>= 7
+ if x == 0 {
+ break
+ }
+ }
+ return n
+}
+
+// EncodeFixed64 writes a 64-bit integer to the Buffer.
+// This is the format for the
+// fixed64, sfixed64, and double protocol buffer types.
+func (p *Buffer) EncodeFixed64(x uint64) error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24),
+ uint8(x>>32),
+ uint8(x>>40),
+ uint8(x>>48),
+ uint8(x>>56))
+ return nil
+}
+
+func sizeFixed64(x uint64) int {
+ return 8
+}
+
+// EncodeFixed32 writes a 32-bit integer to the Buffer.
+// This is the format for the
+// fixed32, sfixed32, and float protocol buffer types.
+func (p *Buffer) EncodeFixed32(x uint64) error {
+ p.buf = append(p.buf,
+ uint8(x),
+ uint8(x>>8),
+ uint8(x>>16),
+ uint8(x>>24))
+ return nil
+}
+
+func sizeFixed32(x uint64) int {
+ return 4
+}
+
+// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
+// to the Buffer.
+// This is the format used for the sint64 protocol buffer type.
+func (p *Buffer) EncodeZigzag64(x uint64) error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63)))
+}
+
+func sizeZigzag64(x uint64) int {
+ return sizeVarint((x << 1) ^ uint64((int64(x) >> 63)))
+}
+
+// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
+// to the Buffer.
+// This is the format used for the sint32 protocol buffer type.
+func (p *Buffer) EncodeZigzag32(x uint64) error {
+ // use signed number to get arithmetic right shift.
+ return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
+func sizeZigzag32(x uint64) int {
+ return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
+}
+
+// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
+// This is the format used for the bytes protocol buffer
+// type and for embedded messages.
+func (p *Buffer) EncodeRawBytes(b []byte) error {
+ p.EncodeVarint(uint64(len(b)))
+ p.buf = append(p.buf, b...)
+ return nil
+}
+
+func sizeRawBytes(b []byte) int {
+ return sizeVarint(uint64(len(b))) +
+ len(b)
+}
+
+// EncodeStringBytes writes an encoded string to the Buffer.
+// This is the format used for the proto2 string type.
+func (p *Buffer) EncodeStringBytes(s string) error {
+ p.EncodeVarint(uint64(len(s)))
+ p.buf = append(p.buf, s...)
+ return nil
+}
+
+func sizeStringBytes(s string) int {
+ return sizeVarint(uint64(len(s))) +
+ len(s)
+}
+
+// Marshaler is the interface representing objects that can marshal themselves.
+type Marshaler interface {
+ Marshal() ([]byte, error)
+}
+
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, returning the data.
+func Marshal(pb Message) ([]byte, error) {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ return m.Marshal()
+ }
+ p := NewBuffer(nil)
+ err := p.Marshal(pb)
+ if p.buf == nil && err == nil {
+ // Return a non-nil slice on success.
+ return []byte{}, nil
+ }
+ return p.buf, err
+}
+
+// EncodeMessage writes the protocol buffer to the Buffer,
+// prefixed by a varint-encoded length.
+func (p *Buffer) EncodeMessage(pb Message) error {
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return ErrNil
+ }
+ if err == nil {
+ var state errorState
+ err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
+ }
+ return err
+}
+
+// Marshal takes the protocol buffer
+// and encodes it into the wire format, writing the result to the
+// Buffer.
+func (p *Buffer) Marshal(pb Message) error {
+ // Can the object marshal itself?
+ if m, ok := pb.(Marshaler); ok {
+ data, err := m.Marshal()
+ p.buf = append(p.buf, data...)
+ return err
+ }
+
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return ErrNil
+ }
+ if err == nil {
+ err = p.enc_struct(GetProperties(t.Elem()), base)
+ }
+
+ if collectStats {
+ (stats).Encode++ // Parens are to work around a goimports bug.
+ }
+
+ if len(p.buf) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ return err
+}
+
+// Size returns the encoded size of a protocol buffer.
+func Size(pb Message) (n int) {
+ // Can the object marshal itself? If so, Size is slow.
+ // TODO: add Size to Marshaler, or add a Sizer interface.
+ if m, ok := pb.(Marshaler); ok {
+ b, _ := m.Marshal()
+ return len(b)
+ }
+
+ t, base, err := getbase(pb)
+ if structPointer_IsNil(base) {
+ return 0
+ }
+ if err == nil {
+ n = size_struct(GetProperties(t.Elem()), base)
+ }
+
+ if collectStats {
+ (stats).Size++ // Parens are to work around a goimports bug.
+ }
+
+ return
+}
+
+// Individual type encoders.
+
+// Encode a bool.
+func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
+ v := *structPointer_Bool(base, p.field)
+ if v == nil {
+ return ErrNil
+ }
+ x := 0
+ if *v {
+ x = 1
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
+ v := *structPointer_BoolVal(base, p.field)
+ if !v {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, 1)
+ return nil
+}
+
+func size_bool(p *Properties, base structPointer) int {
+ v := *structPointer_Bool(base, p.field)
+ if v == nil {
+ return 0
+ }
+ return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+func size_proto3_bool(p *Properties, base structPointer) int {
+ v := *structPointer_BoolVal(base, p.field)
+ if !v && !p.oneof {
+ return 0
+ }
+ return len(p.tagcode) + 1 // each bool takes exactly one byte
+}
+
+// Encode an int32.
+func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return ErrNil
+ }
+ x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_int32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return 0
+ }
+ x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+func size_proto3_int32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+// Encode a uint32.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return ErrNil
+ }
+ x := word32_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, uint64(x))
+ return nil
+}
+
+func size_uint32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32(base, p.field)
+ if word32_IsNil(v) {
+ return 0
+ }
+ x := word32_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+func size_proto3_uint32(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word32Val(base, p.field)
+ x := word32Val_Get(v)
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(uint64(x))
+ return
+}
+
+// Encode an int64.
+func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64(base, p.field)
+ if word64_IsNil(v) {
+ return ErrNil
+ }
+ x := word64_Get(v)
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, x)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ if x == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, x)
+ return nil
+}
+
+func size_int64(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word64(base, p.field)
+ if word64_IsNil(v) {
+ return 0
+ }
+ x := word64_Get(v)
+ n += len(p.tagcode)
+ n += p.valSize(x)
+ return
+}
+
+func size_proto3_int64(p *Properties, base structPointer) (n int) {
+ v := structPointer_Word64Val(base, p.field)
+ x := word64Val_Get(v)
+ if x == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += p.valSize(x)
+ return
+}
+
+// Encode a string.
+func (o *Buffer) enc_string(p *Properties, base structPointer) error {
+ v := *structPointer_String(base, p.field)
+ if v == nil {
+ return ErrNil
+ }
+ x := *v
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(x)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error {
+ v := *structPointer_StringVal(base, p.field)
+ if v == "" {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(v)
+ return nil
+}
+
+func size_string(p *Properties, base structPointer) (n int) {
+ v := *structPointer_String(base, p.field)
+ if v == nil {
+ return 0
+ }
+ x := *v
+ n += len(p.tagcode)
+ n += sizeStringBytes(x)
+ return
+}
+
+func size_proto3_string(p *Properties, base structPointer) (n int) {
+ v := *structPointer_StringVal(base, p.field)
+ if v == "" && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeStringBytes(v)
+ return
+}
+
+// All protocol buffer fields are nillable, but be careful.
+func isNil(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ return v.IsNil()
+ }
+ return false
+}
+
+// Encode a message struct.
+func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return ErrNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ return state.err
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ return o.enc_len_struct(p.sprop, structp, &state)
+}
+
+func size_struct_message(p *Properties, base structPointer) int {
+ structp := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(structp) {
+ return 0
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n0 := len(p.tagcode)
+ n1 := sizeRawBytes(data)
+ return n0 + n1
+ }
+
+ n0 := len(p.tagcode)
+ n1 := size_struct(p.sprop, structp)
+ n2 := sizeVarint(uint64(n1)) // size of encoded length
+ return n0 + n1 + n2
+}
+
+// Encode a group struct.
+func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error {
+ var state errorState
+ b := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(b) {
+ return ErrNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+ err := o.enc_struct(p.sprop, b)
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ return state.err
+}
+
+func size_struct_group(p *Properties, base structPointer) (n int) {
+ b := structPointer_GetStructPointer(base, p.field)
+ if structPointer_IsNil(b) {
+ return 0
+ }
+
+ n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup))
+ n += size_struct(p.sprop, b)
+ n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ return
+}
+
+// Encode a slice of bools ([]bool).
+func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ for _, x := range s {
+ o.buf = append(o.buf, p.tagcode...)
+ v := uint64(0)
+ if x {
+ v = 1
+ }
+ p.valEnc(o, v)
+ }
+ return nil
+}
+
+func size_slice_bool(p *Properties, base structPointer) int {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return 0
+ }
+ return l * (len(p.tagcode) + 1) // each bool takes exactly one byte
+}
+
+// Encode a slice of bools ([]bool) in packed format.
+func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
+ for _, x := range s {
+ v := uint64(0)
+ if x {
+ v = 1
+ }
+ p.valEnc(o, v)
+ }
+ return nil
+}
+
+func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
+ s := *structPointer_BoolSlice(base, p.field)
+ l := len(s)
+ if l == 0 {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(l))
+ n += l // each bool takes exactly one byte
+ return
+}
+
+// Encode a slice of bytes ([]byte).
+func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(s)
+ return nil
+}
+
+func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error {
+ s := *structPointer_Bytes(base, p.field)
+ if len(s) == 0 {
+ return ErrNil
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(s)
+ return nil
+}
+
+func size_slice_byte(p *Properties, base structPointer) (n int) {
+ s := *structPointer_Bytes(base, p.field)
+ if s == nil && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeRawBytes(s)
+ return
+}
+
+func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
+ s := *structPointer_Bytes(base, p.field)
+ if len(s) == 0 && !p.oneof {
+ return 0
+ }
+ n += len(p.tagcode)
+ n += sizeRawBytes(s)
+ return
+}
+
+// Encode a slice of int32s ([]int32).
+func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+func size_slice_int32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ n += p.valSize(uint64(x))
+ }
+ return
+}
+
+// Encode a slice of int32s ([]int32) in packed format.
+func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ p.valEnc(buf, uint64(x))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
+ bufSize += p.valSize(uint64(x))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of uint32s ([]uint32).
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ x := s.Index(i)
+ p.valEnc(o, uint64(x))
+ }
+ return nil
+}
+
+func size_slice_uint32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ x := s.Index(i)
+ n += p.valSize(uint64(x))
+ }
+ return
+}
+
+// Encode a slice of uint32s ([]uint32) in packed format.
+// Exactly the same as int32, except for no sign extension.
+func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, uint64(s.Index(i)))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word32Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ bufSize += p.valSize(uint64(s.Index(i)))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of int64s ([]int64).
+func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ p.valEnc(o, s.Index(i))
+ }
+ return nil
+}
+
+func size_slice_int64(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ for i := 0; i < l; i++ {
+ n += len(p.tagcode)
+ n += p.valSize(s.Index(i))
+ }
+ return
+}
+
+// Encode a slice of int64s ([]int64) in packed format.
+func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return ErrNil
+ }
+ // TODO: Reuse a Buffer.
+ buf := NewBuffer(nil)
+ for i := 0; i < l; i++ {
+ p.valEnc(buf, s.Index(i))
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeVarint(uint64(len(buf.buf)))
+ o.buf = append(o.buf, buf.buf...)
+ return nil
+}
+
+func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
+ s := structPointer_Word64Slice(base, p.field)
+ l := s.Len()
+ if l == 0 {
+ return 0
+ }
+ var bufSize int
+ for i := 0; i < l; i++ {
+ bufSize += p.valSize(s.Index(i))
+ }
+
+ n += len(p.tagcode)
+ n += sizeVarint(uint64(bufSize))
+ n += bufSize
+ return
+}
+
+// Encode a slice of slice of bytes ([][]byte).
+func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error {
+ ss := *structPointer_BytesSlice(base, p.field)
+ l := len(ss)
+ if l == 0 {
+ return ErrNil
+ }
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(ss[i])
+ }
+ return nil
+}
+
+func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
+ ss := *structPointer_BytesSlice(base, p.field)
+ l := len(ss)
+ if l == 0 {
+ return 0
+ }
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ n += sizeRawBytes(ss[i])
+ }
+ return
+}
+
+// Encode a slice of strings ([]string).
+func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error {
+ ss := *structPointer_StringSlice(base, p.field)
+ l := len(ss)
+ for i := 0; i < l; i++ {
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeStringBytes(ss[i])
+ }
+ return nil
+}
+
+func size_slice_string(p *Properties, base structPointer) (n int) {
+ ss := *structPointer_StringSlice(base, p.field)
+ l := len(ss)
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ n += sizeStringBytes(ss[i])
+ }
+ return
+}
+
+// Encode a slice of message structs ([]*struct).
+func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error {
+ var state errorState
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ for i := 0; i < l; i++ {
+ structp := s.Index(i)
+ if structPointer_IsNil(structp) {
+ return errRepeatedHasNil
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, err := m.Marshal()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ o.buf = append(o.buf, p.tagcode...)
+ o.EncodeRawBytes(data)
+ continue
+ }
+
+ o.buf = append(o.buf, p.tagcode...)
+ err := o.enc_len_struct(p.sprop, structp, &state)
+ if err != nil && !state.shouldContinue(err, nil) {
+ if err == ErrNil {
+ return errRepeatedHasNil
+ }
+ return err
+ }
+ }
+ return state.err
+}
+
+func size_slice_struct_message(p *Properties, base structPointer) (n int) {
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+ n += l * len(p.tagcode)
+ for i := 0; i < l; i++ {
+ structp := s.Index(i)
+ if structPointer_IsNil(structp) {
+ return // return the size up to this point
+ }
+
+ // Can the object marshal itself?
+ if p.isMarshaler {
+ m := structPointer_Interface(structp, p.stype).(Marshaler)
+ data, _ := m.Marshal()
+ n += sizeRawBytes(data)
+ continue
+ }
+
+ n0 := size_struct(p.sprop, structp)
+ n1 := sizeVarint(uint64(n0)) // size of encoded length
+ n += n0 + n1
+ }
+ return
+}
+
+// Encode a slice of group structs ([]*struct).
+func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error {
+ var state errorState
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ for i := 0; i < l; i++ {
+ b := s.Index(i)
+ if structPointer_IsNil(b) {
+ return errRepeatedHasNil
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
+
+ err := o.enc_struct(p.sprop, b)
+
+ if err != nil && !state.shouldContinue(err, nil) {
+ if err == ErrNil {
+ return errRepeatedHasNil
+ }
+ return err
+ }
+
+ o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
+ }
+ return state.err
+}
+
+func size_slice_struct_group(p *Properties, base structPointer) (n int) {
+ s := structPointer_StructPointerSlice(base, p.field)
+ l := s.Len()
+
+ n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup))
+ n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup))
+ for i := 0; i < l; i++ {
+ b := s.Index(i)
+ if structPointer_IsNil(b) {
+ return // return size up to this point
+ }
+
+ n += size_struct(p.sprop, b)
+ }
+ return
+}
+
+// Encode an extension map.
+func (o *Buffer) enc_map(p *Properties, base structPointer) error {
+ exts := structPointer_ExtMap(base, p.field)
+ if err := encodeExtensionsMap(*exts); err != nil {
+ return err
+ }
+
+ return o.enc_map_body(*exts)
+}
+
+func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
+ exts := structPointer_Extensions(base, p.field)
+
+ v, mu := exts.extensionsRead()
+ if v == nil {
+ return nil
+ }
+
+ mu.Lock()
+ defer mu.Unlock()
+ if err := encodeExtensionsMap(v); err != nil {
+ return err
+ }
+
+ return o.enc_map_body(v)
+}
+
+func (o *Buffer) enc_map_body(v map[int32]Extension) error {
+ // Fast-path for common cases: zero or one extensions.
+ if len(v) <= 1 {
+ for _, e := range v {
+ o.buf = append(o.buf, e.enc...)
+ }
+ return nil
+ }
+
+ // Sort keys to provide a deterministic encoding.
+ keys := make([]int, 0, len(v))
+ for k := range v {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+
+ for _, k := range keys {
+ o.buf = append(o.buf, v[int32(k)].enc...)
+ }
+ return nil
+}
+
+func size_map(p *Properties, base structPointer) int {
+ v := structPointer_ExtMap(base, p.field)
+ return extensionsMapSize(*v)
+}
+
+func size_exts(p *Properties, base structPointer) int {
+ v := structPointer_Extensions(base, p.field)
+ return extensionsSize(v)
+}
+
+// Encode a map field.
+func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
+ var state errorState // XXX: or do we need to plumb this through?
+
+ /*
+ A map defined as
+ map map_field = N;
+ is encoded in the same way as
+ message MapFieldEntry {
+ key_type key = 1;
+ value_type value = 2;
+ }
+ repeated MapFieldEntry map_field = N;
+ */
+
+ v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+ if v.Len() == 0 {
+ return nil
+ }
+
+ keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+ enc := func() error {
+ if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
+ return err
+ }
+ if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
+ return err
+ }
+ return nil
+ }
+
+ // Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
+ for _, key := range v.MapKeys() {
+ val := v.MapIndex(key)
+
+ keycopy.Set(key)
+ valcopy.Set(val)
+
+ o.buf = append(o.buf, p.tagcode...)
+ if err := o.enc_len_thing(enc, &state); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func size_new_map(p *Properties, base structPointer) int {
+ v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
+
+ keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
+
+ n := 0
+ for _, key := range v.MapKeys() {
+ val := v.MapIndex(key)
+ keycopy.Set(key)
+ valcopy.Set(val)
+
+ // Tag codes for key and val are the responsibility of the sub-sizer.
+ keysize := p.mkeyprop.size(p.mkeyprop, keybase)
+ valsize := p.mvalprop.size(p.mvalprop, valbase)
+ entry := keysize + valsize
+ // Add on tag code and length of map entry itself.
+ n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
+ }
+ return n
+}
+
+// mapEncodeScratch returns a new reflect.Value matching the map's value type,
+// and a structPointer suitable for passing to an encoder or sizer.
+func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
+ // Prepare addressable doubly-indirect placeholders for the key and value types.
+ // This is needed because the element-type encoders expect **T, but the map iteration produces T.
+
+ keycopy = reflect.New(mapType.Key()).Elem() // addressable K
+ keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
+ keyptr.Set(keycopy.Addr()) //
+ keybase = toStructPointer(keyptr.Addr()) // **K
+
+ // Value types are more varied and require special handling.
+ switch mapType.Elem().Kind() {
+ case reflect.Slice:
+ // []byte
+ var dummy []byte
+ valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
+ valbase = toStructPointer(valcopy.Addr())
+ case reflect.Ptr:
+ // message; the generated field type is map[K]*Msg (so V is *Msg),
+ // so we only need one level of indirection.
+ valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
+ valbase = toStructPointer(valcopy.Addr())
+ default:
+ // everything else
+ valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
+ valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
+ valptr.Set(valcopy.Addr()) //
+ valbase = toStructPointer(valptr.Addr()) // **V
+ }
+ return
+}
+
+// Encode a struct.
+func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
+ var state errorState
+ // Encode fields in tag order so that decoders may use optimizations
+ // that depend on the ordering.
+ // https://developers.google.com/protocol-buffers/docs/encoding#order
+ for _, i := range prop.order {
+ p := prop.Prop[i]
+ if p.enc != nil {
+ err := p.enc(o, p, base)
+ if err != nil {
+ if err == ErrNil {
+ if p.Required && state.err == nil {
+ state.err = &RequiredNotSetError{p.Name}
+ }
+ } else if err == errRepeatedHasNil {
+ // Give more context to nil values in repeated fields.
+ return errors.New("repeated field " + p.OrigName + " has nil element")
+ } else if !state.shouldContinue(err, p) {
+ return err
+ }
+ }
+ if len(o.buf) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ }
+ }
+
+ // Do oneof fields.
+ if prop.oneofMarshaler != nil {
+ m := structPointer_Interface(base, prop.stype).(Message)
+ if err := prop.oneofMarshaler(m, o); err == ErrNil {
+ return errOneofHasNil
+ } else if err != nil {
+ return err
+ }
+ }
+
+ // Add unrecognized fields at the end.
+ if prop.unrecField.IsValid() {
+ v := *structPointer_Bytes(base, prop.unrecField)
+ if len(o.buf)+len(v) > maxMarshalSize {
+ return ErrTooLarge
+ }
+ if len(v) > 0 {
+ o.buf = append(o.buf, v...)
+ }
+ }
+
+ return state.err
+}
+
+func size_struct(prop *StructProperties, base structPointer) (n int) {
+ for _, i := range prop.order {
+ p := prop.Prop[i]
+ if p.size != nil {
+ n += p.size(p, base)
+ }
+ }
+
+ // Add unrecognized fields at the end.
+ if prop.unrecField.IsValid() {
+ v := *structPointer_Bytes(base, prop.unrecField)
+ n += len(v)
+ }
+
+ // Factor in any oneof fields.
+ if prop.oneofSizer != nil {
+ m := structPointer_Interface(base, prop.stype).(Message)
+ n += prop.oneofSizer(m)
+ }
+
+ return
+}
+
+var zeroes [20]byte // longer than any conceivable sizeVarint
+
+// Encode a struct, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
+ return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state)
+}
+
+// Encode something, preceded by its encoded length (as a varint).
+func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
+ iLen := len(o.buf)
+ o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
+ iMsg := len(o.buf)
+ err := enc()
+ if err != nil && !state.shouldContinue(err, nil) {
+ return err
+ }
+ lMsg := len(o.buf) - iMsg
+ lLen := sizeVarint(uint64(lMsg))
+ switch x := lLen - (iMsg - iLen); {
+ case x > 0: // actual length is x bytes larger than the space we reserved
+ // Move msg x bytes right.
+ o.buf = append(o.buf, zeroes[:x]...)
+ copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+ case x < 0: // actual length is x bytes smaller than the space we reserved
+ // Move msg x bytes left.
+ copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
+ o.buf = o.buf[:len(o.buf)+x] // x is negative
+ }
+ // Encode the length in the reserved space.
+ o.buf = o.buf[:iLen]
+ o.EncodeVarint(uint64(lMsg))
+ o.buf = o.buf[:len(o.buf)+lMsg]
+ return state.err
+}
+
+// errorState maintains the first error that occurs and updates that error
+// with additional context.
+type errorState struct {
+ err error
+}
+
+// shouldContinue reports whether encoding should continue upon encountering the
+// given error. If the error is RequiredNotSetError, shouldContinue returns true
+// and, if this is the first appearance of that error, remembers it for future
+// reporting.
+//
+// If prop is not nil, it may update any error with additional context about the
+// field with the error.
+func (s *errorState) shouldContinue(err error, prop *Properties) bool {
+ // Ignore unset required fields.
+ reqNotSet, ok := err.(*RequiredNotSetError)
+ if !ok {
+ return false
+ }
+ if s.err == nil {
+ if prop != nil {
+ err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field}
+ }
+ s.err = err
+ }
+ return true
+}
diff --git a/vendor/github.com/golang/protobuf/proto/equal.go b/vendor/github.com/golang/protobuf/proto/equal.go
new file mode 100644
index 0000000..2ed1cf5
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/equal.go
@@ -0,0 +1,300 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2011 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Protocol buffer comparison.
+
+package proto
+
+import (
+ "bytes"
+ "log"
+ "reflect"
+ "strings"
+)
+
+/*
+Equal returns true iff protocol buffers a and b are equal.
+The arguments must both be pointers to protocol buffer structs.
+
+Equality is defined in this way:
+ - Two messages are equal iff they are the same type,
+ corresponding fields are equal, unknown field sets
+ are equal, and extensions sets are equal.
+ - Two set scalar fields are equal iff their values are equal.
+ If the fields are of a floating-point type, remember that
+ NaN != x for all x, including NaN. If the message is defined
+ in a proto3 .proto file, fields are not "set"; specifically,
+ zero length proto3 "bytes" fields are equal (nil == {}).
+ - Two repeated fields are equal iff their lengths are the same,
+ and their corresponding elements are equal. Note a "bytes" field,
+ although represented by []byte, is not a repeated field and the
+ rule for the scalar fields described above applies.
+ - Two unset fields are equal.
+ - Two unknown field sets are equal if their current
+ encoded state is equal.
+ - Two extension sets are equal iff they have corresponding
+ elements that are pairwise equal.
+ - Two map fields are equal iff their lengths are the same,
+ and they contain the same set of elements. Zero-length map
+ fields are equal.
+ - Every other combination of things are not equal.
+
+The return value is undefined if a and b are not protocol buffers.
+*/
+func Equal(a, b Message) bool {
+ if a == nil || b == nil {
+ return a == b
+ }
+ v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
+ if v1.Type() != v2.Type() {
+ return false
+ }
+ if v1.Kind() == reflect.Ptr {
+ if v1.IsNil() {
+ return v2.IsNil()
+ }
+ if v2.IsNil() {
+ return false
+ }
+ v1, v2 = v1.Elem(), v2.Elem()
+ }
+ if v1.Kind() != reflect.Struct {
+ return false
+ }
+ return equalStruct(v1, v2)
+}
+
+// v1 and v2 are known to have the same type.
+func equalStruct(v1, v2 reflect.Value) bool {
+ sprop := GetProperties(v1.Type())
+ for i := 0; i < v1.NumField(); i++ {
+ f := v1.Type().Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ f1, f2 := v1.Field(i), v2.Field(i)
+ if f.Type.Kind() == reflect.Ptr {
+ if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
+ // both unset
+ continue
+ } else if n1 != n2 {
+ // set/unset mismatch
+ return false
+ }
+ b1, ok := f1.Interface().(raw)
+ if ok {
+ b2 := f2.Interface().(raw)
+ // RawMessage
+ if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
+ return false
+ }
+ continue
+ }
+ f1, f2 = f1.Elem(), f2.Elem()
+ }
+ if !equalAny(f1, f2, sprop.Prop[i]) {
+ return false
+ }
+ }
+
+ if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
+ em2 := v2.FieldByName("XXX_InternalExtensions")
+ if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
+ return false
+ }
+ }
+
+ if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
+ em2 := v2.FieldByName("XXX_extensions")
+ if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
+ return false
+ }
+ }
+
+ uf := v1.FieldByName("XXX_unrecognized")
+ if !uf.IsValid() {
+ return true
+ }
+
+ u1 := uf.Bytes()
+ u2 := v2.FieldByName("XXX_unrecognized").Bytes()
+ if !bytes.Equal(u1, u2) {
+ return false
+ }
+
+ return true
+}
+
+// v1 and v2 are known to have the same type.
+// prop may be nil.
+func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
+ if v1.Type() == protoMessageType {
+ m1, _ := v1.Interface().(Message)
+ m2, _ := v2.Interface().(Message)
+ return Equal(m1, m2)
+ }
+ switch v1.Kind() {
+ case reflect.Bool:
+ return v1.Bool() == v2.Bool()
+ case reflect.Float32, reflect.Float64:
+ return v1.Float() == v2.Float()
+ case reflect.Int32, reflect.Int64:
+ return v1.Int() == v2.Int()
+ case reflect.Interface:
+ // Probably a oneof field; compare the inner values.
+ n1, n2 := v1.IsNil(), v2.IsNil()
+ if n1 || n2 {
+ return n1 == n2
+ }
+ e1, e2 := v1.Elem(), v2.Elem()
+ if e1.Type() != e2.Type() {
+ return false
+ }
+ return equalAny(e1, e2, nil)
+ case reflect.Map:
+ if v1.Len() != v2.Len() {
+ return false
+ }
+ for _, key := range v1.MapKeys() {
+ val2 := v2.MapIndex(key)
+ if !val2.IsValid() {
+ // This key was not found in the second map.
+ return false
+ }
+ if !equalAny(v1.MapIndex(key), val2, nil) {
+ return false
+ }
+ }
+ return true
+ case reflect.Ptr:
+ // Maps may have nil values in them, so check for nil.
+ if v1.IsNil() && v2.IsNil() {
+ return true
+ }
+ if v1.IsNil() != v2.IsNil() {
+ return false
+ }
+ return equalAny(v1.Elem(), v2.Elem(), prop)
+ case reflect.Slice:
+ if v1.Type().Elem().Kind() == reflect.Uint8 {
+ // short circuit: []byte
+
+ // Edge case: if this is in a proto3 message, a zero length
+ // bytes field is considered the zero value.
+ if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
+ return true
+ }
+ if v1.IsNil() != v2.IsNil() {
+ return false
+ }
+ return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
+ }
+
+ if v1.Len() != v2.Len() {
+ return false
+ }
+ for i := 0; i < v1.Len(); i++ {
+ if !equalAny(v1.Index(i), v2.Index(i), prop) {
+ return false
+ }
+ }
+ return true
+ case reflect.String:
+ return v1.Interface().(string) == v2.Interface().(string)
+ case reflect.Struct:
+ return equalStruct(v1, v2)
+ case reflect.Uint32, reflect.Uint64:
+ return v1.Uint() == v2.Uint()
+ }
+
+ // unknown type, so not a protocol buffer
+ log.Printf("proto: don't know how to compare %v", v1)
+ return false
+}
+
+// base is the struct type that the extensions are based on.
+// x1 and x2 are InternalExtensions.
+func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
+ em1, _ := x1.extensionsRead()
+ em2, _ := x2.extensionsRead()
+ return equalExtMap(base, em1, em2)
+}
+
+func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
+ if len(em1) != len(em2) {
+ return false
+ }
+
+ for extNum, e1 := range em1 {
+ e2, ok := em2[extNum]
+ if !ok {
+ return false
+ }
+
+ m1, m2 := e1.value, e2.value
+
+ if m1 != nil && m2 != nil {
+ // Both are unencoded.
+ if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
+ return false
+ }
+ continue
+ }
+
+ // At least one is encoded. To do a semantically correct comparison
+ // we need to unmarshal them first.
+ var desc *ExtensionDesc
+ if m := extensionMaps[base]; m != nil {
+ desc = m[extNum]
+ }
+ if desc == nil {
+ log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
+ continue
+ }
+ var err error
+ if m1 == nil {
+ m1, err = decodeExtension(e1.enc, desc)
+ }
+ if m2 == nil && err == nil {
+ m2, err = decodeExtension(e2.enc, desc)
+ }
+ if err != nil {
+ // The encoded form is invalid.
+ log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
+ return false
+ }
+ if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/vendor/github.com/golang/protobuf/proto/extensions.go b/vendor/github.com/golang/protobuf/proto/extensions.go
new file mode 100644
index 0000000..eaad218
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/extensions.go
@@ -0,0 +1,587 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Types and routines for supporting protocol buffer extensions.
+ */
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "sync"
+)
+
+// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
+var ErrMissingExtension = errors.New("proto: missing extension")
+
+// ExtensionRange represents a range of message extensions for a protocol buffer.
+// Used in code generated by the protocol compiler.
+type ExtensionRange struct {
+ Start, End int32 // both inclusive
+}
+
+// extendableProto is an interface implemented by any protocol buffer generated by the current
+// proto compiler that may be extended.
+type extendableProto interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+ extensionsWrite() map[int32]Extension
+ extensionsRead() (map[int32]Extension, sync.Locker)
+}
+
+// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
+// version of the proto compiler that may be extended.
+type extendableProtoV1 interface {
+ Message
+ ExtensionRangeArray() []ExtensionRange
+ ExtensionMap() map[int32]Extension
+}
+
+// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
+type extensionAdapter struct {
+ extendableProtoV1
+}
+
+func (e extensionAdapter) extensionsWrite() map[int32]Extension {
+ return e.ExtensionMap()
+}
+
+func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
+ return e.ExtensionMap(), notLocker{}
+}
+
+// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
+type notLocker struct{}
+
+func (n notLocker) Lock() {}
+func (n notLocker) Unlock() {}
+
+// extendable returns the extendableProto interface for the given generated proto message.
+// If the proto message has the old extension format, it returns a wrapper that implements
+// the extendableProto interface.
+func extendable(p interface{}) (extendableProto, bool) {
+ if ep, ok := p.(extendableProto); ok {
+ return ep, ok
+ }
+ if ep, ok := p.(extendableProtoV1); ok {
+ return extensionAdapter{ep}, ok
+ }
+ return nil, false
+}
+
+// XXX_InternalExtensions is an internal representation of proto extensions.
+//
+// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
+// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
+//
+// The methods of XXX_InternalExtensions are not concurrency safe in general,
+// but calls to logically read-only methods such as has and get may be executed concurrently.
+type XXX_InternalExtensions struct {
+ // The struct must be indirect so that if a user inadvertently copies a
+ // generated message and its embedded XXX_InternalExtensions, they
+ // avoid the mayhem of a copied mutex.
+ //
+ // The mutex serializes all logically read-only operations to p.extensionMap.
+ // It is up to the client to ensure that write operations to p.extensionMap are
+ // mutually exclusive with other accesses.
+ p *struct {
+ mu sync.Mutex
+ extensionMap map[int32]Extension
+ }
+}
+
+// extensionsWrite returns the extension map, creating it on first use.
+func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
+ if e.p == nil {
+ e.p = new(struct {
+ mu sync.Mutex
+ extensionMap map[int32]Extension
+ })
+ e.p.extensionMap = make(map[int32]Extension)
+ }
+ return e.p.extensionMap
+}
+
+// extensionsRead returns the extensions map for read-only use. It may be nil.
+// The caller must hold the returned mutex's lock when accessing Elements within the map.
+func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
+ if e.p == nil {
+ return nil, nil
+ }
+ return e.p.extensionMap, &e.p.mu
+}
+
+var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
+var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
+
+// ExtensionDesc represents an extension specification.
+// Used in generated code from the protocol compiler.
+type ExtensionDesc struct {
+ ExtendedType Message // nil pointer to the type that is being extended
+ ExtensionType interface{} // nil pointer to the extension type
+ Field int32 // field number
+ Name string // fully-qualified name of extension, for text formatting
+ Tag string // protobuf tag style
+ Filename string // name of the file in which the extension is defined
+}
+
+func (ed *ExtensionDesc) repeated() bool {
+ t := reflect.TypeOf(ed.ExtensionType)
+ return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
+}
+
+// Extension represents an extension in a message.
+type Extension struct {
+ // When an extension is stored in a message using SetExtension
+ // only desc and value are set. When the message is marshaled
+ // enc will be set to the encoded form of the message.
+ //
+ // When a message is unmarshaled and contains extensions, each
+ // extension will have only enc set. When such an extension is
+ // accessed using GetExtension (or GetExtensions) desc and value
+ // will be set.
+ desc *ExtensionDesc
+ value interface{}
+ enc []byte
+}
+
+// SetRawExtension is for testing only.
+func SetRawExtension(base Message, id int32, b []byte) {
+ epb, ok := extendable(base)
+ if !ok {
+ return
+ }
+ extmap := epb.extensionsWrite()
+ extmap[id] = Extension{enc: b}
+}
+
+// isExtensionField returns true iff the given field number is in an extension range.
+func isExtensionField(pb extendableProto, field int32) bool {
+ for _, er := range pb.ExtensionRangeArray() {
+ if er.Start <= field && field <= er.End {
+ return true
+ }
+ }
+ return false
+}
+
+// checkExtensionTypes checks that the given extension is valid for pb.
+func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
+ var pbi interface{} = pb
+ // Check the extended type.
+ if ea, ok := pbi.(extensionAdapter); ok {
+ pbi = ea.extendableProtoV1
+ }
+ if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
+ return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
+ }
+ // Check the range.
+ if !isExtensionField(pb, extension.Field) {
+ return errors.New("proto: bad extension number; not in declared ranges")
+ }
+ return nil
+}
+
+// extPropKey is sufficient to uniquely identify an extension.
+type extPropKey struct {
+ base reflect.Type
+ field int32
+}
+
+var extProp = struct {
+ sync.RWMutex
+ m map[extPropKey]*Properties
+}{
+ m: make(map[extPropKey]*Properties),
+}
+
+func extensionProperties(ed *ExtensionDesc) *Properties {
+ key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
+
+ extProp.RLock()
+ if prop, ok := extProp.m[key]; ok {
+ extProp.RUnlock()
+ return prop
+ }
+ extProp.RUnlock()
+
+ extProp.Lock()
+ defer extProp.Unlock()
+ // Check again.
+ if prop, ok := extProp.m[key]; ok {
+ return prop
+ }
+
+ prop := new(Properties)
+ prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
+ extProp.m[key] = prop
+ return prop
+}
+
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensions(e *XXX_InternalExtensions) error {
+ m, mu := e.extensionsRead()
+ if m == nil {
+ return nil // fast path
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ return encodeExtensionsMap(m)
+}
+
+// encode encodes any unmarshaled (unencoded) extensions in e.
+func encodeExtensionsMap(m map[int32]Extension) error {
+ for k, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := extensionProperties(e.desc)
+
+ p := NewBuffer(nil)
+ // If e.value has type T, the encoder expects a *struct{ X T }.
+ // Pass a *T with a zero field and hope it all works out.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ if err := props.enc(p, props, toStructPointer(x)); err != nil {
+ return err
+ }
+ e.enc = p.buf
+ m[k] = e
+ }
+ return nil
+}
+
+func extensionsSize(e *XXX_InternalExtensions) (n int) {
+ m, mu := e.extensionsRead()
+ if m == nil {
+ return 0
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ return extensionsMapSize(m)
+}
+
+func extensionsMapSize(m map[int32]Extension) (n int) {
+ for _, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ n += len(e.enc)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ et := reflect.TypeOf(e.desc.ExtensionType)
+ props := extensionProperties(e.desc)
+
+ // If e.value has type T, the encoder expects a *struct{ X T }.
+ // Pass a *T with a zero field and hope it all works out.
+ x := reflect.New(et)
+ x.Elem().Set(reflect.ValueOf(e.value))
+ n += props.size(props, toStructPointer(x))
+ }
+ return
+}
+
+// HasExtension returns whether the given extension is present in pb.
+func HasExtension(pb Message, extension *ExtensionDesc) bool {
+ // TODO: Check types, field numbers, etc.?
+ epb, ok := extendable(pb)
+ if !ok {
+ return false
+ }
+ extmap, mu := epb.extensionsRead()
+ if extmap == nil {
+ return false
+ }
+ mu.Lock()
+ _, ok = extmap[extension.Field]
+ mu.Unlock()
+ return ok
+}
+
+// ClearExtension removes the given extension from pb.
+func ClearExtension(pb Message, extension *ExtensionDesc) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return
+ }
+ // TODO: Check types, field numbers, etc.?
+ extmap := epb.extensionsWrite()
+ delete(extmap, extension.Field)
+}
+
+// GetExtension parses and returns the given extension of pb.
+// If the extension is not present and has no default value it returns ErrMissingExtension.
+func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, errors.New("proto: not an extendable proto")
+ }
+
+ if err := checkExtensionTypes(epb, extension); err != nil {
+ return nil, err
+ }
+
+ emap, mu := epb.extensionsRead()
+ if emap == nil {
+ return defaultExtensionValue(extension)
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ e, ok := emap[extension.Field]
+ if !ok {
+ // defaultExtensionValue returns the default value or
+ // ErrMissingExtension if there is no default.
+ return defaultExtensionValue(extension)
+ }
+
+ if e.value != nil {
+ // Already decoded. Check the descriptor, though.
+ if e.desc != extension {
+ // This shouldn't happen. If it does, it means that
+ // GetExtension was called twice with two different
+ // descriptors with the same field number.
+ return nil, errors.New("proto: descriptor conflict")
+ }
+ return e.value, nil
+ }
+
+ v, err := decodeExtension(e.enc, extension)
+ if err != nil {
+ return nil, err
+ }
+
+ // Remember the decoded version and drop the encoded version.
+ // That way it is safe to mutate what we return.
+ e.value = v
+ e.desc = extension
+ e.enc = nil
+ emap[extension.Field] = e
+ return e.value, nil
+}
+
+// defaultExtensionValue returns the default value for extension.
+// If no default for an extension is defined ErrMissingExtension is returned.
+func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
+ t := reflect.TypeOf(extension.ExtensionType)
+ props := extensionProperties(extension)
+
+ sf, _, err := fieldDefault(t, props)
+ if err != nil {
+ return nil, err
+ }
+
+ if sf == nil || sf.value == nil {
+ // There is no default value.
+ return nil, ErrMissingExtension
+ }
+
+ if t.Kind() != reflect.Ptr {
+ // We do not need to return a Ptr, we can directly return sf.value.
+ return sf.value, nil
+ }
+
+ // We need to return an interface{} that is a pointer to sf.value.
+ value := reflect.New(t).Elem()
+ value.Set(reflect.New(value.Type().Elem()))
+ if sf.kind == reflect.Int32 {
+ // We may have an int32 or an enum, but the underlying data is int32.
+ // Since we can't set an int32 into a non int32 reflect.value directly
+ // set it as a int32.
+ value.Elem().SetInt(int64(sf.value.(int32)))
+ } else {
+ value.Elem().Set(reflect.ValueOf(sf.value))
+ }
+ return value.Interface(), nil
+}
+
+// decodeExtension decodes an extension encoded in b.
+func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
+ o := NewBuffer(b)
+
+ t := reflect.TypeOf(extension.ExtensionType)
+
+ props := extensionProperties(extension)
+
+ // t is a pointer to a struct, pointer to basic type or a slice.
+ // Allocate a "field" to store the pointer/slice itself; the
+ // pointer/slice will be stored here. We pass
+ // the address of this field to props.dec.
+ // This passes a zero field and a *t and lets props.dec
+ // interpret it as a *struct{ x t }.
+ value := reflect.New(t).Elem()
+
+ for {
+ // Discard wire type and field number varint. It isn't needed.
+ if _, err := o.DecodeVarint(); err != nil {
+ return nil, err
+ }
+
+ if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
+ return nil, err
+ }
+
+ if o.index >= len(o.buf) {
+ break
+ }
+ }
+ return value.Interface(), nil
+}
+
+// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
+// The returned slice has the same length as es; missing extensions will appear as nil elements.
+func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, errors.New("proto: not an extendable proto")
+ }
+ extensions = make([]interface{}, len(es))
+ for i, e := range es {
+ extensions[i], err = GetExtension(epb, e)
+ if err == ErrMissingExtension {
+ err = nil
+ }
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
+// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
+// just the Field field, which defines the extension's field number.
+func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
+ }
+ registeredExtensions := RegisteredExtensions(pb)
+
+ emap, mu := epb.extensionsRead()
+ if emap == nil {
+ return nil, nil
+ }
+ mu.Lock()
+ defer mu.Unlock()
+ extensions := make([]*ExtensionDesc, 0, len(emap))
+ for extid, e := range emap {
+ desc := e.desc
+ if desc == nil {
+ desc = registeredExtensions[extid]
+ if desc == nil {
+ desc = &ExtensionDesc{Field: extid}
+ }
+ }
+
+ extensions = append(extensions, desc)
+ }
+ return extensions, nil
+}
+
+// SetExtension sets the specified extension of pb to the specified value.
+func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
+ epb, ok := extendable(pb)
+ if !ok {
+ return errors.New("proto: not an extendable proto")
+ }
+ if err := checkExtensionTypes(epb, extension); err != nil {
+ return err
+ }
+ typ := reflect.TypeOf(extension.ExtensionType)
+ if typ != reflect.TypeOf(value) {
+ return errors.New("proto: bad extension value type")
+ }
+ // nil extension values need to be caught early, because the
+ // encoder can't distinguish an ErrNil due to a nil extension
+ // from an ErrNil due to a missing field. Extensions are
+ // always optional, so the encoder would just swallow the error
+ // and drop all the extensions from the encoded message.
+ if reflect.ValueOf(value).IsNil() {
+ return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
+ }
+
+ extmap := epb.extensionsWrite()
+ extmap[extension.Field] = Extension{desc: extension, value: value}
+ return nil
+}
+
+// ClearAllExtensions clears all extensions from pb.
+func ClearAllExtensions(pb Message) {
+ epb, ok := extendable(pb)
+ if !ok {
+ return
+ }
+ m := epb.extensionsWrite()
+ for k := range m {
+ delete(m, k)
+ }
+}
+
+// A global registry of extensions.
+// The generated code will register the generated descriptors by calling RegisterExtension.
+
+var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
+
+// RegisterExtension is called from the generated code.
+func RegisterExtension(desc *ExtensionDesc) {
+ st := reflect.TypeOf(desc.ExtendedType).Elem()
+ m := extensionMaps[st]
+ if m == nil {
+ m = make(map[int32]*ExtensionDesc)
+ extensionMaps[st] = m
+ }
+ if _, ok := m[desc.Field]; ok {
+ panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
+ }
+ m[desc.Field] = desc
+}
+
+// RegisteredExtensions returns a map of the registered extensions of a
+// protocol buffer struct, indexed by the extension number.
+// The argument pb should be a nil pointer to the struct type.
+func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
+ return extensionMaps[reflect.TypeOf(pb).Elem()]
+}
diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go
new file mode 100644
index 0000000..1c22550
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/lib.go
@@ -0,0 +1,897 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package proto converts data structures to and from the wire format of
+protocol buffers. It works in concert with the Go source code generated
+for .proto files by the protocol compiler.
+
+A summary of the properties of the protocol buffer interface
+for a protocol buffer variable v:
+
+ - Names are turned from camel_case to CamelCase for export.
+ - There are no methods on v to set fields; just treat
+ them as structure fields.
+ - There are getters that return a field's value if set,
+ and return the field's default value if unset.
+ The getters work even if the receiver is a nil message.
+ - The zero value for a struct is its correct initialization state.
+ All desired fields must be set before marshaling.
+ - A Reset() method will restore a protobuf struct to its zero state.
+ - Non-repeated fields are pointers to the values; nil means unset.
+ That is, optional or required field int32 f becomes F *int32.
+ - Repeated fields are slices.
+ - Helper functions are available to aid the setting of fields.
+ msg.Foo = proto.String("hello") // set field
+ - Constants are defined to hold the default values of all fields that
+ have them. They have the form Default_StructName_FieldName.
+ Because the getter methods handle defaulted values,
+ direct use of these constants should be rare.
+ - Enums are given type names and maps from names to values.
+ Enum values are prefixed by the enclosing message's name, or by the
+ enum's type name if it is a top-level enum. Enum types have a String
+ method, and a Enum method to assist in message construction.
+ - Nested messages, groups and enums have type names prefixed with the name of
+ the surrounding message type.
+ - Extensions are given descriptor names that start with E_,
+ followed by an underscore-delimited list of the nested messages
+ that contain it (if any) followed by the CamelCased name of the
+ extension field itself. HasExtension, ClearExtension, GetExtension
+ and SetExtension are functions for manipulating extensions.
+ - Oneof field sets are given a single field in their message,
+ with distinguished wrapper types for each possible field value.
+ - Marshal and Unmarshal are functions to encode and decode the wire format.
+
+When the .proto file specifies `syntax="proto3"`, there are some differences:
+
+ - Non-repeated fields of non-message type are values instead of pointers.
+ - Enum types do not get an Enum method.
+
+The simplest way to describe this is to see an example.
+Given file test.proto, containing
+
+ package example;
+
+ enum FOO { X = 17; }
+
+ message Test {
+ required string label = 1;
+ optional int32 type = 2 [default=77];
+ repeated int64 reps = 3;
+ optional group OptionalGroup = 4 {
+ required string RequiredField = 5;
+ }
+ oneof union {
+ int32 number = 6;
+ string name = 7;
+ }
+ }
+
+The resulting file, test.pb.go, is:
+
+ package example
+
+ import proto "github.com/golang/protobuf/proto"
+ import math "math"
+
+ type FOO int32
+ const (
+ FOO_X FOO = 17
+ )
+ var FOO_name = map[int32]string{
+ 17: "X",
+ }
+ var FOO_value = map[string]int32{
+ "X": 17,
+ }
+
+ func (x FOO) Enum() *FOO {
+ p := new(FOO)
+ *p = x
+ return p
+ }
+ func (x FOO) String() string {
+ return proto.EnumName(FOO_name, int32(x))
+ }
+ func (x *FOO) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FOO_value, data)
+ if err != nil {
+ return err
+ }
+ *x = FOO(value)
+ return nil
+ }
+
+ type Test struct {
+ Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
+ Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
+ Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
+ Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
+ // Types that are valid to be assigned to Union:
+ // *Test_Number
+ // *Test_Name
+ Union isTest_Union `protobuf_oneof:"union"`
+ XXX_unrecognized []byte `json:"-"`
+ }
+ func (m *Test) Reset() { *m = Test{} }
+ func (m *Test) String() string { return proto.CompactTextString(m) }
+ func (*Test) ProtoMessage() {}
+
+ type isTest_Union interface {
+ isTest_Union()
+ }
+
+ type Test_Number struct {
+ Number int32 `protobuf:"varint,6,opt,name=number"`
+ }
+ type Test_Name struct {
+ Name string `protobuf:"bytes,7,opt,name=name"`
+ }
+
+ func (*Test_Number) isTest_Union() {}
+ func (*Test_Name) isTest_Union() {}
+
+ func (m *Test) GetUnion() isTest_Union {
+ if m != nil {
+ return m.Union
+ }
+ return nil
+ }
+ const Default_Test_Type int32 = 77
+
+ func (m *Test) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+ }
+
+ func (m *Test) GetType() int32 {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return Default_Test_Type
+ }
+
+ func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
+ if m != nil {
+ return m.Optionalgroup
+ }
+ return nil
+ }
+
+ type Test_OptionalGroup struct {
+ RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
+ }
+ func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
+ func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
+
+ func (m *Test_OptionalGroup) GetRequiredField() string {
+ if m != nil && m.RequiredField != nil {
+ return *m.RequiredField
+ }
+ return ""
+ }
+
+ func (m *Test) GetNumber() int32 {
+ if x, ok := m.GetUnion().(*Test_Number); ok {
+ return x.Number
+ }
+ return 0
+ }
+
+ func (m *Test) GetName() string {
+ if x, ok := m.GetUnion().(*Test_Name); ok {
+ return x.Name
+ }
+ return ""
+ }
+
+ func init() {
+ proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
+ }
+
+To create and play with a Test object:
+
+ package main
+
+ import (
+ "log"
+
+ "github.com/golang/protobuf/proto"
+ pb "./example.pb"
+ )
+
+ func main() {
+ test := &pb.Test{
+ Label: proto.String("hello"),
+ Type: proto.Int32(17),
+ Reps: []int64{1, 2, 3},
+ Optionalgroup: &pb.Test_OptionalGroup{
+ RequiredField: proto.String("good bye"),
+ },
+ Union: &pb.Test_Name{"fred"},
+ }
+ data, err := proto.Marshal(test)
+ if err != nil {
+ log.Fatal("marshaling error: ", err)
+ }
+ newTest := &pb.Test{}
+ err = proto.Unmarshal(data, newTest)
+ if err != nil {
+ log.Fatal("unmarshaling error: ", err)
+ }
+ // Now test and newTest contain the same data.
+ if test.GetLabel() != newTest.GetLabel() {
+ log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
+ }
+ // Use a type switch to determine which oneof was set.
+ switch u := test.Union.(type) {
+ case *pb.Test_Number: // u.Number contains the number.
+ case *pb.Test_Name: // u.Name contains the string.
+ }
+ // etc.
+ }
+*/
+package proto
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "reflect"
+ "sort"
+ "strconv"
+ "sync"
+)
+
+// Message is implemented by generated protocol buffer messages.
+type Message interface {
+ Reset()
+ String() string
+ ProtoMessage()
+}
+
+// Stats records allocation details about the protocol buffer encoders
+// and decoders. Useful for tuning the library itself.
+type Stats struct {
+ Emalloc uint64 // mallocs in encode
+ Dmalloc uint64 // mallocs in decode
+ Encode uint64 // number of encodes
+ Decode uint64 // number of decodes
+ Chit uint64 // number of cache hits
+ Cmiss uint64 // number of cache misses
+ Size uint64 // number of sizes
+}
+
+// Set to true to enable stats collection.
+const collectStats = false
+
+var stats Stats
+
+// GetStats returns a copy of the global Stats structure.
+func GetStats() Stats { return stats }
+
+// A Buffer is a buffer manager for marshaling and unmarshaling
+// protocol buffers. It may be reused between invocations to
+// reduce memory usage. It is not necessary to use a Buffer;
+// the global functions Marshal and Unmarshal create a
+// temporary Buffer and are fine for most applications.
+type Buffer struct {
+ buf []byte // encode/decode byte stream
+ index int // read point
+
+ // pools of basic types to amortize allocation.
+ bools []bool
+ uint32s []uint32
+ uint64s []uint64
+
+ // extra pools, only used with pointer_reflect.go
+ int32s []int32
+ int64s []int64
+ float32s []float32
+ float64s []float64
+}
+
+// NewBuffer allocates a new Buffer and initializes its internal data to
+// the contents of the argument slice.
+func NewBuffer(e []byte) *Buffer {
+ return &Buffer{buf: e}
+}
+
+// Reset resets the Buffer, ready for marshaling a new protocol buffer.
+func (p *Buffer) Reset() {
+ p.buf = p.buf[0:0] // for reading/writing
+ p.index = 0 // for reading
+}
+
+// SetBuf replaces the internal buffer with the slice,
+// ready for unmarshaling the contents of the slice.
+func (p *Buffer) SetBuf(s []byte) {
+ p.buf = s
+ p.index = 0
+}
+
+// Bytes returns the contents of the Buffer.
+func (p *Buffer) Bytes() []byte { return p.buf }
+
+/*
+ * Helper routines for simplifying the creation of optional fields of basic type.
+ */
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool {
+ return &v
+}
+
+// Int32 is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it.
+func Int32(v int32) *int32 {
+ return &v
+}
+
+// Int is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it, but unlike Int32
+// its argument value is an int.
+func Int(v int) *int32 {
+ p := new(int32)
+ *p = int32(v)
+ return p
+}
+
+// Int64 is a helper routine that allocates a new int64 value
+// to store v and returns a pointer to it.
+func Int64(v int64) *int64 {
+ return &v
+}
+
+// Float32 is a helper routine that allocates a new float32 value
+// to store v and returns a pointer to it.
+func Float32(v float32) *float32 {
+ return &v
+}
+
+// Float64 is a helper routine that allocates a new float64 value
+// to store v and returns a pointer to it.
+func Float64(v float64) *float64 {
+ return &v
+}
+
+// Uint32 is a helper routine that allocates a new uint32 value
+// to store v and returns a pointer to it.
+func Uint32(v uint32) *uint32 {
+ return &v
+}
+
+// Uint64 is a helper routine that allocates a new uint64 value
+// to store v and returns a pointer to it.
+func Uint64(v uint64) *uint64 {
+ return &v
+}
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string {
+ return &v
+}
+
+// EnumName is a helper function to simplify printing protocol buffer enums
+// by name. Given an enum map and a value, it returns a useful string.
+func EnumName(m map[int32]string, v int32) string {
+ s, ok := m[v]
+ if ok {
+ return s
+ }
+ return strconv.Itoa(int(v))
+}
+
+// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
+// from their JSON-encoded representation. Given a map from the enum's symbolic
+// names to its int values, and a byte buffer containing the JSON-encoded
+// value, it returns an int32 that can be cast to the enum type by the caller.
+//
+// The function can deal with both JSON representations, numeric and symbolic.
+func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
+ if data[0] == '"' {
+ // New style: enums are strings.
+ var repr string
+ if err := json.Unmarshal(data, &repr); err != nil {
+ return -1, err
+ }
+ val, ok := m[repr]
+ if !ok {
+ return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
+ }
+ return val, nil
+ }
+ // Old style: enums are ints.
+ var val int32
+ if err := json.Unmarshal(data, &val); err != nil {
+ return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
+ }
+ return val, nil
+}
+
+// DebugPrint dumps the encoded data in b in a debugging format with a header
+// including the string s. Used in testing but made available for general debugging.
+func (p *Buffer) DebugPrint(s string, b []byte) {
+ var u uint64
+
+ obuf := p.buf
+ index := p.index
+ p.buf = b
+ p.index = 0
+ depth := 0
+
+ fmt.Printf("\n--- %s ---\n", s)
+
+out:
+ for {
+ for i := 0; i < depth; i++ {
+ fmt.Print(" ")
+ }
+
+ index := p.index
+ if index == len(p.buf) {
+ break
+ }
+
+ op, err := p.DecodeVarint()
+ if err != nil {
+ fmt.Printf("%3d: fetching op err %v\n", index, err)
+ break out
+ }
+ tag := op >> 3
+ wire := op & 7
+
+ switch wire {
+ default:
+ fmt.Printf("%3d: t=%3d unknown wire=%d\n",
+ index, tag, wire)
+ break out
+
+ case WireBytes:
+ var r []byte
+
+ r, err = p.DecodeRawBytes(false)
+ if err != nil {
+ break out
+ }
+ fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
+ if len(r) <= 6 {
+ for i := 0; i < len(r); i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ } else {
+ for i := 0; i < 3; i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ fmt.Printf(" ..")
+ for i := len(r) - 3; i < len(r); i++ {
+ fmt.Printf(" %.2x", r[i])
+ }
+ }
+ fmt.Printf("\n")
+
+ case WireFixed32:
+ u, err = p.DecodeFixed32()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
+
+ case WireFixed64:
+ u, err = p.DecodeFixed64()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
+
+ case WireVarint:
+ u, err = p.DecodeVarint()
+ if err != nil {
+ fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
+ break out
+ }
+ fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
+
+ case WireStartGroup:
+ fmt.Printf("%3d: t=%3d start\n", index, tag)
+ depth++
+
+ case WireEndGroup:
+ depth--
+ fmt.Printf("%3d: t=%3d end\n", index, tag)
+ }
+ }
+
+ if depth != 0 {
+ fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
+ }
+ fmt.Printf("\n")
+
+ p.buf = obuf
+ p.index = index
+}
+
+// SetDefaults sets unset protocol buffer fields to their default values.
+// It only modifies fields that are both unset and have defined defaults.
+// It recursively sets default values in any non-nil sub-messages.
+func SetDefaults(pb Message) {
+ setDefaults(reflect.ValueOf(pb), true, false)
+}
+
+// v is a pointer to a struct.
+func setDefaults(v reflect.Value, recur, zeros bool) {
+ v = v.Elem()
+
+ defaultMu.RLock()
+ dm, ok := defaults[v.Type()]
+ defaultMu.RUnlock()
+ if !ok {
+ dm = buildDefaultMessage(v.Type())
+ defaultMu.Lock()
+ defaults[v.Type()] = dm
+ defaultMu.Unlock()
+ }
+
+ for _, sf := range dm.scalars {
+ f := v.Field(sf.index)
+ if !f.IsNil() {
+ // field already set
+ continue
+ }
+ dv := sf.value
+ if dv == nil && !zeros {
+ // no explicit default, and don't want to set zeros
+ continue
+ }
+ fptr := f.Addr().Interface() // **T
+ // TODO: Consider batching the allocations we do here.
+ switch sf.kind {
+ case reflect.Bool:
+ b := new(bool)
+ if dv != nil {
+ *b = dv.(bool)
+ }
+ *(fptr.(**bool)) = b
+ case reflect.Float32:
+ f := new(float32)
+ if dv != nil {
+ *f = dv.(float32)
+ }
+ *(fptr.(**float32)) = f
+ case reflect.Float64:
+ f := new(float64)
+ if dv != nil {
+ *f = dv.(float64)
+ }
+ *(fptr.(**float64)) = f
+ case reflect.Int32:
+ // might be an enum
+ if ft := f.Type(); ft != int32PtrType {
+ // enum
+ f.Set(reflect.New(ft.Elem()))
+ if dv != nil {
+ f.Elem().SetInt(int64(dv.(int32)))
+ }
+ } else {
+ // int32 field
+ i := new(int32)
+ if dv != nil {
+ *i = dv.(int32)
+ }
+ *(fptr.(**int32)) = i
+ }
+ case reflect.Int64:
+ i := new(int64)
+ if dv != nil {
+ *i = dv.(int64)
+ }
+ *(fptr.(**int64)) = i
+ case reflect.String:
+ s := new(string)
+ if dv != nil {
+ *s = dv.(string)
+ }
+ *(fptr.(**string)) = s
+ case reflect.Uint8:
+ // exceptional case: []byte
+ var b []byte
+ if dv != nil {
+ db := dv.([]byte)
+ b = make([]byte, len(db))
+ copy(b, db)
+ } else {
+ b = []byte{}
+ }
+ *(fptr.(*[]byte)) = b
+ case reflect.Uint32:
+ u := new(uint32)
+ if dv != nil {
+ *u = dv.(uint32)
+ }
+ *(fptr.(**uint32)) = u
+ case reflect.Uint64:
+ u := new(uint64)
+ if dv != nil {
+ *u = dv.(uint64)
+ }
+ *(fptr.(**uint64)) = u
+ default:
+ log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
+ }
+ }
+
+ for _, ni := range dm.nested {
+ f := v.Field(ni)
+ // f is *T or []*T or map[T]*T
+ switch f.Kind() {
+ case reflect.Ptr:
+ if f.IsNil() {
+ continue
+ }
+ setDefaults(f, recur, zeros)
+
+ case reflect.Slice:
+ for i := 0; i < f.Len(); i++ {
+ e := f.Index(i)
+ if e.IsNil() {
+ continue
+ }
+ setDefaults(e, recur, zeros)
+ }
+
+ case reflect.Map:
+ for _, k := range f.MapKeys() {
+ e := f.MapIndex(k)
+ if e.IsNil() {
+ continue
+ }
+ setDefaults(e, recur, zeros)
+ }
+ }
+ }
+}
+
+var (
+ // defaults maps a protocol buffer struct type to a slice of the fields,
+ // with its scalar fields set to their proto-declared non-zero default values.
+ defaultMu sync.RWMutex
+ defaults = make(map[reflect.Type]defaultMessage)
+
+ int32PtrType = reflect.TypeOf((*int32)(nil))
+)
+
+// defaultMessage represents information about the default values of a message.
+type defaultMessage struct {
+ scalars []scalarField
+ nested []int // struct field index of nested messages
+}
+
+type scalarField struct {
+ index int // struct field index
+ kind reflect.Kind // element type (the T in *T or []T)
+ value interface{} // the proto-declared default value, or nil
+}
+
+// t is a struct type.
+func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
+ sprop := GetProperties(t)
+ for _, prop := range sprop.Prop {
+ fi, ok := sprop.decoderTags.get(prop.Tag)
+ if !ok {
+ // XXX_unrecognized
+ continue
+ }
+ ft := t.Field(fi).Type
+
+ sf, nested, err := fieldDefault(ft, prop)
+ switch {
+ case err != nil:
+ log.Print(err)
+ case nested:
+ dm.nested = append(dm.nested, fi)
+ case sf != nil:
+ sf.index = fi
+ dm.scalars = append(dm.scalars, *sf)
+ }
+ }
+
+ return dm
+}
+
+// fieldDefault returns the scalarField for field type ft.
+// sf will be nil if the field can not have a default.
+// nestedMessage will be true if this is a nested message.
+// Note that sf.index is not set on return.
+func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
+ var canHaveDefault bool
+ switch ft.Kind() {
+ case reflect.Ptr:
+ if ft.Elem().Kind() == reflect.Struct {
+ nestedMessage = true
+ } else {
+ canHaveDefault = true // proto2 scalar field
+ }
+
+ case reflect.Slice:
+ switch ft.Elem().Kind() {
+ case reflect.Ptr:
+ nestedMessage = true // repeated message
+ case reflect.Uint8:
+ canHaveDefault = true // bytes field
+ }
+
+ case reflect.Map:
+ if ft.Elem().Kind() == reflect.Ptr {
+ nestedMessage = true // map with message values
+ }
+ }
+
+ if !canHaveDefault {
+ if nestedMessage {
+ return nil, true, nil
+ }
+ return nil, false, nil
+ }
+
+ // We now know that ft is a pointer or slice.
+ sf = &scalarField{kind: ft.Elem().Kind()}
+
+ // scalar fields without defaults
+ if !prop.HasDefault {
+ return sf, false, nil
+ }
+
+ // a scalar field: either *T or []byte
+ switch ft.Elem().Kind() {
+ case reflect.Bool:
+ x, err := strconv.ParseBool(prop.Default)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.Float32:
+ x, err := strconv.ParseFloat(prop.Default, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
+ }
+ sf.value = float32(x)
+ case reflect.Float64:
+ x, err := strconv.ParseFloat(prop.Default, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.Int32:
+ x, err := strconv.ParseInt(prop.Default, 10, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
+ }
+ sf.value = int32(x)
+ case reflect.Int64:
+ x, err := strconv.ParseInt(prop.Default, 10, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ case reflect.String:
+ sf.value = prop.Default
+ case reflect.Uint8:
+ // []byte (not *uint8)
+ sf.value = []byte(prop.Default)
+ case reflect.Uint32:
+ x, err := strconv.ParseUint(prop.Default, 10, 32)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
+ }
+ sf.value = uint32(x)
+ case reflect.Uint64:
+ x, err := strconv.ParseUint(prop.Default, 10, 64)
+ if err != nil {
+ return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
+ }
+ sf.value = x
+ default:
+ return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
+ }
+
+ return sf, false, nil
+}
+
+// Map fields may have key types of non-float scalars, strings and enums.
+// The easiest way to sort them in some deterministic order is to use fmt.
+// If this turns out to be inefficient we can always consider other options,
+// such as doing a Schwartzian transform.
+
+func mapKeys(vs []reflect.Value) sort.Interface {
+ s := mapKeySorter{
+ vs: vs,
+ // default Less function: textual comparison
+ less: func(a, b reflect.Value) bool {
+ return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
+ },
+ }
+
+ // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
+ // numeric keys are sorted numerically.
+ if len(vs) == 0 {
+ return s
+ }
+ switch vs[0].Kind() {
+ case reflect.Int32, reflect.Int64:
+ s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
+ case reflect.Uint32, reflect.Uint64:
+ s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
+ }
+
+ return s
+}
+
+type mapKeySorter struct {
+ vs []reflect.Value
+ less func(a, b reflect.Value) bool
+}
+
+func (s mapKeySorter) Len() int { return len(s.vs) }
+func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
+func (s mapKeySorter) Less(i, j int) bool {
+ return s.less(s.vs[i], s.vs[j])
+}
+
+// isProto3Zero reports whether v is a zero proto3 value.
+func isProto3Zero(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint32, reflect.Uint64:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.String:
+ return v.String() == ""
+ }
+ return false
+}
+
+// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
+// to assert that that code is compatible with this version of the proto package.
+const ProtoPackageIsVersion2 = true
+
+// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
+// to assert that that code is compatible with this version of the proto package.
+const ProtoPackageIsVersion1 = true
diff --git a/vendor/github.com/golang/protobuf/proto/message_set.go b/vendor/github.com/golang/protobuf/proto/message_set.go
new file mode 100644
index 0000000..fd982de
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/message_set.go
@@ -0,0 +1,311 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Support for message sets.
+ */
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
+// A message type ID is required for storing a protocol buffer in a message set.
+var errNoMessageTypeID = errors.New("proto does not have a message type ID")
+
+// The first two types (_MessageSet_Item and messageSet)
+// model what the protocol compiler produces for the following protocol message:
+// message MessageSet {
+// repeated group Item = 1 {
+// required int32 type_id = 2;
+// required string message = 3;
+// };
+// }
+// That is the MessageSet wire format. We can't use a proto to generate these
+// because that would introduce a circular dependency between it and this package.
+
+type _MessageSet_Item struct {
+ TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
+ Message []byte `protobuf:"bytes,3,req,name=message"`
+}
+
+type messageSet struct {
+ Item []*_MessageSet_Item `protobuf:"group,1,rep"`
+ XXX_unrecognized []byte
+ // TODO: caching?
+}
+
+// Make sure messageSet is a Message.
+var _ Message = (*messageSet)(nil)
+
+// messageTypeIder is an interface satisfied by a protocol buffer type
+// that may be stored in a MessageSet.
+type messageTypeIder interface {
+ MessageTypeId() int32
+}
+
+func (ms *messageSet) find(pb Message) *_MessageSet_Item {
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return nil
+ }
+ id := mti.MessageTypeId()
+ for _, item := range ms.Item {
+ if *item.TypeId == id {
+ return item
+ }
+ }
+ return nil
+}
+
+func (ms *messageSet) Has(pb Message) bool {
+ if ms.find(pb) != nil {
+ return true
+ }
+ return false
+}
+
+func (ms *messageSet) Unmarshal(pb Message) error {
+ if item := ms.find(pb); item != nil {
+ return Unmarshal(item.Message, pb)
+ }
+ if _, ok := pb.(messageTypeIder); !ok {
+ return errNoMessageTypeID
+ }
+ return nil // TODO: return error instead?
+}
+
+func (ms *messageSet) Marshal(pb Message) error {
+ msg, err := Marshal(pb)
+ if err != nil {
+ return err
+ }
+ if item := ms.find(pb); item != nil {
+ // reuse existing item
+ item.Message = msg
+ return nil
+ }
+
+ mti, ok := pb.(messageTypeIder)
+ if !ok {
+ return errNoMessageTypeID
+ }
+
+ mtid := mti.MessageTypeId()
+ ms.Item = append(ms.Item, &_MessageSet_Item{
+ TypeId: &mtid,
+ Message: msg,
+ })
+ return nil
+}
+
+func (ms *messageSet) Reset() { *ms = messageSet{} }
+func (ms *messageSet) String() string { return CompactTextString(ms) }
+func (*messageSet) ProtoMessage() {}
+
+// Support for the message_set_wire_format message option.
+
+func skipVarint(buf []byte) []byte {
+ i := 0
+ for ; buf[i]&0x80 != 0; i++ {
+ }
+ return buf[i+1:]
+}
+
+// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
+// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
+func MarshalMessageSet(exts interface{}) ([]byte, error) {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ if err := encodeExtensions(exts); err != nil {
+ return nil, err
+ }
+ m, _ = exts.extensionsRead()
+ case map[int32]Extension:
+ if err := encodeExtensionsMap(exts); err != nil {
+ return nil, err
+ }
+ m = exts
+ default:
+ return nil, errors.New("proto: not an extension map")
+ }
+
+ // Sort extension IDs to provide a deterministic encoding.
+ // See also enc_map in encode.go.
+ ids := make([]int, 0, len(m))
+ for id := range m {
+ ids = append(ids, int(id))
+ }
+ sort.Ints(ids)
+
+ ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
+ for _, id := range ids {
+ e := m[int32(id)]
+ // Remove the wire type and field number varint, as well as the length varint.
+ msg := skipVarint(skipVarint(e.enc))
+
+ ms.Item = append(ms.Item, &_MessageSet_Item{
+ TypeId: Int32(int32(id)),
+ Message: msg,
+ })
+ }
+ return Marshal(ms)
+}
+
+// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
+// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
+func UnmarshalMessageSet(buf []byte, exts interface{}) error {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ m = exts.extensionsWrite()
+ case map[int32]Extension:
+ m = exts
+ default:
+ return errors.New("proto: not an extension map")
+ }
+
+ ms := new(messageSet)
+ if err := Unmarshal(buf, ms); err != nil {
+ return err
+ }
+ for _, item := range ms.Item {
+ id := *item.TypeId
+ msg := item.Message
+
+ // Restore wire type and field number varint, plus length varint.
+ // Be careful to preserve duplicate items.
+ b := EncodeVarint(uint64(id)<<3 | WireBytes)
+ if ext, ok := m[id]; ok {
+ // Existing data; rip off the tag and length varint
+ // so we join the new data correctly.
+ // We can assume that ext.enc is set because we are unmarshaling.
+ o := ext.enc[len(b):] // skip wire type and field number
+ _, n := DecodeVarint(o) // calculate length of length varint
+ o = o[n:] // skip length varint
+ msg = append(o, msg...) // join old data and new data
+ }
+ b = append(b, EncodeVarint(uint64(len(msg)))...)
+ b = append(b, msg...)
+
+ m[id] = Extension{enc: b}
+ }
+ return nil
+}
+
+// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
+// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
+func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
+ var m map[int32]Extension
+ switch exts := exts.(type) {
+ case *XXX_InternalExtensions:
+ m, _ = exts.extensionsRead()
+ case map[int32]Extension:
+ m = exts
+ default:
+ return nil, errors.New("proto: not an extension map")
+ }
+ var b bytes.Buffer
+ b.WriteByte('{')
+
+ // Process the map in key order for deterministic output.
+ ids := make([]int32, 0, len(m))
+ for id := range m {
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
+
+ for i, id := range ids {
+ ext := m[id]
+ if i > 0 {
+ b.WriteByte(',')
+ }
+
+ msd, ok := messageSetMap[id]
+ if !ok {
+ // Unknown type; we can't render it, so skip it.
+ continue
+ }
+ fmt.Fprintf(&b, `"[%s]":`, msd.name)
+
+ x := ext.value
+ if x == nil {
+ x = reflect.New(msd.t.Elem()).Interface()
+ if err := Unmarshal(ext.enc, x.(Message)); err != nil {
+ return nil, err
+ }
+ }
+ d, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ b.Write(d)
+ }
+ b.WriteByte('}')
+ return b.Bytes(), nil
+}
+
+// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
+// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
+func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
+ // Common-case fast path.
+ if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
+ return nil
+ }
+
+ // This is fairly tricky, and it's not clear that it is needed.
+ return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
+}
+
+// A global registry of types that can be used in a MessageSet.
+
+var messageSetMap = make(map[int32]messageSetDesc)
+
+type messageSetDesc struct {
+ t reflect.Type // pointer to struct
+ name string
+}
+
+// RegisterMessageSetType is called from the generated code.
+func RegisterMessageSetType(m Message, fieldNum int32, name string) {
+ messageSetMap[fieldNum] = messageSetDesc{
+ t: reflect.TypeOf(m),
+ name: name,
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
new file mode 100644
index 0000000..fb512e2
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
@@ -0,0 +1,484 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2012 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build appengine js
+
+// This file contains an implementation of proto field accesses using package reflect.
+// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
+// be used on App Engine.
+
+package proto
+
+import (
+ "math"
+ "reflect"
+)
+
+// A structPointer is a pointer to a struct.
+type structPointer struct {
+ v reflect.Value
+}
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+// The reflect value must itself be a pointer to a struct.
+func toStructPointer(v reflect.Value) structPointer {
+ return structPointer{v}
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+ return p.v.IsNil()
+}
+
+// Interface returns the struct pointer as an interface value.
+func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
+ return p.v.Interface()
+}
+
+// A field identifies a field in a struct, accessible from a structPointer.
+// In this implementation, a field is identified by the sequence of field indices
+// passed to reflect's FieldByIndex.
+type field []int
+
+// toField returns a field equivalent to the given reflect field.
+func toField(f *reflect.StructField) field {
+ return f.Index
+}
+
+// invalidField is an invalid field identifier.
+var invalidField = field(nil)
+
+// IsValid reports whether the field identifier is valid.
+func (f field) IsValid() bool { return f != nil }
+
+// field returns the given field in the struct as a reflect value.
+func structPointer_field(p structPointer, f field) reflect.Value {
+ // Special case: an extension map entry with a value of type T
+ // passes a *T to the struct-handling code with a zero field,
+ // expecting that it will be treated as equivalent to *struct{ X T },
+ // which has the same memory layout. We have to handle that case
+ // specially, because reflect will panic if we call FieldByIndex on a
+ // non-struct.
+ if f == nil {
+ return p.v.Elem()
+ }
+
+ return p.v.Elem().FieldByIndex(f)
+}
+
+// ifield returns the given field in the struct as an interface value.
+func structPointer_ifield(p structPointer, f field) interface{} {
+ return structPointer_field(p, f).Addr().Interface()
+}
+
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+ return structPointer_ifield(p, f).(*[]byte)
+}
+
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+ return structPointer_ifield(p, f).(*[][]byte)
+}
+
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+ return structPointer_ifield(p, f).(**bool)
+}
+
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+ return structPointer_ifield(p, f).(*bool)
+}
+
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+ return structPointer_ifield(p, f).(*[]bool)
+}
+
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+ return structPointer_ifield(p, f).(**string)
+}
+
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+ return structPointer_ifield(p, f).(*string)
+}
+
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+ return structPointer_ifield(p, f).(*[]string)
+}
+
+// Extensions returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+ return structPointer_ifield(p, f).(*XXX_InternalExtensions)
+}
+
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+ return structPointer_ifield(p, f).(*map[int32]Extension)
+}
+
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+ return structPointer_field(p, f).Addr()
+}
+
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+ structPointer_field(p, f).Set(q.v)
+}
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+ return structPointer{structPointer_field(p, f)}
+}
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
+ return structPointerSlice{structPointer_field(p, f)}
+}
+
+// A structPointerSlice represents the address of a slice of pointers to structs
+// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
+type structPointerSlice struct {
+ v reflect.Value
+}
+
+func (p structPointerSlice) Len() int { return p.v.Len() }
+func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
+func (p structPointerSlice) Append(q structPointer) {
+ p.v.Set(reflect.Append(p.v, q.v))
+}
+
+var (
+ int32Type = reflect.TypeOf(int32(0))
+ uint32Type = reflect.TypeOf(uint32(0))
+ float32Type = reflect.TypeOf(float32(0))
+ int64Type = reflect.TypeOf(int64(0))
+ uint64Type = reflect.TypeOf(uint64(0))
+ float64Type = reflect.TypeOf(float64(0))
+)
+
+// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
+// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
+type word32 struct {
+ v reflect.Value
+}
+
+// IsNil reports whether p is nil.
+func word32_IsNil(p word32) bool {
+ return p.v.IsNil()
+}
+
+// Set sets p to point at a newly allocated word with bits set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+ t := p.v.Type().Elem()
+ switch t {
+ case int32Type:
+ if len(o.int32s) == 0 {
+ o.int32s = make([]int32, uint32PoolSize)
+ }
+ o.int32s[0] = int32(x)
+ p.v.Set(reflect.ValueOf(&o.int32s[0]))
+ o.int32s = o.int32s[1:]
+ return
+ case uint32Type:
+ if len(o.uint32s) == 0 {
+ o.uint32s = make([]uint32, uint32PoolSize)
+ }
+ o.uint32s[0] = x
+ p.v.Set(reflect.ValueOf(&o.uint32s[0]))
+ o.uint32s = o.uint32s[1:]
+ return
+ case float32Type:
+ if len(o.float32s) == 0 {
+ o.float32s = make([]float32, uint32PoolSize)
+ }
+ o.float32s[0] = math.Float32frombits(x)
+ p.v.Set(reflect.ValueOf(&o.float32s[0]))
+ o.float32s = o.float32s[1:]
+ return
+ }
+
+ // must be enum
+ p.v.Set(reflect.New(t))
+ p.v.Elem().SetInt(int64(int32(x)))
+}
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32_Get(p word32) uint32 {
+ elem := p.v.Elem()
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+ return word32{structPointer_field(p, f)}
+}
+
+// A word32Val represents a field of type int32, uint32, float32, or enum.
+// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
+type word32Val struct {
+ v reflect.Value
+}
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+ switch p.v.Type() {
+ case int32Type:
+ p.v.SetInt(int64(x))
+ return
+ case uint32Type:
+ p.v.SetUint(uint64(x))
+ return
+ case float32Type:
+ p.v.SetFloat(float64(math.Float32frombits(x)))
+ return
+ }
+
+ // must be enum
+ p.v.SetInt(int64(int32(x)))
+}
+
+// Get gets the bits pointed at by p, as a uint32.
+func word32Val_Get(p word32Val) uint32 {
+ elem := p.v
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+ return word32Val{structPointer_field(p, f)}
+}
+
+// A word32Slice is a slice of 32-bit values.
+// That is, v.Type() is []int32, []uint32, []float32, or []enum.
+type word32Slice struct {
+ v reflect.Value
+}
+
+func (p word32Slice) Append(x uint32) {
+ n, m := p.v.Len(), p.v.Cap()
+ if n < m {
+ p.v.SetLen(n + 1)
+ } else {
+ t := p.v.Type().Elem()
+ p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+ }
+ elem := p.v.Index(n)
+ switch elem.Kind() {
+ case reflect.Int32:
+ elem.SetInt(int64(int32(x)))
+ case reflect.Uint32:
+ elem.SetUint(uint64(x))
+ case reflect.Float32:
+ elem.SetFloat(float64(math.Float32frombits(x)))
+ }
+}
+
+func (p word32Slice) Len() int {
+ return p.v.Len()
+}
+
+func (p word32Slice) Index(i int) uint32 {
+ elem := p.v.Index(i)
+ switch elem.Kind() {
+ case reflect.Int32:
+ return uint32(elem.Int())
+ case reflect.Uint32:
+ return uint32(elem.Uint())
+ case reflect.Float32:
+ return math.Float32bits(float32(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) word32Slice {
+ return word32Slice{structPointer_field(p, f)}
+}
+
+// word64 is like word32 but for 64-bit values.
+type word64 struct {
+ v reflect.Value
+}
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+ t := p.v.Type().Elem()
+ switch t {
+ case int64Type:
+ if len(o.int64s) == 0 {
+ o.int64s = make([]int64, uint64PoolSize)
+ }
+ o.int64s[0] = int64(x)
+ p.v.Set(reflect.ValueOf(&o.int64s[0]))
+ o.int64s = o.int64s[1:]
+ return
+ case uint64Type:
+ if len(o.uint64s) == 0 {
+ o.uint64s = make([]uint64, uint64PoolSize)
+ }
+ o.uint64s[0] = x
+ p.v.Set(reflect.ValueOf(&o.uint64s[0]))
+ o.uint64s = o.uint64s[1:]
+ return
+ case float64Type:
+ if len(o.float64s) == 0 {
+ o.float64s = make([]float64, uint64PoolSize)
+ }
+ o.float64s[0] = math.Float64frombits(x)
+ p.v.Set(reflect.ValueOf(&o.float64s[0]))
+ o.float64s = o.float64s[1:]
+ return
+ }
+ panic("unreachable")
+}
+
+func word64_IsNil(p word64) bool {
+ return p.v.IsNil()
+}
+
+func word64_Get(p word64) uint64 {
+ elem := p.v.Elem()
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return elem.Uint()
+ case reflect.Float64:
+ return math.Float64bits(elem.Float())
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64(p structPointer, f field) word64 {
+ return word64{structPointer_field(p, f)}
+}
+
+// word64Val is like word32Val but for 64-bit values.
+type word64Val struct {
+ v reflect.Value
+}
+
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+ switch p.v.Type() {
+ case int64Type:
+ p.v.SetInt(int64(x))
+ return
+ case uint64Type:
+ p.v.SetUint(x)
+ return
+ case float64Type:
+ p.v.SetFloat(math.Float64frombits(x))
+ return
+ }
+ panic("unreachable")
+}
+
+func word64Val_Get(p word64Val) uint64 {
+ elem := p.v
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return elem.Uint()
+ case reflect.Float64:
+ return math.Float64bits(elem.Float())
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+ return word64Val{structPointer_field(p, f)}
+}
+
+type word64Slice struct {
+ v reflect.Value
+}
+
+func (p word64Slice) Append(x uint64) {
+ n, m := p.v.Len(), p.v.Cap()
+ if n < m {
+ p.v.SetLen(n + 1)
+ } else {
+ t := p.v.Type().Elem()
+ p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
+ }
+ elem := p.v.Index(n)
+ switch elem.Kind() {
+ case reflect.Int64:
+ elem.SetInt(int64(int64(x)))
+ case reflect.Uint64:
+ elem.SetUint(uint64(x))
+ case reflect.Float64:
+ elem.SetFloat(float64(math.Float64frombits(x)))
+ }
+}
+
+func (p word64Slice) Len() int {
+ return p.v.Len()
+}
+
+func (p word64Slice) Index(i int) uint64 {
+ elem := p.v.Index(i)
+ switch elem.Kind() {
+ case reflect.Int64:
+ return uint64(elem.Int())
+ case reflect.Uint64:
+ return uint64(elem.Uint())
+ case reflect.Float64:
+ return math.Float64bits(float64(elem.Float()))
+ }
+ panic("unreachable")
+}
+
+func structPointer_Word64Slice(p structPointer, f field) word64Slice {
+ return word64Slice{structPointer_field(p, f)}
+}
diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
new file mode 100644
index 0000000..6b5567d
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
@@ -0,0 +1,270 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2012 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// +build !appengine,!js
+
+// This file contains the implementation of the proto field accesses using package unsafe.
+
+package proto
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+// NOTE: These type_Foo functions would more idiomatically be methods,
+// but Go does not allow methods on pointer types, and we must preserve
+// some pointer type for the garbage collector. We use these
+// funcs with clunky names as our poor approximation to methods.
+//
+// An alternative would be
+// type structPointer struct { p unsafe.Pointer }
+// but that does not registerize as well.
+
+// A structPointer is a pointer to a struct.
+type structPointer unsafe.Pointer
+
+// toStructPointer returns a structPointer equivalent to the given reflect value.
+func toStructPointer(v reflect.Value) structPointer {
+ return structPointer(unsafe.Pointer(v.Pointer()))
+}
+
+// IsNil reports whether p is nil.
+func structPointer_IsNil(p structPointer) bool {
+ return p == nil
+}
+
+// Interface returns the struct pointer, assumed to have element type t,
+// as an interface value.
+func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
+ return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
+}
+
+// A field identifies a field in a struct, accessible from a structPointer.
+// In this implementation, a field is identified by its byte offset from the start of the struct.
+type field uintptr
+
+// toField returns a field equivalent to the given reflect field.
+func toField(f *reflect.StructField) field {
+ return field(f.Offset)
+}
+
+// invalidField is an invalid field identifier.
+const invalidField = ^field(0)
+
+// IsValid reports whether the field identifier is valid.
+func (f field) IsValid() bool {
+ return f != ^field(0)
+}
+
+// Bytes returns the address of a []byte field in the struct.
+func structPointer_Bytes(p structPointer, f field) *[]byte {
+ return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BytesSlice returns the address of a [][]byte field in the struct.
+func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
+ return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// Bool returns the address of a *bool field in the struct.
+func structPointer_Bool(p structPointer, f field) **bool {
+ return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BoolVal returns the address of a bool field in the struct.
+func structPointer_BoolVal(p structPointer, f field) *bool {
+ return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// BoolSlice returns the address of a []bool field in the struct.
+func structPointer_BoolSlice(p structPointer, f field) *[]bool {
+ return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// String returns the address of a *string field in the struct.
+func structPointer_String(p structPointer, f field) **string {
+ return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StringVal returns the address of a string field in the struct.
+func structPointer_StringVal(p structPointer, f field) *string {
+ return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StringSlice returns the address of a []string field in the struct.
+func structPointer_StringSlice(p structPointer, f field) *[]string {
+ return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// ExtMap returns the address of an extension map field in the struct.
+func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
+ return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
+ return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
+ return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
+}
+
+// SetStructPointer writes a *struct field in the struct.
+func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
+ *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
+}
+
+// GetStructPointer reads a *struct field in the struct.
+func structPointer_GetStructPointer(p structPointer, f field) structPointer {
+ return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// StructPointerSlice the address of a []*struct field in the struct.
+func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
+ return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
+type structPointerSlice []structPointer
+
+func (v *structPointerSlice) Len() int { return len(*v) }
+func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
+func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) }
+
+// A word32 is the address of a "pointer to 32-bit value" field.
+type word32 **uint32
+
+// IsNil reports whether *v is nil.
+func word32_IsNil(p word32) bool {
+ return *p == nil
+}
+
+// Set sets *v to point at a newly allocated word set to x.
+func word32_Set(p word32, o *Buffer, x uint32) {
+ if len(o.uint32s) == 0 {
+ o.uint32s = make([]uint32, uint32PoolSize)
+ }
+ o.uint32s[0] = x
+ *p = &o.uint32s[0]
+ o.uint32s = o.uint32s[1:]
+}
+
+// Get gets the value pointed at by *v.
+func word32_Get(p word32) uint32 {
+ return **p
+}
+
+// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32(p structPointer, f field) word32 {
+ return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// A word32Val is the address of a 32-bit value field.
+type word32Val *uint32
+
+// Set sets *p to x.
+func word32Val_Set(p word32Val, x uint32) {
+ *p = x
+}
+
+// Get gets the value pointed at by p.
+func word32Val_Get(p word32Val) uint32 {
+ return *p
+}
+
+// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
+func structPointer_Word32Val(p structPointer, f field) word32Val {
+ return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// A word32Slice is a slice of 32-bit values.
+type word32Slice []uint32
+
+func (v *word32Slice) Append(x uint32) { *v = append(*v, x) }
+func (v *word32Slice) Len() int { return len(*v) }
+func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
+
+// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
+func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
+ return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
+
+// word64 is like word32 but for 64-bit values.
+type word64 **uint64
+
+func word64_Set(p word64, o *Buffer, x uint64) {
+ if len(o.uint64s) == 0 {
+ o.uint64s = make([]uint64, uint64PoolSize)
+ }
+ o.uint64s[0] = x
+ *p = &o.uint64s[0]
+ o.uint64s = o.uint64s[1:]
+}
+
+func word64_IsNil(p word64) bool {
+ return *p == nil
+}
+
+func word64_Get(p word64) uint64 {
+ return **p
+}
+
+func structPointer_Word64(p structPointer, f field) word64 {
+ return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// word64Val is like word32Val but for 64-bit values.
+type word64Val *uint64
+
+func word64Val_Set(p word64Val, o *Buffer, x uint64) {
+ *p = x
+}
+
+func word64Val_Get(p word64Val) uint64 {
+ return *p
+}
+
+func structPointer_Word64Val(p structPointer, f field) word64Val {
+ return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+}
+
+// word64Slice is like word32Slice but for 64-bit values.
+type word64Slice []uint64
+
+func (v *word64Slice) Append(x uint64) { *v = append(*v, x) }
+func (v *word64Slice) Len() int { return len(*v) }
+func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
+
+func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
+ return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+}
diff --git a/vendor/github.com/golang/protobuf/proto/properties.go b/vendor/github.com/golang/protobuf/proto/properties.go
new file mode 100644
index 0000000..ec2289c
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/properties.go
@@ -0,0 +1,872 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+/*
+ * Routines for encoding data into the wire format for protocol buffers.
+ */
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+const debug bool = false
+
+// Constants that identify the encoding of a value on the wire.
+const (
+ WireVarint = 0
+ WireFixed64 = 1
+ WireBytes = 2
+ WireStartGroup = 3
+ WireEndGroup = 4
+ WireFixed32 = 5
+)
+
+const startSize = 10 // initial slice/string sizes
+
+// Encoders are defined in encode.go
+// An encoder outputs the full representation of a field, including its
+// tag and encoder type.
+type encoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueEncoder encodes a single integer in a particular encoding.
+type valueEncoder func(o *Buffer, x uint64) error
+
+// Sizers are defined in encode.go
+// A sizer returns the encoded size of a field, including its tag and encoder
+// type.
+type sizer func(prop *Properties, base structPointer) int
+
+// A valueSizer returns the encoded size of a single integer in a particular
+// encoding.
+type valueSizer func(x uint64) int
+
+// Decoders are defined in decode.go
+// A decoder creates a value from its wire representation.
+// Unrecognized subelements are saved in unrec.
+type decoder func(p *Buffer, prop *Properties, base structPointer) error
+
+// A valueDecoder decodes a single integer in a particular encoding.
+type valueDecoder func(o *Buffer) (x uint64, err error)
+
+// A oneofMarshaler does the marshaling for all oneof fields in a message.
+type oneofMarshaler func(Message, *Buffer) error
+
+// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
+type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
+
+// A oneofSizer does the sizing for all oneof fields in a message.
+type oneofSizer func(Message) int
+
+// tagMap is an optimization over map[int]int for typical protocol buffer
+// use-cases. Encoded protocol buffers are often in tag order with small tag
+// numbers.
+type tagMap struct {
+ fastTags []int
+ slowTags map[int]int
+}
+
+// tagMapFastLimit is the upper bound on the tag number that will be stored in
+// the tagMap slice rather than its map.
+const tagMapFastLimit = 1024
+
+func (p *tagMap) get(t int) (int, bool) {
+ if t > 0 && t < tagMapFastLimit {
+ if t >= len(p.fastTags) {
+ return 0, false
+ }
+ fi := p.fastTags[t]
+ return fi, fi >= 0
+ }
+ fi, ok := p.slowTags[t]
+ return fi, ok
+}
+
+func (p *tagMap) put(t int, fi int) {
+ if t > 0 && t < tagMapFastLimit {
+ for len(p.fastTags) < t+1 {
+ p.fastTags = append(p.fastTags, -1)
+ }
+ p.fastTags[t] = fi
+ return
+ }
+ if p.slowTags == nil {
+ p.slowTags = make(map[int]int)
+ }
+ p.slowTags[t] = fi
+}
+
+// StructProperties represents properties for all the fields of a struct.
+// decoderTags and decoderOrigNames should only be used by the decoder.
+type StructProperties struct {
+ Prop []*Properties // properties for each field
+ reqCount int // required count
+ decoderTags tagMap // map from proto tag to struct field number
+ decoderOrigNames map[string]int // map from original name to struct field number
+ order []int // list of struct field numbers in tag order
+ unrecField field // field id of the XXX_unrecognized []byte field
+ extendable bool // is this an extendable proto
+
+ oneofMarshaler oneofMarshaler
+ oneofUnmarshaler oneofUnmarshaler
+ oneofSizer oneofSizer
+ stype reflect.Type
+
+ // OneofTypes contains information about the oneof fields in this message.
+ // It is keyed by the original name of a field.
+ OneofTypes map[string]*OneofProperties
+}
+
+// OneofProperties represents information about a specific field in a oneof.
+type OneofProperties struct {
+ Type reflect.Type // pointer to generated struct type for this oneof field
+ Field int // struct field number of the containing oneof in the message
+ Prop *Properties
+}
+
+// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
+// See encode.go, (*Buffer).enc_struct.
+
+func (sp *StructProperties) Len() int { return len(sp.order) }
+func (sp *StructProperties) Less(i, j int) bool {
+ return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
+}
+func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
+
+// Properties represents the protocol-specific behavior of a single struct field.
+type Properties struct {
+ Name string // name of the field, for error messages
+ OrigName string // original name before protocol compiler (always set)
+ JSONName string // name to use for JSON; determined by protoc
+ Wire string
+ WireType int
+ Tag int
+ Required bool
+ Optional bool
+ Repeated bool
+ Packed bool // relevant for repeated primitives only
+ Enum string // set for enum types only
+ proto3 bool // whether this is known to be a proto3 field; set for []byte only
+ oneof bool // whether this is a oneof field
+
+ Default string // default value
+ HasDefault bool // whether an explicit default was provided
+ def_uint64 uint64
+
+ enc encoder
+ valEnc valueEncoder // set for bool and numeric types only
+ field field
+ tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
+ tagbuf [8]byte
+ stype reflect.Type // set for struct types only
+ sprop *StructProperties // set for struct types only
+ isMarshaler bool
+ isUnmarshaler bool
+
+ mtype reflect.Type // set for map types only
+ mkeyprop *Properties // set for map types only
+ mvalprop *Properties // set for map types only
+
+ size sizer
+ valSize valueSizer // set for bool and numeric types only
+
+ dec decoder
+ valDec valueDecoder // set for bool and numeric types only
+
+ // If this is a packable field, this will be the decoder for the packed version of the field.
+ packedDec decoder
+}
+
+// String formats the properties in the protobuf struct field tag style.
+func (p *Properties) String() string {
+ s := p.Wire
+ s = ","
+ s += strconv.Itoa(p.Tag)
+ if p.Required {
+ s += ",req"
+ }
+ if p.Optional {
+ s += ",opt"
+ }
+ if p.Repeated {
+ s += ",rep"
+ }
+ if p.Packed {
+ s += ",packed"
+ }
+ s += ",name=" + p.OrigName
+ if p.JSONName != p.OrigName {
+ s += ",json=" + p.JSONName
+ }
+ if p.proto3 {
+ s += ",proto3"
+ }
+ if p.oneof {
+ s += ",oneof"
+ }
+ if len(p.Enum) > 0 {
+ s += ",enum=" + p.Enum
+ }
+ if p.HasDefault {
+ s += ",def=" + p.Default
+ }
+ return s
+}
+
+// Parse populates p by parsing a string in the protobuf struct field tag style.
+func (p *Properties) Parse(s string) {
+ // "bytes,49,opt,name=foo,def=hello!"
+ fields := strings.Split(s, ",") // breaks def=, but handled below.
+ if len(fields) < 2 {
+ fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
+ return
+ }
+
+ p.Wire = fields[0]
+ switch p.Wire {
+ case "varint":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeVarint
+ p.valDec = (*Buffer).DecodeVarint
+ p.valSize = sizeVarint
+ case "fixed32":
+ p.WireType = WireFixed32
+ p.valEnc = (*Buffer).EncodeFixed32
+ p.valDec = (*Buffer).DecodeFixed32
+ p.valSize = sizeFixed32
+ case "fixed64":
+ p.WireType = WireFixed64
+ p.valEnc = (*Buffer).EncodeFixed64
+ p.valDec = (*Buffer).DecodeFixed64
+ p.valSize = sizeFixed64
+ case "zigzag32":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag32
+ p.valDec = (*Buffer).DecodeZigzag32
+ p.valSize = sizeZigzag32
+ case "zigzag64":
+ p.WireType = WireVarint
+ p.valEnc = (*Buffer).EncodeZigzag64
+ p.valDec = (*Buffer).DecodeZigzag64
+ p.valSize = sizeZigzag64
+ case "bytes", "group":
+ p.WireType = WireBytes
+ // no numeric converter for non-numeric types
+ default:
+ fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
+ return
+ }
+
+ var err error
+ p.Tag, err = strconv.Atoi(fields[1])
+ if err != nil {
+ return
+ }
+
+ for i := 2; i < len(fields); i++ {
+ f := fields[i]
+ switch {
+ case f == "req":
+ p.Required = true
+ case f == "opt":
+ p.Optional = true
+ case f == "rep":
+ p.Repeated = true
+ case f == "packed":
+ p.Packed = true
+ case strings.HasPrefix(f, "name="):
+ p.OrigName = f[5:]
+ case strings.HasPrefix(f, "json="):
+ p.JSONName = f[5:]
+ case strings.HasPrefix(f, "enum="):
+ p.Enum = f[5:]
+ case f == "proto3":
+ p.proto3 = true
+ case f == "oneof":
+ p.oneof = true
+ case strings.HasPrefix(f, "def="):
+ p.HasDefault = true
+ p.Default = f[4:] // rest of string
+ if i+1 < len(fields) {
+ // Commas aren't escaped, and def is always last.
+ p.Default += "," + strings.Join(fields[i+1:], ",")
+ break
+ }
+ }
+ }
+}
+
+func logNoSliceEnc(t1, t2 reflect.Type) {
+ fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
+}
+
+var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
+
+// Initialize the fields for encoding and decoding.
+func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
+ p.enc = nil
+ p.dec = nil
+ p.size = nil
+
+ switch t1 := typ; t1.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
+
+ // proto3 scalar types
+
+ case reflect.Bool:
+ p.enc = (*Buffer).enc_proto3_bool
+ p.dec = (*Buffer).dec_proto3_bool
+ p.size = size_proto3_bool
+ case reflect.Int32:
+ p.enc = (*Buffer).enc_proto3_int32
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_proto3_int32
+ case reflect.Uint32:
+ p.enc = (*Buffer).enc_proto3_uint32
+ p.dec = (*Buffer).dec_proto3_int32 // can reuse
+ p.size = size_proto3_uint32
+ case reflect.Int64, reflect.Uint64:
+ p.enc = (*Buffer).enc_proto3_int64
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_proto3_int64
+ case reflect.Float32:
+ p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int32
+ p.size = size_proto3_uint32
+ case reflect.Float64:
+ p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_proto3_int64
+ p.size = size_proto3_int64
+ case reflect.String:
+ p.enc = (*Buffer).enc_proto3_string
+ p.dec = (*Buffer).dec_proto3_string
+ p.size = size_proto3_string
+
+ case reflect.Ptr:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
+ break
+ case reflect.Bool:
+ p.enc = (*Buffer).enc_bool
+ p.dec = (*Buffer).dec_bool
+ p.size = size_bool
+ case reflect.Int32:
+ p.enc = (*Buffer).enc_int32
+ p.dec = (*Buffer).dec_int32
+ p.size = size_int32
+ case reflect.Uint32:
+ p.enc = (*Buffer).enc_uint32
+ p.dec = (*Buffer).dec_int32 // can reuse
+ p.size = size_uint32
+ case reflect.Int64, reflect.Uint64:
+ p.enc = (*Buffer).enc_int64
+ p.dec = (*Buffer).dec_int64
+ p.size = size_int64
+ case reflect.Float32:
+ p.enc = (*Buffer).enc_uint32 // can just treat them as bits
+ p.dec = (*Buffer).dec_int32
+ p.size = size_uint32
+ case reflect.Float64:
+ p.enc = (*Buffer).enc_int64 // can just treat them as bits
+ p.dec = (*Buffer).dec_int64
+ p.size = size_int64
+ case reflect.String:
+ p.enc = (*Buffer).enc_string
+ p.dec = (*Buffer).dec_string
+ p.size = size_string
+ case reflect.Struct:
+ p.stype = t1.Elem()
+ p.isMarshaler = isMarshaler(t1)
+ p.isUnmarshaler = isUnmarshaler(t1)
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_struct_message
+ p.dec = (*Buffer).dec_struct_message
+ p.size = size_struct_message
+ } else {
+ p.enc = (*Buffer).enc_struct_group
+ p.dec = (*Buffer).dec_struct_group
+ p.size = size_struct_group
+ }
+ }
+
+ case reflect.Slice:
+ switch t2 := t1.Elem(); t2.Kind() {
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ case reflect.Bool:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_bool
+ p.size = size_slice_packed_bool
+ } else {
+ p.enc = (*Buffer).enc_slice_bool
+ p.size = size_slice_bool
+ }
+ p.dec = (*Buffer).dec_slice_bool
+ p.packedDec = (*Buffer).dec_slice_packed_bool
+ case reflect.Int32:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int32
+ p.size = size_slice_packed_int32
+ } else {
+ p.enc = (*Buffer).enc_slice_int32
+ p.size = size_slice_int32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case reflect.Uint32:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_uint32
+ p.size = size_slice_packed_uint32
+ } else {
+ p.enc = (*Buffer).enc_slice_uint32
+ p.size = size_slice_uint32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case reflect.Int64, reflect.Uint64:
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ p.size = size_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ p.size = size_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ case reflect.Uint8:
+ p.dec = (*Buffer).dec_slice_byte
+ if p.proto3 {
+ p.enc = (*Buffer).enc_proto3_slice_byte
+ p.size = size_proto3_slice_byte
+ } else {
+ p.enc = (*Buffer).enc_slice_byte
+ p.size = size_slice_byte
+ }
+ case reflect.Float32, reflect.Float64:
+ switch t2.Bits() {
+ case 32:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_uint32
+ p.size = size_slice_packed_uint32
+ } else {
+ p.enc = (*Buffer).enc_slice_uint32
+ p.size = size_slice_uint32
+ }
+ p.dec = (*Buffer).dec_slice_int32
+ p.packedDec = (*Buffer).dec_slice_packed_int32
+ case 64:
+ // can just treat them as bits
+ if p.Packed {
+ p.enc = (*Buffer).enc_slice_packed_int64
+ p.size = size_slice_packed_int64
+ } else {
+ p.enc = (*Buffer).enc_slice_int64
+ p.size = size_slice_int64
+ }
+ p.dec = (*Buffer).dec_slice_int64
+ p.packedDec = (*Buffer).dec_slice_packed_int64
+ default:
+ logNoSliceEnc(t1, t2)
+ break
+ }
+ case reflect.String:
+ p.enc = (*Buffer).enc_slice_string
+ p.dec = (*Buffer).dec_slice_string
+ p.size = size_slice_string
+ case reflect.Ptr:
+ switch t3 := t2.Elem(); t3.Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
+ break
+ case reflect.Struct:
+ p.stype = t2.Elem()
+ p.isMarshaler = isMarshaler(t2)
+ p.isUnmarshaler = isUnmarshaler(t2)
+ if p.Wire == "bytes" {
+ p.enc = (*Buffer).enc_slice_struct_message
+ p.dec = (*Buffer).dec_slice_struct_message
+ p.size = size_slice_struct_message
+ } else {
+ p.enc = (*Buffer).enc_slice_struct_group
+ p.dec = (*Buffer).dec_slice_struct_group
+ p.size = size_slice_struct_group
+ }
+ }
+ case reflect.Slice:
+ switch t2.Elem().Kind() {
+ default:
+ fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
+ break
+ case reflect.Uint8:
+ p.enc = (*Buffer).enc_slice_slice_byte
+ p.dec = (*Buffer).dec_slice_slice_byte
+ p.size = size_slice_slice_byte
+ }
+ }
+
+ case reflect.Map:
+ p.enc = (*Buffer).enc_new_map
+ p.dec = (*Buffer).dec_new_map
+ p.size = size_new_map
+
+ p.mtype = t1
+ p.mkeyprop = &Properties{}
+ p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
+ p.mvalprop = &Properties{}
+ vtype := p.mtype.Elem()
+ if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
+ // The value type is not a message (*T) or bytes ([]byte),
+ // so we need encoders for the pointer to this type.
+ vtype = reflect.PtrTo(vtype)
+ }
+ p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
+ }
+
+ // precalculate tag code
+ wire := p.WireType
+ if p.Packed {
+ wire = WireBytes
+ }
+ x := uint32(p.Tag)<<3 | uint32(wire)
+ i := 0
+ for i = 0; x > 127; i++ {
+ p.tagbuf[i] = 0x80 | uint8(x&0x7F)
+ x >>= 7
+ }
+ p.tagbuf[i] = uint8(x)
+ p.tagcode = p.tagbuf[0 : i+1]
+
+ if p.stype != nil {
+ if lockGetProp {
+ p.sprop = GetProperties(p.stype)
+ } else {
+ p.sprop = getPropertiesLocked(p.stype)
+ }
+ }
+}
+
+var (
+ marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
+ unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+)
+
+// isMarshaler reports whether type t implements Marshaler.
+func isMarshaler(t reflect.Type) bool {
+ // We're checking for (likely) pointer-receiver methods
+ // so if t is not a pointer, something is very wrong.
+ // The calls above only invoke isMarshaler on pointer types.
+ if t.Kind() != reflect.Ptr {
+ panic("proto: misuse of isMarshaler")
+ }
+ return t.Implements(marshalerType)
+}
+
+// isUnmarshaler reports whether type t implements Unmarshaler.
+func isUnmarshaler(t reflect.Type) bool {
+ // We're checking for (likely) pointer-receiver methods
+ // so if t is not a pointer, something is very wrong.
+ // The calls above only invoke isUnmarshaler on pointer types.
+ if t.Kind() != reflect.Ptr {
+ panic("proto: misuse of isUnmarshaler")
+ }
+ return t.Implements(unmarshalerType)
+}
+
+// Init populates the properties from a protocol buffer struct tag.
+func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
+ p.init(typ, name, tag, f, true)
+}
+
+func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
+ // "bytes,49,opt,def=hello!"
+ p.Name = name
+ p.OrigName = name
+ if f != nil {
+ p.field = toField(f)
+ }
+ if tag == "" {
+ return
+ }
+ p.Parse(tag)
+ p.setEncAndDec(typ, f, lockGetProp)
+}
+
+var (
+ propertiesMu sync.RWMutex
+ propertiesMap = make(map[reflect.Type]*StructProperties)
+)
+
+// GetProperties returns the list of properties for the type represented by t.
+// t must represent a generated struct type of a protocol message.
+func GetProperties(t reflect.Type) *StructProperties {
+ if t.Kind() != reflect.Struct {
+ panic("proto: type must have kind struct")
+ }
+
+ // Most calls to GetProperties in a long-running program will be
+ // retrieving details for types we have seen before.
+ propertiesMu.RLock()
+ sprop, ok := propertiesMap[t]
+ propertiesMu.RUnlock()
+ if ok {
+ if collectStats {
+ stats.Chit++
+ }
+ return sprop
+ }
+
+ propertiesMu.Lock()
+ sprop = getPropertiesLocked(t)
+ propertiesMu.Unlock()
+ return sprop
+}
+
+// getPropertiesLocked requires that propertiesMu is held.
+func getPropertiesLocked(t reflect.Type) *StructProperties {
+ if prop, ok := propertiesMap[t]; ok {
+ if collectStats {
+ stats.Chit++
+ }
+ return prop
+ }
+ if collectStats {
+ stats.Cmiss++
+ }
+
+ prop := new(StructProperties)
+ // in case of recursive protos, fill this in now.
+ propertiesMap[t] = prop
+
+ // build properties
+ prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
+ reflect.PtrTo(t).Implements(extendableProtoV1Type)
+ prop.unrecField = invalidField
+ prop.Prop = make([]*Properties, t.NumField())
+ prop.order = make([]int, t.NumField())
+
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ p := new(Properties)
+ name := f.Name
+ p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
+
+ if f.Name == "XXX_InternalExtensions" { // special case
+ p.enc = (*Buffer).enc_exts
+ p.dec = nil // not needed
+ p.size = size_exts
+ } else if f.Name == "XXX_extensions" { // special case
+ p.enc = (*Buffer).enc_map
+ p.dec = nil // not needed
+ p.size = size_map
+ } else if f.Name == "XXX_unrecognized" { // special case
+ prop.unrecField = toField(&f)
+ }
+ oneof := f.Tag.Get("protobuf_oneof") // special case
+ if oneof != "" {
+ // Oneof fields don't use the traditional protobuf tag.
+ p.OrigName = oneof
+ }
+ prop.Prop[i] = p
+ prop.order[i] = i
+ if debug {
+ print(i, " ", f.Name, " ", t.String(), " ")
+ if p.Tag > 0 {
+ print(p.String())
+ }
+ print("\n")
+ }
+ if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
+ fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
+ }
+ }
+
+ // Re-order prop.order.
+ sort.Sort(prop)
+
+ type oneofMessage interface {
+ XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+ }
+ if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
+ var oots []interface{}
+ prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
+ prop.stype = t
+
+ // Interpret oneof metadata.
+ prop.OneofTypes = make(map[string]*OneofProperties)
+ for _, oot := range oots {
+ oop := &OneofProperties{
+ Type: reflect.ValueOf(oot).Type(), // *T
+ Prop: new(Properties),
+ }
+ sft := oop.Type.Elem().Field(0)
+ oop.Prop.Name = sft.Name
+ oop.Prop.Parse(sft.Tag.Get("protobuf"))
+ // There will be exactly one interface field that
+ // this new value is assignable to.
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ if f.Type.Kind() != reflect.Interface {
+ continue
+ }
+ if !oop.Type.AssignableTo(f.Type) {
+ continue
+ }
+ oop.Field = i
+ break
+ }
+ prop.OneofTypes[oop.Prop.OrigName] = oop
+ }
+ }
+
+ // build required counts
+ // build tags
+ reqCount := 0
+ prop.decoderOrigNames = make(map[string]int)
+ for i, p := range prop.Prop {
+ if strings.HasPrefix(p.Name, "XXX_") {
+ // Internal fields should not appear in tags/origNames maps.
+ // They are handled specially when encoding and decoding.
+ continue
+ }
+ if p.Required {
+ reqCount++
+ }
+ prop.decoderTags.put(p.Tag, i)
+ prop.decoderOrigNames[p.OrigName] = i
+ }
+ prop.reqCount = reqCount
+
+ return prop
+}
+
+// Return the Properties object for the x[0]'th field of the structure.
+func propByIndex(t reflect.Type, x []int) *Properties {
+ if len(x) != 1 {
+ fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
+ return nil
+ }
+ prop := GetProperties(t)
+ return prop.Prop[x[0]]
+}
+
+// Get the address and type of a pointer to a struct from an interface.
+func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
+ if pb == nil {
+ err = ErrNil
+ return
+ }
+ // get the reflect type of the pointer to the struct.
+ t = reflect.TypeOf(pb)
+ // get the address of the struct.
+ value := reflect.ValueOf(pb)
+ b = toStructPointer(value)
+ return
+}
+
+// A global registry of enum types.
+// The generated code will register the generated maps by calling RegisterEnum.
+
+var enumValueMaps = make(map[string]map[string]int32)
+
+// RegisterEnum is called from the generated code to install the enum descriptor
+// maps into the global table to aid parsing text format protocol buffers.
+func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
+ if _, ok := enumValueMaps[typeName]; ok {
+ panic("proto: duplicate enum registered: " + typeName)
+ }
+ enumValueMaps[typeName] = valueMap
+}
+
+// EnumValueMap returns the mapping from names to integers of the
+// enum type enumType, or a nil if not found.
+func EnumValueMap(enumType string) map[string]int32 {
+ return enumValueMaps[enumType]
+}
+
+// A registry of all linked message types.
+// The string is a fully-qualified proto name ("pkg.Message").
+var (
+ protoTypes = make(map[string]reflect.Type)
+ revProtoTypes = make(map[reflect.Type]string)
+)
+
+// RegisterType is called from generated code and maps from the fully qualified
+// proto name to the type (pointer to struct) of the protocol buffer.
+func RegisterType(x Message, name string) {
+ if _, ok := protoTypes[name]; ok {
+ // TODO: Some day, make this a panic.
+ log.Printf("proto: duplicate proto type registered: %s", name)
+ return
+ }
+ t := reflect.TypeOf(x)
+ protoTypes[name] = t
+ revProtoTypes[t] = name
+}
+
+// MessageName returns the fully-qualified proto name for the given message type.
+func MessageName(x Message) string {
+ type xname interface {
+ XXX_MessageName() string
+ }
+ if m, ok := x.(xname); ok {
+ return m.XXX_MessageName()
+ }
+ return revProtoTypes[reflect.TypeOf(x)]
+}
+
+// MessageType returns the message type (pointer to struct) for a named message.
+func MessageType(name string) reflect.Type { return protoTypes[name] }
+
+// A registry of all linked proto files.
+var (
+ protoFiles = make(map[string][]byte) // file name => fileDescriptor
+)
+
+// RegisterFile is called from generated code and maps from the
+// full file name of a .proto file to its compressed FileDescriptorProto.
+func RegisterFile(filename string, fileDescriptor []byte) {
+ protoFiles[filename] = fileDescriptor
+}
+
+// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
+func FileDescriptor(filename string) []byte { return protoFiles[filename] }
diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
new file mode 100644
index 0000000..cc4d048
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
@@ -0,0 +1,347 @@
+// Code generated by protoc-gen-go.
+// source: proto3_proto/proto3.proto
+// DO NOT EDIT!
+
+/*
+Package proto3_proto is a generated protocol buffer package.
+
+It is generated from these files:
+ proto3_proto/proto3.proto
+
+It has these top-level messages:
+ Message
+ Nested
+ MessageWithMap
+ IntMap
+ IntMaps
+*/
+package proto3_proto
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import google_protobuf "github.com/golang/protobuf/ptypes/any"
+import testdata "github.com/golang/protobuf/proto/testdata"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Message_Humour int32
+
+const (
+ Message_UNKNOWN Message_Humour = 0
+ Message_PUNS Message_Humour = 1
+ Message_SLAPSTICK Message_Humour = 2
+ Message_BILL_BAILEY Message_Humour = 3
+)
+
+var Message_Humour_name = map[int32]string{
+ 0: "UNKNOWN",
+ 1: "PUNS",
+ 2: "SLAPSTICK",
+ 3: "BILL_BAILEY",
+}
+var Message_Humour_value = map[string]int32{
+ "UNKNOWN": 0,
+ "PUNS": 1,
+ "SLAPSTICK": 2,
+ "BILL_BAILEY": 3,
+}
+
+func (x Message_Humour) String() string {
+ return proto.EnumName(Message_Humour_name, int32(x))
+}
+func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
+
+type Message struct {
+ Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
+ HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm" json:"height_in_cm,omitempty"`
+ Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
+ ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount" json:"result_count,omitempty"`
+ TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman" json:"true_scotsman,omitempty"`
+ Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"`
+ Key []uint64 `protobuf:"varint,5,rep,packed,name=key" json:"key,omitempty"`
+ ShortKey []int32 `protobuf:"varint,19,rep,packed,name=short_key,json=shortKey" json:"short_key,omitempty"`
+ Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
+ RFunny []Message_Humour `protobuf:"varint,16,rep,packed,name=r_funny,json=rFunny,enum=proto3_proto.Message_Humour" json:"r_funny,omitempty"`
+ Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field" json:"proto2_field,omitempty"`
+ Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ Anything *google_protobuf.Any `protobuf:"bytes,14,opt,name=anything" json:"anything,omitempty"`
+ ManyThings []*google_protobuf.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings" json:"many_things,omitempty"`
+ Submessage *Message `protobuf:"bytes,17,opt,name=submessage" json:"submessage,omitempty"`
+ Children []*Message `protobuf:"bytes,18,rep,name=children" json:"children,omitempty"`
+}
+
+func (m *Message) Reset() { *m = Message{} }
+func (m *Message) String() string { return proto.CompactTextString(m) }
+func (*Message) ProtoMessage() {}
+func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func (m *Message) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *Message) GetHilarity() Message_Humour {
+ if m != nil {
+ return m.Hilarity
+ }
+ return Message_UNKNOWN
+}
+
+func (m *Message) GetHeightInCm() uint32 {
+ if m != nil {
+ return m.HeightInCm
+ }
+ return 0
+}
+
+func (m *Message) GetData() []byte {
+ if m != nil {
+ return m.Data
+ }
+ return nil
+}
+
+func (m *Message) GetResultCount() int64 {
+ if m != nil {
+ return m.ResultCount
+ }
+ return 0
+}
+
+func (m *Message) GetTrueScotsman() bool {
+ if m != nil {
+ return m.TrueScotsman
+ }
+ return false
+}
+
+func (m *Message) GetScore() float32 {
+ if m != nil {
+ return m.Score
+ }
+ return 0
+}
+
+func (m *Message) GetKey() []uint64 {
+ if m != nil {
+ return m.Key
+ }
+ return nil
+}
+
+func (m *Message) GetShortKey() []int32 {
+ if m != nil {
+ return m.ShortKey
+ }
+ return nil
+}
+
+func (m *Message) GetNested() *Nested {
+ if m != nil {
+ return m.Nested
+ }
+ return nil
+}
+
+func (m *Message) GetRFunny() []Message_Humour {
+ if m != nil {
+ return m.RFunny
+ }
+ return nil
+}
+
+func (m *Message) GetTerrain() map[string]*Nested {
+ if m != nil {
+ return m.Terrain
+ }
+ return nil
+}
+
+func (m *Message) GetProto2Field() *testdata.SubDefaults {
+ if m != nil {
+ return m.Proto2Field
+ }
+ return nil
+}
+
+func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
+ if m != nil {
+ return m.Proto2Value
+ }
+ return nil
+}
+
+func (m *Message) GetAnything() *google_protobuf.Any {
+ if m != nil {
+ return m.Anything
+ }
+ return nil
+}
+
+func (m *Message) GetManyThings() []*google_protobuf.Any {
+ if m != nil {
+ return m.ManyThings
+ }
+ return nil
+}
+
+func (m *Message) GetSubmessage() *Message {
+ if m != nil {
+ return m.Submessage
+ }
+ return nil
+}
+
+func (m *Message) GetChildren() []*Message {
+ if m != nil {
+ return m.Children
+ }
+ return nil
+}
+
+type Nested struct {
+ Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"`
+ Cute bool `protobuf:"varint,2,opt,name=cute" json:"cute,omitempty"`
+}
+
+func (m *Nested) Reset() { *m = Nested{} }
+func (m *Nested) String() string { return proto.CompactTextString(m) }
+func (*Nested) ProtoMessage() {}
+func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+func (m *Nested) GetBunny() string {
+ if m != nil {
+ return m.Bunny
+ }
+ return ""
+}
+
+func (m *Nested) GetCute() bool {
+ if m != nil {
+ return m.Cute
+ }
+ return false
+}
+
+type MessageWithMap struct {
+ ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"`
+}
+
+func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
+func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
+func (*MessageWithMap) ProtoMessage() {}
+func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
+ if m != nil {
+ return m.ByteMapping
+ }
+ return nil
+}
+
+type IntMap struct {
+ Rtt map[int32]int32 `protobuf:"bytes,1,rep,name=rtt" json:"rtt,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
+}
+
+func (m *IntMap) Reset() { *m = IntMap{} }
+func (m *IntMap) String() string { return proto.CompactTextString(m) }
+func (*IntMap) ProtoMessage() {}
+func (*IntMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+func (m *IntMap) GetRtt() map[int32]int32 {
+ if m != nil {
+ return m.Rtt
+ }
+ return nil
+}
+
+type IntMaps struct {
+ Maps []*IntMap `protobuf:"bytes,1,rep,name=maps" json:"maps,omitempty"`
+}
+
+func (m *IntMaps) Reset() { *m = IntMaps{} }
+func (m *IntMaps) String() string { return proto.CompactTextString(m) }
+func (*IntMaps) ProtoMessage() {}
+func (*IntMaps) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *IntMaps) GetMaps() []*IntMap {
+ if m != nil {
+ return m.Maps
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Message)(nil), "proto3_proto.Message")
+ proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
+ proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
+ proto.RegisterType((*IntMap)(nil), "proto3_proto.IntMap")
+ proto.RegisterType((*IntMaps)(nil), "proto3_proto.IntMaps")
+ proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
+}
+
+func init() { proto.RegisterFile("proto3_proto/proto3.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 733 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x53, 0x6d, 0x6f, 0xf3, 0x34,
+ 0x14, 0x25, 0x4d, 0x5f, 0xd2, 0x9b, 0x74, 0x0b, 0x5e, 0x91, 0xbc, 0x02, 0x52, 0x28, 0x12, 0x8a,
+ 0x78, 0x49, 0xa1, 0xd3, 0xd0, 0x84, 0x10, 0x68, 0x1b, 0x9b, 0xa8, 0xd6, 0x95, 0xca, 0xdd, 0x98,
+ 0xf8, 0x14, 0xa5, 0xad, 0xdb, 0x46, 0x34, 0x4e, 0x49, 0x1c, 0xa4, 0xfc, 0x1d, 0xfe, 0x28, 0x8f,
+ 0x6c, 0xa7, 0x5d, 0x36, 0x65, 0xcf, 0xf3, 0x29, 0xf6, 0xf1, 0xb9, 0xf7, 0x9c, 0x1c, 0x5f, 0xc3,
+ 0xe9, 0x2e, 0x89, 0x79, 0x7c, 0xe6, 0xcb, 0xcf, 0x40, 0x6d, 0x3c, 0xf9, 0x41, 0x56, 0xf9, 0xa8,
+ 0x77, 0xba, 0x8e, 0xe3, 0xf5, 0x96, 0x2a, 0xca, 0x3c, 0x5b, 0x0d, 0x02, 0x96, 0x2b, 0x62, 0xef,
+ 0x84, 0xd3, 0x94, 0x2f, 0x03, 0x1e, 0x0c, 0xc4, 0x42, 0x81, 0xfd, 0xff, 0x5b, 0xd0, 0xba, 0xa7,
+ 0x69, 0x1a, 0xac, 0x29, 0x42, 0x50, 0x67, 0x41, 0x44, 0xb1, 0xe6, 0x68, 0x6e, 0x9b, 0xc8, 0x35,
+ 0xba, 0x00, 0x63, 0x13, 0x6e, 0x83, 0x24, 0xe4, 0x39, 0xae, 0x39, 0x9a, 0x7b, 0x34, 0xfc, 0xcc,
+ 0x2b, 0x0b, 0x7a, 0x45, 0xb1, 0xf7, 0x7b, 0x16, 0xc5, 0x59, 0x42, 0x0e, 0x6c, 0xe4, 0x80, 0xb5,
+ 0xa1, 0xe1, 0x7a, 0xc3, 0xfd, 0x90, 0xf9, 0x8b, 0x08, 0xeb, 0x8e, 0xe6, 0x76, 0x08, 0x28, 0x6c,
+ 0xc4, 0xae, 0x23, 0xa1, 0x27, 0xec, 0xe0, 0xba, 0xa3, 0xb9, 0x16, 0x91, 0x6b, 0xf4, 0x05, 0x58,
+ 0x09, 0x4d, 0xb3, 0x2d, 0xf7, 0x17, 0x71, 0xc6, 0x38, 0x6e, 0x39, 0x9a, 0xab, 0x13, 0x53, 0x61,
+ 0xd7, 0x02, 0x42, 0x5f, 0x42, 0x87, 0x27, 0x19, 0xf5, 0xd3, 0x45, 0xcc, 0xd3, 0x28, 0x60, 0xd8,
+ 0x70, 0x34, 0xd7, 0x20, 0x96, 0x00, 0x67, 0x05, 0x86, 0xba, 0xd0, 0x48, 0x17, 0x71, 0x42, 0x71,
+ 0xdb, 0xd1, 0xdc, 0x1a, 0x51, 0x1b, 0x64, 0x83, 0xfe, 0x37, 0xcd, 0x71, 0xc3, 0xd1, 0xdd, 0x3a,
+ 0x11, 0x4b, 0xf4, 0x29, 0xb4, 0xd3, 0x4d, 0x9c, 0x70, 0x5f, 0xe0, 0x27, 0x8e, 0xee, 0x36, 0x88,
+ 0x21, 0x81, 0x3b, 0x9a, 0xa3, 0x6f, 0xa1, 0xc9, 0x68, 0xca, 0xe9, 0x12, 0x37, 0x1d, 0xcd, 0x35,
+ 0x87, 0xdd, 0x97, 0xbf, 0x3e, 0x91, 0x67, 0xa4, 0xe0, 0xa0, 0x73, 0x68, 0x25, 0xfe, 0x2a, 0x63,
+ 0x2c, 0xc7, 0xb6, 0xa3, 0x7f, 0x30, 0xa9, 0x66, 0x72, 0x2b, 0xb8, 0xe8, 0x67, 0x68, 0x71, 0x9a,
+ 0x24, 0x41, 0xc8, 0x30, 0x38, 0xba, 0x6b, 0x0e, 0xfb, 0xd5, 0x65, 0x0f, 0x8a, 0x74, 0xc3, 0x78,
+ 0x92, 0x93, 0x7d, 0x09, 0xba, 0x00, 0x75, 0xff, 0x43, 0x7f, 0x15, 0xd2, 0xed, 0x12, 0x9b, 0xd2,
+ 0xe8, 0x27, 0xde, 0xfe, 0xae, 0xbd, 0x59, 0x36, 0xff, 0x8d, 0xae, 0x82, 0x6c, 0xcb, 0x53, 0x62,
+ 0x2a, 0xea, 0xad, 0x60, 0xa2, 0xd1, 0xa1, 0xf2, 0xdf, 0x60, 0x9b, 0x51, 0xdc, 0x91, 0xe2, 0x5f,
+ 0x55, 0x8b, 0x4f, 0x25, 0xf3, 0x4f, 0x41, 0x54, 0x06, 0x8a, 0x56, 0x12, 0x41, 0xdf, 0x83, 0x11,
+ 0xb0, 0x9c, 0x6f, 0x42, 0xb6, 0xc6, 0x47, 0x45, 0x52, 0x6a, 0x0e, 0xbd, 0xfd, 0x1c, 0x7a, 0x97,
+ 0x2c, 0x27, 0x07, 0x16, 0x3a, 0x07, 0x33, 0x0a, 0x58, 0xee, 0xcb, 0x5d, 0x8a, 0x8f, 0xa5, 0x76,
+ 0x75, 0x11, 0x08, 0xe2, 0x83, 0xe4, 0xa1, 0x73, 0x80, 0x34, 0x9b, 0x47, 0xca, 0x14, 0xfe, 0xb8,
+ 0xf8, 0xd7, 0x2a, 0xc7, 0xa4, 0x44, 0x44, 0x3f, 0x80, 0xb1, 0xd8, 0x84, 0xdb, 0x65, 0x42, 0x19,
+ 0x46, 0x52, 0xea, 0x8d, 0xa2, 0x03, 0xad, 0x37, 0x05, 0xab, 0x1c, 0xf8, 0x7e, 0x72, 0xd4, 0xd3,
+ 0x90, 0x93, 0xf3, 0x35, 0x34, 0x54, 0x70, 0xb5, 0xf7, 0xcc, 0x86, 0xa2, 0xfc, 0x54, 0xbb, 0xd0,
+ 0x7a, 0x8f, 0x60, 0xbf, 0x4e, 0xb1, 0xa2, 0xeb, 0x37, 0x2f, 0xbb, 0xbe, 0x71, 0x91, 0xcf, 0x6d,
+ 0xfb, 0xbf, 0x42, 0x53, 0x0d, 0x14, 0x32, 0xa1, 0xf5, 0x38, 0xb9, 0x9b, 0xfc, 0xf1, 0x34, 0xb1,
+ 0x3f, 0x42, 0x06, 0xd4, 0xa7, 0x8f, 0x93, 0x99, 0xad, 0xa1, 0x0e, 0xb4, 0x67, 0xe3, 0xcb, 0xe9,
+ 0xec, 0x61, 0x74, 0x7d, 0x67, 0xd7, 0xd0, 0x31, 0x98, 0x57, 0xa3, 0xf1, 0xd8, 0xbf, 0xba, 0x1c,
+ 0x8d, 0x6f, 0xfe, 0xb2, 0xf5, 0xfe, 0x10, 0x9a, 0xca, 0xac, 0x78, 0x33, 0x73, 0x39, 0xbe, 0xca,
+ 0x8f, 0xda, 0x88, 0x57, 0xba, 0xc8, 0xb8, 0x32, 0x64, 0x10, 0xb9, 0xee, 0xff, 0xa7, 0xc1, 0x51,
+ 0x91, 0xd9, 0x53, 0xc8, 0x37, 0xf7, 0xc1, 0x0e, 0x4d, 0xc1, 0x9a, 0xe7, 0x9c, 0xfa, 0x51, 0xb0,
+ 0xdb, 0x89, 0x39, 0xd0, 0x64, 0xce, 0xdf, 0x55, 0xe6, 0x5c, 0xd4, 0x78, 0x57, 0x39, 0xa7, 0xf7,
+ 0x8a, 0x5f, 0x4c, 0xd5, 0xfc, 0x19, 0xe9, 0xfd, 0x02, 0xf6, 0x6b, 0x42, 0x39, 0x30, 0x43, 0x05,
+ 0xd6, 0x2d, 0x07, 0x66, 0x95, 0x93, 0xf9, 0x07, 0x9a, 0x23, 0xc6, 0x85, 0xb7, 0x01, 0xe8, 0x09,
+ 0xe7, 0x85, 0xa5, 0xcf, 0x5f, 0x5a, 0x52, 0x14, 0x8f, 0x70, 0xae, 0x2c, 0x08, 0x66, 0xef, 0x47,
+ 0x30, 0xf6, 0x40, 0x59, 0xb2, 0x51, 0x21, 0xd9, 0x28, 0x4b, 0x9e, 0x41, 0x4b, 0xf5, 0x4b, 0x91,
+ 0x0b, 0xf5, 0x28, 0xd8, 0xa5, 0x85, 0x68, 0xb7, 0x4a, 0x94, 0x48, 0xc6, 0xbc, 0xa9, 0x8e, 0xde,
+ 0x05, 0x00, 0x00, 0xff, 0xff, 0x75, 0x38, 0xad, 0x84, 0xe4, 0x05, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
new file mode 100644
index 0000000..2048655
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
@@ -0,0 +1,87 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2014 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+import "google/protobuf/any.proto";
+import "testdata/test.proto";
+
+package proto3_proto;
+
+message Message {
+ enum Humour {
+ UNKNOWN = 0;
+ PUNS = 1;
+ SLAPSTICK = 2;
+ BILL_BAILEY = 3;
+ }
+
+ string name = 1;
+ Humour hilarity = 2;
+ uint32 height_in_cm = 3;
+ bytes data = 4;
+ int64 result_count = 7;
+ bool true_scotsman = 8;
+ float score = 9;
+
+ repeated uint64 key = 5;
+ repeated int32 short_key = 19;
+ Nested nested = 6;
+ repeated Humour r_funny = 16;
+
+ map terrain = 10;
+ testdata.SubDefaults proto2_field = 11;
+ map proto2_value = 13;
+
+ google.protobuf.Any anything = 14;
+ repeated google.protobuf.Any many_things = 15;
+
+ Message submessage = 17;
+ repeated Message children = 18;
+}
+
+message Nested {
+ string bunny = 1;
+ bool cute = 2;
+}
+
+message MessageWithMap {
+ map byte_mapping = 1;
+}
+
+
+message IntMap {
+ map rtt = 1;
+}
+
+message IntMaps {
+ repeated IntMap maps = 1;
+}
diff --git a/vendor/github.com/golang/protobuf/proto/testdata/Makefile b/vendor/github.com/golang/protobuf/proto/testdata/Makefile
new file mode 100644
index 0000000..fc28862
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/testdata/Makefile
@@ -0,0 +1,50 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+include ../../Make.protobuf
+
+all: regenerate
+
+regenerate:
+ rm -f test.pb.go
+ make test.pb.go
+
+# The following rules are just aids to development. Not needed for typical testing.
+
+diff: regenerate
+ git diff test.pb.go
+
+restore:
+ cp test.pb.go.golden test.pb.go
+
+preserve:
+ cp test.pb.go test.pb.go.golden
diff --git a/vendor/github.com/golang/protobuf/proto/testdata/test.pb.go b/vendor/github.com/golang/protobuf/proto/testdata/test.pb.go
new file mode 100644
index 0000000..e980d1a
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/testdata/test.pb.go
@@ -0,0 +1,4147 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test.proto
+
+/*
+Package testdata is a generated protocol buffer package.
+
+It is generated from these files:
+ test.proto
+
+It has these top-level messages:
+ GoEnum
+ GoTestField
+ GoTest
+ GoTestRequiredGroupField
+ GoSkipTest
+ NonPackedTest
+ PackedTest
+ MaxTag
+ OldMessage
+ NewMessage
+ InnerMessage
+ OtherMessage
+ RequiredInnerMessage
+ MyMessage
+ Ext
+ ComplexExtension
+ DefaultsMessage
+ MyMessageSet
+ Empty
+ MessageList
+ Strings
+ Defaults
+ SubDefaults
+ RepeatedEnum
+ MoreRepeated
+ GroupOld
+ GroupNew
+ FloatingPoint
+ MessageWithMap
+ Oneof
+ Communique
+*/
+package testdata
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type FOO int32
+
+const (
+ FOO_FOO1 FOO = 1
+)
+
+var FOO_name = map[int32]string{
+ 1: "FOO1",
+}
+var FOO_value = map[string]int32{
+ "FOO1": 1,
+}
+
+func (x FOO) Enum() *FOO {
+ p := new(FOO)
+ *p = x
+ return p
+}
+func (x FOO) String() string {
+ return proto.EnumName(FOO_name, int32(x))
+}
+func (x *FOO) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO")
+ if err != nil {
+ return err
+ }
+ *x = FOO(value)
+ return nil
+}
+func (FOO) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+// An enum, for completeness.
+type GoTest_KIND int32
+
+const (
+ GoTest_VOID GoTest_KIND = 0
+ // Basic types
+ GoTest_BOOL GoTest_KIND = 1
+ GoTest_BYTES GoTest_KIND = 2
+ GoTest_FINGERPRINT GoTest_KIND = 3
+ GoTest_FLOAT GoTest_KIND = 4
+ GoTest_INT GoTest_KIND = 5
+ GoTest_STRING GoTest_KIND = 6
+ GoTest_TIME GoTest_KIND = 7
+ // Groupings
+ GoTest_TUPLE GoTest_KIND = 8
+ GoTest_ARRAY GoTest_KIND = 9
+ GoTest_MAP GoTest_KIND = 10
+ // Table types
+ GoTest_TABLE GoTest_KIND = 11
+ // Functions
+ GoTest_FUNCTION GoTest_KIND = 12
+)
+
+var GoTest_KIND_name = map[int32]string{
+ 0: "VOID",
+ 1: "BOOL",
+ 2: "BYTES",
+ 3: "FINGERPRINT",
+ 4: "FLOAT",
+ 5: "INT",
+ 6: "STRING",
+ 7: "TIME",
+ 8: "TUPLE",
+ 9: "ARRAY",
+ 10: "MAP",
+ 11: "TABLE",
+ 12: "FUNCTION",
+}
+var GoTest_KIND_value = map[string]int32{
+ "VOID": 0,
+ "BOOL": 1,
+ "BYTES": 2,
+ "FINGERPRINT": 3,
+ "FLOAT": 4,
+ "INT": 5,
+ "STRING": 6,
+ "TIME": 7,
+ "TUPLE": 8,
+ "ARRAY": 9,
+ "MAP": 10,
+ "TABLE": 11,
+ "FUNCTION": 12,
+}
+
+func (x GoTest_KIND) Enum() *GoTest_KIND {
+ p := new(GoTest_KIND)
+ *p = x
+ return p
+}
+func (x GoTest_KIND) String() string {
+ return proto.EnumName(GoTest_KIND_name, int32(x))
+}
+func (x *GoTest_KIND) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(GoTest_KIND_value, data, "GoTest_KIND")
+ if err != nil {
+ return err
+ }
+ *x = GoTest_KIND(value)
+ return nil
+}
+func (GoTest_KIND) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} }
+
+type MyMessage_Color int32
+
+const (
+ MyMessage_RED MyMessage_Color = 0
+ MyMessage_GREEN MyMessage_Color = 1
+ MyMessage_BLUE MyMessage_Color = 2
+)
+
+var MyMessage_Color_name = map[int32]string{
+ 0: "RED",
+ 1: "GREEN",
+ 2: "BLUE",
+}
+var MyMessage_Color_value = map[string]int32{
+ "RED": 0,
+ "GREEN": 1,
+ "BLUE": 2,
+}
+
+func (x MyMessage_Color) Enum() *MyMessage_Color {
+ p := new(MyMessage_Color)
+ *p = x
+ return p
+}
+func (x MyMessage_Color) String() string {
+ return proto.EnumName(MyMessage_Color_name, int32(x))
+}
+func (x *MyMessage_Color) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MyMessage_Color_value, data, "MyMessage_Color")
+ if err != nil {
+ return err
+ }
+ *x = MyMessage_Color(value)
+ return nil
+}
+func (MyMessage_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{13, 0} }
+
+type DefaultsMessage_DefaultsEnum int32
+
+const (
+ DefaultsMessage_ZERO DefaultsMessage_DefaultsEnum = 0
+ DefaultsMessage_ONE DefaultsMessage_DefaultsEnum = 1
+ DefaultsMessage_TWO DefaultsMessage_DefaultsEnum = 2
+)
+
+var DefaultsMessage_DefaultsEnum_name = map[int32]string{
+ 0: "ZERO",
+ 1: "ONE",
+ 2: "TWO",
+}
+var DefaultsMessage_DefaultsEnum_value = map[string]int32{
+ "ZERO": 0,
+ "ONE": 1,
+ "TWO": 2,
+}
+
+func (x DefaultsMessage_DefaultsEnum) Enum() *DefaultsMessage_DefaultsEnum {
+ p := new(DefaultsMessage_DefaultsEnum)
+ *p = x
+ return p
+}
+func (x DefaultsMessage_DefaultsEnum) String() string {
+ return proto.EnumName(DefaultsMessage_DefaultsEnum_name, int32(x))
+}
+func (x *DefaultsMessage_DefaultsEnum) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(DefaultsMessage_DefaultsEnum_value, data, "DefaultsMessage_DefaultsEnum")
+ if err != nil {
+ return err
+ }
+ *x = DefaultsMessage_DefaultsEnum(value)
+ return nil
+}
+func (DefaultsMessage_DefaultsEnum) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{16, 0}
+}
+
+type Defaults_Color int32
+
+const (
+ Defaults_RED Defaults_Color = 0
+ Defaults_GREEN Defaults_Color = 1
+ Defaults_BLUE Defaults_Color = 2
+)
+
+var Defaults_Color_name = map[int32]string{
+ 0: "RED",
+ 1: "GREEN",
+ 2: "BLUE",
+}
+var Defaults_Color_value = map[string]int32{
+ "RED": 0,
+ "GREEN": 1,
+ "BLUE": 2,
+}
+
+func (x Defaults_Color) Enum() *Defaults_Color {
+ p := new(Defaults_Color)
+ *p = x
+ return p
+}
+func (x Defaults_Color) String() string {
+ return proto.EnumName(Defaults_Color_name, int32(x))
+}
+func (x *Defaults_Color) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(Defaults_Color_value, data, "Defaults_Color")
+ if err != nil {
+ return err
+ }
+ *x = Defaults_Color(value)
+ return nil
+}
+func (Defaults_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{21, 0} }
+
+type RepeatedEnum_Color int32
+
+const (
+ RepeatedEnum_RED RepeatedEnum_Color = 1
+)
+
+var RepeatedEnum_Color_name = map[int32]string{
+ 1: "RED",
+}
+var RepeatedEnum_Color_value = map[string]int32{
+ "RED": 1,
+}
+
+func (x RepeatedEnum_Color) Enum() *RepeatedEnum_Color {
+ p := new(RepeatedEnum_Color)
+ *p = x
+ return p
+}
+func (x RepeatedEnum_Color) String() string {
+ return proto.EnumName(RepeatedEnum_Color_name, int32(x))
+}
+func (x *RepeatedEnum_Color) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(RepeatedEnum_Color_value, data, "RepeatedEnum_Color")
+ if err != nil {
+ return err
+ }
+ *x = RepeatedEnum_Color(value)
+ return nil
+}
+func (RepeatedEnum_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{23, 0} }
+
+type GoEnum struct {
+ Foo *FOO `protobuf:"varint,1,req,name=foo,enum=testdata.FOO" json:"foo,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoEnum) Reset() { *m = GoEnum{} }
+func (m *GoEnum) String() string { return proto.CompactTextString(m) }
+func (*GoEnum) ProtoMessage() {}
+func (*GoEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func (m *GoEnum) GetFoo() FOO {
+ if m != nil && m.Foo != nil {
+ return *m.Foo
+ }
+ return FOO_FOO1
+}
+
+type GoTestField struct {
+ Label *string `protobuf:"bytes,1,req,name=Label" json:"Label,omitempty"`
+ Type *string `protobuf:"bytes,2,req,name=Type" json:"Type,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoTestField) Reset() { *m = GoTestField{} }
+func (m *GoTestField) String() string { return proto.CompactTextString(m) }
+func (*GoTestField) ProtoMessage() {}
+func (*GoTestField) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+func (m *GoTestField) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+}
+
+func (m *GoTestField) GetType() string {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return ""
+}
+
+type GoTest struct {
+ // Some typical parameters
+ Kind *GoTest_KIND `protobuf:"varint,1,req,name=Kind,enum=testdata.GoTest_KIND" json:"Kind,omitempty"`
+ Table *string `protobuf:"bytes,2,opt,name=Table" json:"Table,omitempty"`
+ Param *int32 `protobuf:"varint,3,opt,name=Param" json:"Param,omitempty"`
+ // Required, repeated and optional foreign fields.
+ RequiredField *GoTestField `protobuf:"bytes,4,req,name=RequiredField" json:"RequiredField,omitempty"`
+ RepeatedField []*GoTestField `protobuf:"bytes,5,rep,name=RepeatedField" json:"RepeatedField,omitempty"`
+ OptionalField *GoTestField `protobuf:"bytes,6,opt,name=OptionalField" json:"OptionalField,omitempty"`
+ // Required fields of all basic types
+ F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required,json=FBoolRequired" json:"F_Bool_required,omitempty"`
+ F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required,json=FInt32Required" json:"F_Int32_required,omitempty"`
+ F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required,json=FInt64Required" json:"F_Int64_required,omitempty"`
+ F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required,json=FFixed32Required" json:"F_Fixed32_required,omitempty"`
+ F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required,json=FFixed64Required" json:"F_Fixed64_required,omitempty"`
+ F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required,json=FUint32Required" json:"F_Uint32_required,omitempty"`
+ F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required,json=FUint64Required" json:"F_Uint64_required,omitempty"`
+ F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required,json=FFloatRequired" json:"F_Float_required,omitempty"`
+ F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required,json=FDoubleRequired" json:"F_Double_required,omitempty"`
+ F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required,json=FStringRequired" json:"F_String_required,omitempty"`
+ F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required,json=FBytesRequired" json:"F_Bytes_required,omitempty"`
+ F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required,json=FSint32Required" json:"F_Sint32_required,omitempty"`
+ F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required,json=FSint64Required" json:"F_Sint64_required,omitempty"`
+ // Repeated fields of all basic types
+ F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated,json=FBoolRepeated" json:"F_Bool_repeated,omitempty"`
+ F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated,json=FInt32Repeated" json:"F_Int32_repeated,omitempty"`
+ F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated,json=FInt64Repeated" json:"F_Int64_repeated,omitempty"`
+ F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated,json=FFixed32Repeated" json:"F_Fixed32_repeated,omitempty"`
+ F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated,json=FFixed64Repeated" json:"F_Fixed64_repeated,omitempty"`
+ F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated,json=FUint32Repeated" json:"F_Uint32_repeated,omitempty"`
+ F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated,json=FUint64Repeated" json:"F_Uint64_repeated,omitempty"`
+ F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated,json=FFloatRepeated" json:"F_Float_repeated,omitempty"`
+ F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated,json=FDoubleRepeated" json:"F_Double_repeated,omitempty"`
+ F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated,json=FStringRepeated" json:"F_String_repeated,omitempty"`
+ F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated,json=FBytesRepeated" json:"F_Bytes_repeated,omitempty"`
+ F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated,json=FSint32Repeated" json:"F_Sint32_repeated,omitempty"`
+ F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated,json=FSint64Repeated" json:"F_Sint64_repeated,omitempty"`
+ // Optional fields of all basic types
+ F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional,json=FBoolOptional" json:"F_Bool_optional,omitempty"`
+ F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional,json=FInt32Optional" json:"F_Int32_optional,omitempty"`
+ F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional,json=FInt64Optional" json:"F_Int64_optional,omitempty"`
+ F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional,json=FFixed32Optional" json:"F_Fixed32_optional,omitempty"`
+ F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional,json=FFixed64Optional" json:"F_Fixed64_optional,omitempty"`
+ F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional,json=FUint32Optional" json:"F_Uint32_optional,omitempty"`
+ F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional,json=FUint64Optional" json:"F_Uint64_optional,omitempty"`
+ F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional,json=FFloatOptional" json:"F_Float_optional,omitempty"`
+ F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional,json=FDoubleOptional" json:"F_Double_optional,omitempty"`
+ F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional,json=FStringOptional" json:"F_String_optional,omitempty"`
+ F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional,json=FBytesOptional" json:"F_Bytes_optional,omitempty"`
+ F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional,json=FSint32Optional" json:"F_Sint32_optional,omitempty"`
+ F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional,json=FSint64Optional" json:"F_Sint64_optional,omitempty"`
+ // Default-valued fields of all basic types
+ F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,json=FBoolDefaulted,def=1" json:"F_Bool_defaulted,omitempty"`
+ F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,json=FInt32Defaulted,def=32" json:"F_Int32_defaulted,omitempty"`
+ F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,json=FInt64Defaulted,def=64" json:"F_Int64_defaulted,omitempty"`
+ F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,json=FFixed32Defaulted,def=320" json:"F_Fixed32_defaulted,omitempty"`
+ F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,json=FFixed64Defaulted,def=640" json:"F_Fixed64_defaulted,omitempty"`
+ F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,json=FUint32Defaulted,def=3200" json:"F_Uint32_defaulted,omitempty"`
+ F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,json=FUint64Defaulted,def=6400" json:"F_Uint64_defaulted,omitempty"`
+ F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,json=FFloatDefaulted,def=314159" json:"F_Float_defaulted,omitempty"`
+ F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,json=FDoubleDefaulted,def=271828" json:"F_Double_defaulted,omitempty"`
+ F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,json=FStringDefaulted,def=hello, \"world!\"\n" json:"F_String_defaulted,omitempty"`
+ F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,json=FBytesDefaulted,def=Bignose" json:"F_Bytes_defaulted,omitempty"`
+ F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,json=FSint32Defaulted,def=-32" json:"F_Sint32_defaulted,omitempty"`
+ F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,json=FSint64Defaulted,def=-64" json:"F_Sint64_defaulted,omitempty"`
+ // Packed repeated fields (no string or bytes).
+ F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed,json=FBoolRepeatedPacked" json:"F_Bool_repeated_packed,omitempty"`
+ F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed,json=FInt32RepeatedPacked" json:"F_Int32_repeated_packed,omitempty"`
+ F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed,json=FInt64RepeatedPacked" json:"F_Int64_repeated_packed,omitempty"`
+ F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed,json=FFixed32RepeatedPacked" json:"F_Fixed32_repeated_packed,omitempty"`
+ F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed,json=FFixed64RepeatedPacked" json:"F_Fixed64_repeated_packed,omitempty"`
+ F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed,json=FUint32RepeatedPacked" json:"F_Uint32_repeated_packed,omitempty"`
+ F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed,json=FUint64RepeatedPacked" json:"F_Uint64_repeated_packed,omitempty"`
+ F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed,json=FFloatRepeatedPacked" json:"F_Float_repeated_packed,omitempty"`
+ F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed,json=FDoubleRepeatedPacked" json:"F_Double_repeated_packed,omitempty"`
+ F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed,json=FSint32RepeatedPacked" json:"F_Sint32_repeated_packed,omitempty"`
+ F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed,json=FSint64RepeatedPacked" json:"F_Sint64_repeated_packed,omitempty"`
+ Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup,json=requiredgroup" json:"requiredgroup,omitempty"`
+ Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup,json=repeatedgroup" json:"repeatedgroup,omitempty"`
+ Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup,json=optionalgroup" json:"optionalgroup,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoTest) Reset() { *m = GoTest{} }
+func (m *GoTest) String() string { return proto.CompactTextString(m) }
+func (*GoTest) ProtoMessage() {}
+func (*GoTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+const Default_GoTest_F_BoolDefaulted bool = true
+const Default_GoTest_F_Int32Defaulted int32 = 32
+const Default_GoTest_F_Int64Defaulted int64 = 64
+const Default_GoTest_F_Fixed32Defaulted uint32 = 320
+const Default_GoTest_F_Fixed64Defaulted uint64 = 640
+const Default_GoTest_F_Uint32Defaulted uint32 = 3200
+const Default_GoTest_F_Uint64Defaulted uint64 = 6400
+const Default_GoTest_F_FloatDefaulted float32 = 314159
+const Default_GoTest_F_DoubleDefaulted float64 = 271828
+const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n"
+
+var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose")
+
+const Default_GoTest_F_Sint32Defaulted int32 = -32
+const Default_GoTest_F_Sint64Defaulted int64 = -64
+
+func (m *GoTest) GetKind() GoTest_KIND {
+ if m != nil && m.Kind != nil {
+ return *m.Kind
+ }
+ return GoTest_VOID
+}
+
+func (m *GoTest) GetTable() string {
+ if m != nil && m.Table != nil {
+ return *m.Table
+ }
+ return ""
+}
+
+func (m *GoTest) GetParam() int32 {
+ if m != nil && m.Param != nil {
+ return *m.Param
+ }
+ return 0
+}
+
+func (m *GoTest) GetRequiredField() *GoTestField {
+ if m != nil {
+ return m.RequiredField
+ }
+ return nil
+}
+
+func (m *GoTest) GetRepeatedField() []*GoTestField {
+ if m != nil {
+ return m.RepeatedField
+ }
+ return nil
+}
+
+func (m *GoTest) GetOptionalField() *GoTestField {
+ if m != nil {
+ return m.OptionalField
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_BoolRequired() bool {
+ if m != nil && m.F_BoolRequired != nil {
+ return *m.F_BoolRequired
+ }
+ return false
+}
+
+func (m *GoTest) GetF_Int32Required() int32 {
+ if m != nil && m.F_Int32Required != nil {
+ return *m.F_Int32Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Int64Required() int64 {
+ if m != nil && m.F_Int64Required != nil {
+ return *m.F_Int64Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Fixed32Required() uint32 {
+ if m != nil && m.F_Fixed32Required != nil {
+ return *m.F_Fixed32Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Fixed64Required() uint64 {
+ if m != nil && m.F_Fixed64Required != nil {
+ return *m.F_Fixed64Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Uint32Required() uint32 {
+ if m != nil && m.F_Uint32Required != nil {
+ return *m.F_Uint32Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Uint64Required() uint64 {
+ if m != nil && m.F_Uint64Required != nil {
+ return *m.F_Uint64Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_FloatRequired() float32 {
+ if m != nil && m.F_FloatRequired != nil {
+ return *m.F_FloatRequired
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_DoubleRequired() float64 {
+ if m != nil && m.F_DoubleRequired != nil {
+ return *m.F_DoubleRequired
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_StringRequired() string {
+ if m != nil && m.F_StringRequired != nil {
+ return *m.F_StringRequired
+ }
+ return ""
+}
+
+func (m *GoTest) GetF_BytesRequired() []byte {
+ if m != nil {
+ return m.F_BytesRequired
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Sint32Required() int32 {
+ if m != nil && m.F_Sint32Required != nil {
+ return *m.F_Sint32Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Sint64Required() int64 {
+ if m != nil && m.F_Sint64Required != nil {
+ return *m.F_Sint64Required
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_BoolRepeated() []bool {
+ if m != nil {
+ return m.F_BoolRepeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Int32Repeated() []int32 {
+ if m != nil {
+ return m.F_Int32Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Int64Repeated() []int64 {
+ if m != nil {
+ return m.F_Int64Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Fixed32Repeated() []uint32 {
+ if m != nil {
+ return m.F_Fixed32Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Fixed64Repeated() []uint64 {
+ if m != nil {
+ return m.F_Fixed64Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Uint32Repeated() []uint32 {
+ if m != nil {
+ return m.F_Uint32Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Uint64Repeated() []uint64 {
+ if m != nil {
+ return m.F_Uint64Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_FloatRepeated() []float32 {
+ if m != nil {
+ return m.F_FloatRepeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_DoubleRepeated() []float64 {
+ if m != nil {
+ return m.F_DoubleRepeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_StringRepeated() []string {
+ if m != nil {
+ return m.F_StringRepeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_BytesRepeated() [][]byte {
+ if m != nil {
+ return m.F_BytesRepeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Sint32Repeated() []int32 {
+ if m != nil {
+ return m.F_Sint32Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Sint64Repeated() []int64 {
+ if m != nil {
+ return m.F_Sint64Repeated
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_BoolOptional() bool {
+ if m != nil && m.F_BoolOptional != nil {
+ return *m.F_BoolOptional
+ }
+ return false
+}
+
+func (m *GoTest) GetF_Int32Optional() int32 {
+ if m != nil && m.F_Int32Optional != nil {
+ return *m.F_Int32Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Int64Optional() int64 {
+ if m != nil && m.F_Int64Optional != nil {
+ return *m.F_Int64Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Fixed32Optional() uint32 {
+ if m != nil && m.F_Fixed32Optional != nil {
+ return *m.F_Fixed32Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Fixed64Optional() uint64 {
+ if m != nil && m.F_Fixed64Optional != nil {
+ return *m.F_Fixed64Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Uint32Optional() uint32 {
+ if m != nil && m.F_Uint32Optional != nil {
+ return *m.F_Uint32Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Uint64Optional() uint64 {
+ if m != nil && m.F_Uint64Optional != nil {
+ return *m.F_Uint64Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_FloatOptional() float32 {
+ if m != nil && m.F_FloatOptional != nil {
+ return *m.F_FloatOptional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_DoubleOptional() float64 {
+ if m != nil && m.F_DoubleOptional != nil {
+ return *m.F_DoubleOptional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_StringOptional() string {
+ if m != nil && m.F_StringOptional != nil {
+ return *m.F_StringOptional
+ }
+ return ""
+}
+
+func (m *GoTest) GetF_BytesOptional() []byte {
+ if m != nil {
+ return m.F_BytesOptional
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Sint32Optional() int32 {
+ if m != nil && m.F_Sint32Optional != nil {
+ return *m.F_Sint32Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_Sint64Optional() int64 {
+ if m != nil && m.F_Sint64Optional != nil {
+ return *m.F_Sint64Optional
+ }
+ return 0
+}
+
+func (m *GoTest) GetF_BoolDefaulted() bool {
+ if m != nil && m.F_BoolDefaulted != nil {
+ return *m.F_BoolDefaulted
+ }
+ return Default_GoTest_F_BoolDefaulted
+}
+
+func (m *GoTest) GetF_Int32Defaulted() int32 {
+ if m != nil && m.F_Int32Defaulted != nil {
+ return *m.F_Int32Defaulted
+ }
+ return Default_GoTest_F_Int32Defaulted
+}
+
+func (m *GoTest) GetF_Int64Defaulted() int64 {
+ if m != nil && m.F_Int64Defaulted != nil {
+ return *m.F_Int64Defaulted
+ }
+ return Default_GoTest_F_Int64Defaulted
+}
+
+func (m *GoTest) GetF_Fixed32Defaulted() uint32 {
+ if m != nil && m.F_Fixed32Defaulted != nil {
+ return *m.F_Fixed32Defaulted
+ }
+ return Default_GoTest_F_Fixed32Defaulted
+}
+
+func (m *GoTest) GetF_Fixed64Defaulted() uint64 {
+ if m != nil && m.F_Fixed64Defaulted != nil {
+ return *m.F_Fixed64Defaulted
+ }
+ return Default_GoTest_F_Fixed64Defaulted
+}
+
+func (m *GoTest) GetF_Uint32Defaulted() uint32 {
+ if m != nil && m.F_Uint32Defaulted != nil {
+ return *m.F_Uint32Defaulted
+ }
+ return Default_GoTest_F_Uint32Defaulted
+}
+
+func (m *GoTest) GetF_Uint64Defaulted() uint64 {
+ if m != nil && m.F_Uint64Defaulted != nil {
+ return *m.F_Uint64Defaulted
+ }
+ return Default_GoTest_F_Uint64Defaulted
+}
+
+func (m *GoTest) GetF_FloatDefaulted() float32 {
+ if m != nil && m.F_FloatDefaulted != nil {
+ return *m.F_FloatDefaulted
+ }
+ return Default_GoTest_F_FloatDefaulted
+}
+
+func (m *GoTest) GetF_DoubleDefaulted() float64 {
+ if m != nil && m.F_DoubleDefaulted != nil {
+ return *m.F_DoubleDefaulted
+ }
+ return Default_GoTest_F_DoubleDefaulted
+}
+
+func (m *GoTest) GetF_StringDefaulted() string {
+ if m != nil && m.F_StringDefaulted != nil {
+ return *m.F_StringDefaulted
+ }
+ return Default_GoTest_F_StringDefaulted
+}
+
+func (m *GoTest) GetF_BytesDefaulted() []byte {
+ if m != nil && m.F_BytesDefaulted != nil {
+ return m.F_BytesDefaulted
+ }
+ return append([]byte(nil), Default_GoTest_F_BytesDefaulted...)
+}
+
+func (m *GoTest) GetF_Sint32Defaulted() int32 {
+ if m != nil && m.F_Sint32Defaulted != nil {
+ return *m.F_Sint32Defaulted
+ }
+ return Default_GoTest_F_Sint32Defaulted
+}
+
+func (m *GoTest) GetF_Sint64Defaulted() int64 {
+ if m != nil && m.F_Sint64Defaulted != nil {
+ return *m.F_Sint64Defaulted
+ }
+ return Default_GoTest_F_Sint64Defaulted
+}
+
+func (m *GoTest) GetF_BoolRepeatedPacked() []bool {
+ if m != nil {
+ return m.F_BoolRepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Int32RepeatedPacked() []int32 {
+ if m != nil {
+ return m.F_Int32RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Int64RepeatedPacked() []int64 {
+ if m != nil {
+ return m.F_Int64RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Fixed32RepeatedPacked() []uint32 {
+ if m != nil {
+ return m.F_Fixed32RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Fixed64RepeatedPacked() []uint64 {
+ if m != nil {
+ return m.F_Fixed64RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Uint32RepeatedPacked() []uint32 {
+ if m != nil {
+ return m.F_Uint32RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Uint64RepeatedPacked() []uint64 {
+ if m != nil {
+ return m.F_Uint64RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_FloatRepeatedPacked() []float32 {
+ if m != nil {
+ return m.F_FloatRepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_DoubleRepeatedPacked() []float64 {
+ if m != nil {
+ return m.F_DoubleRepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Sint32RepeatedPacked() []int32 {
+ if m != nil {
+ return m.F_Sint32RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetF_Sint64RepeatedPacked() []int64 {
+ if m != nil {
+ return m.F_Sint64RepeatedPacked
+ }
+ return nil
+}
+
+func (m *GoTest) GetRequiredgroup() *GoTest_RequiredGroup {
+ if m != nil {
+ return m.Requiredgroup
+ }
+ return nil
+}
+
+func (m *GoTest) GetRepeatedgroup() []*GoTest_RepeatedGroup {
+ if m != nil {
+ return m.Repeatedgroup
+ }
+ return nil
+}
+
+func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup {
+ if m != nil {
+ return m.Optionalgroup
+ }
+ return nil
+}
+
+// Required, repeated, and optional groups.
+type GoTest_RequiredGroup struct {
+ RequiredField *string `protobuf:"bytes,71,req,name=RequiredField" json:"RequiredField,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoTest_RequiredGroup) Reset() { *m = GoTest_RequiredGroup{} }
+func (m *GoTest_RequiredGroup) String() string { return proto.CompactTextString(m) }
+func (*GoTest_RequiredGroup) ProtoMessage() {}
+func (*GoTest_RequiredGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} }
+
+func (m *GoTest_RequiredGroup) GetRequiredField() string {
+ if m != nil && m.RequiredField != nil {
+ return *m.RequiredField
+ }
+ return ""
+}
+
+type GoTest_RepeatedGroup struct {
+ RequiredField *string `protobuf:"bytes,81,req,name=RequiredField" json:"RequiredField,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoTest_RepeatedGroup) Reset() { *m = GoTest_RepeatedGroup{} }
+func (m *GoTest_RepeatedGroup) String() string { return proto.CompactTextString(m) }
+func (*GoTest_RepeatedGroup) ProtoMessage() {}
+func (*GoTest_RepeatedGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 1} }
+
+func (m *GoTest_RepeatedGroup) GetRequiredField() string {
+ if m != nil && m.RequiredField != nil {
+ return *m.RequiredField
+ }
+ return ""
+}
+
+type GoTest_OptionalGroup struct {
+ RequiredField *string `protobuf:"bytes,91,req,name=RequiredField" json:"RequiredField,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoTest_OptionalGroup) Reset() { *m = GoTest_OptionalGroup{} }
+func (m *GoTest_OptionalGroup) String() string { return proto.CompactTextString(m) }
+func (*GoTest_OptionalGroup) ProtoMessage() {}
+func (*GoTest_OptionalGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 2} }
+
+func (m *GoTest_OptionalGroup) GetRequiredField() string {
+ if m != nil && m.RequiredField != nil {
+ return *m.RequiredField
+ }
+ return ""
+}
+
+// For testing a group containing a required field.
+type GoTestRequiredGroupField struct {
+ Group *GoTestRequiredGroupField_Group `protobuf:"group,1,req,name=Group,json=group" json:"group,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoTestRequiredGroupField) Reset() { *m = GoTestRequiredGroupField{} }
+func (m *GoTestRequiredGroupField) String() string { return proto.CompactTextString(m) }
+func (*GoTestRequiredGroupField) ProtoMessage() {}
+func (*GoTestRequiredGroupField) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+func (m *GoTestRequiredGroupField) GetGroup() *GoTestRequiredGroupField_Group {
+ if m != nil {
+ return m.Group
+ }
+ return nil
+}
+
+type GoTestRequiredGroupField_Group struct {
+ Field *int32 `protobuf:"varint,2,req,name=Field" json:"Field,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoTestRequiredGroupField_Group) Reset() { *m = GoTestRequiredGroupField_Group{} }
+func (m *GoTestRequiredGroupField_Group) String() string { return proto.CompactTextString(m) }
+func (*GoTestRequiredGroupField_Group) ProtoMessage() {}
+func (*GoTestRequiredGroupField_Group) Descriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{3, 0}
+}
+
+func (m *GoTestRequiredGroupField_Group) GetField() int32 {
+ if m != nil && m.Field != nil {
+ return *m.Field
+ }
+ return 0
+}
+
+// For testing skipping of unrecognized fields.
+// Numbers are all big, larger than tag numbers in GoTestField,
+// the message used in the corresponding test.
+type GoSkipTest struct {
+ SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32,json=skipInt32" json:"skip_int32,omitempty"`
+ SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32,json=skipFixed32" json:"skip_fixed32,omitempty"`
+ SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64,json=skipFixed64" json:"skip_fixed64,omitempty"`
+ SkipString *string `protobuf:"bytes,14,req,name=skip_string,json=skipString" json:"skip_string,omitempty"`
+ Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup,json=skipgroup" json:"skipgroup,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoSkipTest) Reset() { *m = GoSkipTest{} }
+func (m *GoSkipTest) String() string { return proto.CompactTextString(m) }
+func (*GoSkipTest) ProtoMessage() {}
+func (*GoSkipTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *GoSkipTest) GetSkipInt32() int32 {
+ if m != nil && m.SkipInt32 != nil {
+ return *m.SkipInt32
+ }
+ return 0
+}
+
+func (m *GoSkipTest) GetSkipFixed32() uint32 {
+ if m != nil && m.SkipFixed32 != nil {
+ return *m.SkipFixed32
+ }
+ return 0
+}
+
+func (m *GoSkipTest) GetSkipFixed64() uint64 {
+ if m != nil && m.SkipFixed64 != nil {
+ return *m.SkipFixed64
+ }
+ return 0
+}
+
+func (m *GoSkipTest) GetSkipString() string {
+ if m != nil && m.SkipString != nil {
+ return *m.SkipString
+ }
+ return ""
+}
+
+func (m *GoSkipTest) GetSkipgroup() *GoSkipTest_SkipGroup {
+ if m != nil {
+ return m.Skipgroup
+ }
+ return nil
+}
+
+type GoSkipTest_SkipGroup struct {
+ GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32,json=groupInt32" json:"group_int32,omitempty"`
+ GroupString *string `protobuf:"bytes,17,req,name=group_string,json=groupString" json:"group_string,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GoSkipTest_SkipGroup) Reset() { *m = GoSkipTest_SkipGroup{} }
+func (m *GoSkipTest_SkipGroup) String() string { return proto.CompactTextString(m) }
+func (*GoSkipTest_SkipGroup) ProtoMessage() {}
+func (*GoSkipTest_SkipGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} }
+
+func (m *GoSkipTest_SkipGroup) GetGroupInt32() int32 {
+ if m != nil && m.GroupInt32 != nil {
+ return *m.GroupInt32
+ }
+ return 0
+}
+
+func (m *GoSkipTest_SkipGroup) GetGroupString() string {
+ if m != nil && m.GroupString != nil {
+ return *m.GroupString
+ }
+ return ""
+}
+
+// For testing packed/non-packed decoder switching.
+// A serialized instance of one should be deserializable as the other.
+type NonPackedTest struct {
+ A []int32 `protobuf:"varint,1,rep,name=a" json:"a,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *NonPackedTest) Reset() { *m = NonPackedTest{} }
+func (m *NonPackedTest) String() string { return proto.CompactTextString(m) }
+func (*NonPackedTest) ProtoMessage() {}
+func (*NonPackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+
+func (m *NonPackedTest) GetA() []int32 {
+ if m != nil {
+ return m.A
+ }
+ return nil
+}
+
+type PackedTest struct {
+ B []int32 `protobuf:"varint,1,rep,packed,name=b" json:"b,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *PackedTest) Reset() { *m = PackedTest{} }
+func (m *PackedTest) String() string { return proto.CompactTextString(m) }
+func (*PackedTest) ProtoMessage() {}
+func (*PackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+
+func (m *PackedTest) GetB() []int32 {
+ if m != nil {
+ return m.B
+ }
+ return nil
+}
+
+type MaxTag struct {
+ // Maximum possible tag number.
+ LastField *string `protobuf:"bytes,536870911,opt,name=last_field,json=lastField" json:"last_field,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MaxTag) Reset() { *m = MaxTag{} }
+func (m *MaxTag) String() string { return proto.CompactTextString(m) }
+func (*MaxTag) ProtoMessage() {}
+func (*MaxTag) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+
+func (m *MaxTag) GetLastField() string {
+ if m != nil && m.LastField != nil {
+ return *m.LastField
+ }
+ return ""
+}
+
+type OldMessage struct {
+ Nested *OldMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"`
+ Num *int32 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OldMessage) Reset() { *m = OldMessage{} }
+func (m *OldMessage) String() string { return proto.CompactTextString(m) }
+func (*OldMessage) ProtoMessage() {}
+func (*OldMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+
+func (m *OldMessage) GetNested() *OldMessage_Nested {
+ if m != nil {
+ return m.Nested
+ }
+ return nil
+}
+
+func (m *OldMessage) GetNum() int32 {
+ if m != nil && m.Num != nil {
+ return *m.Num
+ }
+ return 0
+}
+
+type OldMessage_Nested struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OldMessage_Nested) Reset() { *m = OldMessage_Nested{} }
+func (m *OldMessage_Nested) String() string { return proto.CompactTextString(m) }
+func (*OldMessage_Nested) ProtoMessage() {}
+func (*OldMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8, 0} }
+
+func (m *OldMessage_Nested) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+// NewMessage is wire compatible with OldMessage;
+// imagine it as a future version.
+type NewMessage struct {
+ Nested *NewMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"`
+ // This is an int32 in OldMessage.
+ Num *int64 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *NewMessage) Reset() { *m = NewMessage{} }
+func (m *NewMessage) String() string { return proto.CompactTextString(m) }
+func (*NewMessage) ProtoMessage() {}
+func (*NewMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+
+func (m *NewMessage) GetNested() *NewMessage_Nested {
+ if m != nil {
+ return m.Nested
+ }
+ return nil
+}
+
+func (m *NewMessage) GetNum() int64 {
+ if m != nil && m.Num != nil {
+ return *m.Num
+ }
+ return 0
+}
+
+type NewMessage_Nested struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ FoodGroup *string `protobuf:"bytes,2,opt,name=food_group,json=foodGroup" json:"food_group,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *NewMessage_Nested) Reset() { *m = NewMessage_Nested{} }
+func (m *NewMessage_Nested) String() string { return proto.CompactTextString(m) }
+func (*NewMessage_Nested) ProtoMessage() {}
+func (*NewMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 0} }
+
+func (m *NewMessage_Nested) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *NewMessage_Nested) GetFoodGroup() string {
+ if m != nil && m.FoodGroup != nil {
+ return *m.FoodGroup
+ }
+ return ""
+}
+
+type InnerMessage struct {
+ Host *string `protobuf:"bytes,1,req,name=host" json:"host,omitempty"`
+ Port *int32 `protobuf:"varint,2,opt,name=port,def=4000" json:"port,omitempty"`
+ Connected *bool `protobuf:"varint,3,opt,name=connected" json:"connected,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *InnerMessage) Reset() { *m = InnerMessage{} }
+func (m *InnerMessage) String() string { return proto.CompactTextString(m) }
+func (*InnerMessage) ProtoMessage() {}
+func (*InnerMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
+
+const Default_InnerMessage_Port int32 = 4000
+
+func (m *InnerMessage) GetHost() string {
+ if m != nil && m.Host != nil {
+ return *m.Host
+ }
+ return ""
+}
+
+func (m *InnerMessage) GetPort() int32 {
+ if m != nil && m.Port != nil {
+ return *m.Port
+ }
+ return Default_InnerMessage_Port
+}
+
+func (m *InnerMessage) GetConnected() bool {
+ if m != nil && m.Connected != nil {
+ return *m.Connected
+ }
+ return false
+}
+
+type OtherMessage struct {
+ Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"`
+ Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
+ Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"`
+ Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OtherMessage) Reset() { *m = OtherMessage{} }
+func (m *OtherMessage) String() string { return proto.CompactTextString(m) }
+func (*OtherMessage) ProtoMessage() {}
+func (*OtherMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
+
+var extRange_OtherMessage = []proto.ExtensionRange{
+ {100, 536870911},
+}
+
+func (*OtherMessage) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_OtherMessage
+}
+
+func (m *OtherMessage) GetKey() int64 {
+ if m != nil && m.Key != nil {
+ return *m.Key
+ }
+ return 0
+}
+
+func (m *OtherMessage) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (m *OtherMessage) GetWeight() float32 {
+ if m != nil && m.Weight != nil {
+ return *m.Weight
+ }
+ return 0
+}
+
+func (m *OtherMessage) GetInner() *InnerMessage {
+ if m != nil {
+ return m.Inner
+ }
+ return nil
+}
+
+type RequiredInnerMessage struct {
+ LeoFinallyWonAnOscar *InnerMessage `protobuf:"bytes,1,req,name=leo_finally_won_an_oscar,json=leoFinallyWonAnOscar" json:"leo_finally_won_an_oscar,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *RequiredInnerMessage) Reset() { *m = RequiredInnerMessage{} }
+func (m *RequiredInnerMessage) String() string { return proto.CompactTextString(m) }
+func (*RequiredInnerMessage) ProtoMessage() {}
+func (*RequiredInnerMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
+
+func (m *RequiredInnerMessage) GetLeoFinallyWonAnOscar() *InnerMessage {
+ if m != nil {
+ return m.LeoFinallyWonAnOscar
+ }
+ return nil
+}
+
+type MyMessage struct {
+ Count *int32 `protobuf:"varint,1,req,name=count" json:"count,omitempty"`
+ Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
+ Quote *string `protobuf:"bytes,3,opt,name=quote" json:"quote,omitempty"`
+ Pet []string `protobuf:"bytes,4,rep,name=pet" json:"pet,omitempty"`
+ Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner" json:"inner,omitempty"`
+ Others []*OtherMessage `protobuf:"bytes,6,rep,name=others" json:"others,omitempty"`
+ WeMustGoDeeper *RequiredInnerMessage `protobuf:"bytes,13,opt,name=we_must_go_deeper,json=weMustGoDeeper" json:"we_must_go_deeper,omitempty"`
+ RepInner []*InnerMessage `protobuf:"bytes,12,rep,name=rep_inner,json=repInner" json:"rep_inner,omitempty"`
+ Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"`
+ Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"`
+ // This field becomes [][]byte in the generated code.
+ RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes,json=repBytes" json:"rep_bytes,omitempty"`
+ Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MyMessage) Reset() { *m = MyMessage{} }
+func (m *MyMessage) String() string { return proto.CompactTextString(m) }
+func (*MyMessage) ProtoMessage() {}
+func (*MyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
+
+var extRange_MyMessage = []proto.ExtensionRange{
+ {100, 536870911},
+}
+
+func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MyMessage
+}
+
+func (m *MyMessage) GetCount() int32 {
+ if m != nil && m.Count != nil {
+ return *m.Count
+ }
+ return 0
+}
+
+func (m *MyMessage) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *MyMessage) GetQuote() string {
+ if m != nil && m.Quote != nil {
+ return *m.Quote
+ }
+ return ""
+}
+
+func (m *MyMessage) GetPet() []string {
+ if m != nil {
+ return m.Pet
+ }
+ return nil
+}
+
+func (m *MyMessage) GetInner() *InnerMessage {
+ if m != nil {
+ return m.Inner
+ }
+ return nil
+}
+
+func (m *MyMessage) GetOthers() []*OtherMessage {
+ if m != nil {
+ return m.Others
+ }
+ return nil
+}
+
+func (m *MyMessage) GetWeMustGoDeeper() *RequiredInnerMessage {
+ if m != nil {
+ return m.WeMustGoDeeper
+ }
+ return nil
+}
+
+func (m *MyMessage) GetRepInner() []*InnerMessage {
+ if m != nil {
+ return m.RepInner
+ }
+ return nil
+}
+
+func (m *MyMessage) GetBikeshed() MyMessage_Color {
+ if m != nil && m.Bikeshed != nil {
+ return *m.Bikeshed
+ }
+ return MyMessage_RED
+}
+
+func (m *MyMessage) GetSomegroup() *MyMessage_SomeGroup {
+ if m != nil {
+ return m.Somegroup
+ }
+ return nil
+}
+
+func (m *MyMessage) GetRepBytes() [][]byte {
+ if m != nil {
+ return m.RepBytes
+ }
+ return nil
+}
+
+func (m *MyMessage) GetBigfloat() float64 {
+ if m != nil && m.Bigfloat != nil {
+ return *m.Bigfloat
+ }
+ return 0
+}
+
+type MyMessage_SomeGroup struct {
+ GroupField *int32 `protobuf:"varint,9,opt,name=group_field,json=groupField" json:"group_field,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MyMessage_SomeGroup) Reset() { *m = MyMessage_SomeGroup{} }
+func (m *MyMessage_SomeGroup) String() string { return proto.CompactTextString(m) }
+func (*MyMessage_SomeGroup) ProtoMessage() {}
+func (*MyMessage_SomeGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13, 0} }
+
+func (m *MyMessage_SomeGroup) GetGroupField() int32 {
+ if m != nil && m.GroupField != nil {
+ return *m.GroupField
+ }
+ return 0
+}
+
+type Ext struct {
+ Data *string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Ext) Reset() { *m = Ext{} }
+func (m *Ext) String() string { return proto.CompactTextString(m) }
+func (*Ext) ProtoMessage() {}
+func (*Ext) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
+
+func (m *Ext) GetData() string {
+ if m != nil && m.Data != nil {
+ return *m.Data
+ }
+ return ""
+}
+
+var E_Ext_More = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessage)(nil),
+ ExtensionType: (*Ext)(nil),
+ Field: 103,
+ Name: "testdata.Ext.more",
+ Tag: "bytes,103,opt,name=more",
+ Filename: "test.proto",
+}
+
+var E_Ext_Text = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessage)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 104,
+ Name: "testdata.Ext.text",
+ Tag: "bytes,104,opt,name=text",
+ Filename: "test.proto",
+}
+
+var E_Ext_Number = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessage)(nil),
+ ExtensionType: (*int32)(nil),
+ Field: 105,
+ Name: "testdata.Ext.number",
+ Tag: "varint,105,opt,name=number",
+ Filename: "test.proto",
+}
+
+type ComplexExtension struct {
+ First *int32 `protobuf:"varint,1,opt,name=first" json:"first,omitempty"`
+ Second *int32 `protobuf:"varint,2,opt,name=second" json:"second,omitempty"`
+ Third []int32 `protobuf:"varint,3,rep,name=third" json:"third,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ComplexExtension) Reset() { *m = ComplexExtension{} }
+func (m *ComplexExtension) String() string { return proto.CompactTextString(m) }
+func (*ComplexExtension) ProtoMessage() {}
+func (*ComplexExtension) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
+
+func (m *ComplexExtension) GetFirst() int32 {
+ if m != nil && m.First != nil {
+ return *m.First
+ }
+ return 0
+}
+
+func (m *ComplexExtension) GetSecond() int32 {
+ if m != nil && m.Second != nil {
+ return *m.Second
+ }
+ return 0
+}
+
+func (m *ComplexExtension) GetThird() []int32 {
+ if m != nil {
+ return m.Third
+ }
+ return nil
+}
+
+type DefaultsMessage struct {
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DefaultsMessage) Reset() { *m = DefaultsMessage{} }
+func (m *DefaultsMessage) String() string { return proto.CompactTextString(m) }
+func (*DefaultsMessage) ProtoMessage() {}
+func (*DefaultsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
+
+var extRange_DefaultsMessage = []proto.ExtensionRange{
+ {100, 536870911},
+}
+
+func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_DefaultsMessage
+}
+
+type MyMessageSet struct {
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MyMessageSet) Reset() { *m = MyMessageSet{} }
+func (m *MyMessageSet) String() string { return proto.CompactTextString(m) }
+func (*MyMessageSet) ProtoMessage() {}
+func (*MyMessageSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
+
+func (m *MyMessageSet) Marshal() ([]byte, error) {
+ return proto.MarshalMessageSet(&m.XXX_InternalExtensions)
+}
+func (m *MyMessageSet) Unmarshal(buf []byte) error {
+ return proto.UnmarshalMessageSet(buf, &m.XXX_InternalExtensions)
+}
+func (m *MyMessageSet) MarshalJSON() ([]byte, error) {
+ return proto.MarshalMessageSetJSON(&m.XXX_InternalExtensions)
+}
+func (m *MyMessageSet) UnmarshalJSON(buf []byte) error {
+ return proto.UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions)
+}
+
+// ensure MyMessageSet satisfies proto.Marshaler and proto.Unmarshaler
+var _ proto.Marshaler = (*MyMessageSet)(nil)
+var _ proto.Unmarshaler = (*MyMessageSet)(nil)
+
+var extRange_MyMessageSet = []proto.ExtensionRange{
+ {100, 2147483646},
+}
+
+func (*MyMessageSet) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MyMessageSet
+}
+
+type Empty struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Empty) Reset() { *m = Empty{} }
+func (m *Empty) String() string { return proto.CompactTextString(m) }
+func (*Empty) ProtoMessage() {}
+func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
+
+type MessageList struct {
+ Message []*MessageList_Message `protobuf:"group,1,rep,name=Message,json=message" json:"message,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MessageList) Reset() { *m = MessageList{} }
+func (m *MessageList) String() string { return proto.CompactTextString(m) }
+func (*MessageList) ProtoMessage() {}
+func (*MessageList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
+
+func (m *MessageList) GetMessage() []*MessageList_Message {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+type MessageList_Message struct {
+ Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"`
+ Count *int32 `protobuf:"varint,3,req,name=count" json:"count,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MessageList_Message) Reset() { *m = MessageList_Message{} }
+func (m *MessageList_Message) String() string { return proto.CompactTextString(m) }
+func (*MessageList_Message) ProtoMessage() {}
+func (*MessageList_Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} }
+
+func (m *MessageList_Message) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *MessageList_Message) GetCount() int32 {
+ if m != nil && m.Count != nil {
+ return *m.Count
+ }
+ return 0
+}
+
+type Strings struct {
+ StringField *string `protobuf:"bytes,1,opt,name=string_field,json=stringField" json:"string_field,omitempty"`
+ BytesField []byte `protobuf:"bytes,2,opt,name=bytes_field,json=bytesField" json:"bytes_field,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Strings) Reset() { *m = Strings{} }
+func (m *Strings) String() string { return proto.CompactTextString(m) }
+func (*Strings) ProtoMessage() {}
+func (*Strings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
+
+func (m *Strings) GetStringField() string {
+ if m != nil && m.StringField != nil {
+ return *m.StringField
+ }
+ return ""
+}
+
+func (m *Strings) GetBytesField() []byte {
+ if m != nil {
+ return m.BytesField
+ }
+ return nil
+}
+
+type Defaults struct {
+ // Default-valued fields of all basic types.
+ // Same as GoTest, but copied here to make testing easier.
+ F_Bool *bool `protobuf:"varint,1,opt,name=F_Bool,json=FBool,def=1" json:"F_Bool,omitempty"`
+ F_Int32 *int32 `protobuf:"varint,2,opt,name=F_Int32,json=FInt32,def=32" json:"F_Int32,omitempty"`
+ F_Int64 *int64 `protobuf:"varint,3,opt,name=F_Int64,json=FInt64,def=64" json:"F_Int64,omitempty"`
+ F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,json=FFixed32,def=320" json:"F_Fixed32,omitempty"`
+ F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,json=FFixed64,def=640" json:"F_Fixed64,omitempty"`
+ F_Uint32 *uint32 `protobuf:"varint,6,opt,name=F_Uint32,json=FUint32,def=3200" json:"F_Uint32,omitempty"`
+ F_Uint64 *uint64 `protobuf:"varint,7,opt,name=F_Uint64,json=FUint64,def=6400" json:"F_Uint64,omitempty"`
+ F_Float *float32 `protobuf:"fixed32,8,opt,name=F_Float,json=FFloat,def=314159" json:"F_Float,omitempty"`
+ F_Double *float64 `protobuf:"fixed64,9,opt,name=F_Double,json=FDouble,def=271828" json:"F_Double,omitempty"`
+ F_String *string `protobuf:"bytes,10,opt,name=F_String,json=FString,def=hello, \"world!\"\n" json:"F_String,omitempty"`
+ F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,json=FBytes,def=Bignose" json:"F_Bytes,omitempty"`
+ F_Sint32 *int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,json=FSint32,def=-32" json:"F_Sint32,omitempty"`
+ F_Sint64 *int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,json=FSint64,def=-64" json:"F_Sint64,omitempty"`
+ F_Enum *Defaults_Color `protobuf:"varint,14,opt,name=F_Enum,json=FEnum,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"`
+ // More fields with crazy defaults.
+ F_Pinf *float32 `protobuf:"fixed32,15,opt,name=F_Pinf,json=FPinf,def=inf" json:"F_Pinf,omitempty"`
+ F_Ninf *float32 `protobuf:"fixed32,16,opt,name=F_Ninf,json=FNinf,def=-inf" json:"F_Ninf,omitempty"`
+ F_Nan *float32 `protobuf:"fixed32,17,opt,name=F_Nan,json=FNan,def=nan" json:"F_Nan,omitempty"`
+ // Sub-message.
+ Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"`
+ // Redundant but explicit defaults.
+ StrZero *string `protobuf:"bytes,19,opt,name=str_zero,json=strZero,def=" json:"str_zero,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Defaults) Reset() { *m = Defaults{} }
+func (m *Defaults) String() string { return proto.CompactTextString(m) }
+func (*Defaults) ProtoMessage() {}
+func (*Defaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} }
+
+const Default_Defaults_F_Bool bool = true
+const Default_Defaults_F_Int32 int32 = 32
+const Default_Defaults_F_Int64 int64 = 64
+const Default_Defaults_F_Fixed32 uint32 = 320
+const Default_Defaults_F_Fixed64 uint64 = 640
+const Default_Defaults_F_Uint32 uint32 = 3200
+const Default_Defaults_F_Uint64 uint64 = 6400
+const Default_Defaults_F_Float float32 = 314159
+const Default_Defaults_F_Double float64 = 271828
+const Default_Defaults_F_String string = "hello, \"world!\"\n"
+
+var Default_Defaults_F_Bytes []byte = []byte("Bignose")
+
+const Default_Defaults_F_Sint32 int32 = -32
+const Default_Defaults_F_Sint64 int64 = -64
+const Default_Defaults_F_Enum Defaults_Color = Defaults_GREEN
+
+var Default_Defaults_F_Pinf float32 = float32(math.Inf(1))
+var Default_Defaults_F_Ninf float32 = float32(math.Inf(-1))
+var Default_Defaults_F_Nan float32 = float32(math.NaN())
+
+func (m *Defaults) GetF_Bool() bool {
+ if m != nil && m.F_Bool != nil {
+ return *m.F_Bool
+ }
+ return Default_Defaults_F_Bool
+}
+
+func (m *Defaults) GetF_Int32() int32 {
+ if m != nil && m.F_Int32 != nil {
+ return *m.F_Int32
+ }
+ return Default_Defaults_F_Int32
+}
+
+func (m *Defaults) GetF_Int64() int64 {
+ if m != nil && m.F_Int64 != nil {
+ return *m.F_Int64
+ }
+ return Default_Defaults_F_Int64
+}
+
+func (m *Defaults) GetF_Fixed32() uint32 {
+ if m != nil && m.F_Fixed32 != nil {
+ return *m.F_Fixed32
+ }
+ return Default_Defaults_F_Fixed32
+}
+
+func (m *Defaults) GetF_Fixed64() uint64 {
+ if m != nil && m.F_Fixed64 != nil {
+ return *m.F_Fixed64
+ }
+ return Default_Defaults_F_Fixed64
+}
+
+func (m *Defaults) GetF_Uint32() uint32 {
+ if m != nil && m.F_Uint32 != nil {
+ return *m.F_Uint32
+ }
+ return Default_Defaults_F_Uint32
+}
+
+func (m *Defaults) GetF_Uint64() uint64 {
+ if m != nil && m.F_Uint64 != nil {
+ return *m.F_Uint64
+ }
+ return Default_Defaults_F_Uint64
+}
+
+func (m *Defaults) GetF_Float() float32 {
+ if m != nil && m.F_Float != nil {
+ return *m.F_Float
+ }
+ return Default_Defaults_F_Float
+}
+
+func (m *Defaults) GetF_Double() float64 {
+ if m != nil && m.F_Double != nil {
+ return *m.F_Double
+ }
+ return Default_Defaults_F_Double
+}
+
+func (m *Defaults) GetF_String() string {
+ if m != nil && m.F_String != nil {
+ return *m.F_String
+ }
+ return Default_Defaults_F_String
+}
+
+func (m *Defaults) GetF_Bytes() []byte {
+ if m != nil && m.F_Bytes != nil {
+ return m.F_Bytes
+ }
+ return append([]byte(nil), Default_Defaults_F_Bytes...)
+}
+
+func (m *Defaults) GetF_Sint32() int32 {
+ if m != nil && m.F_Sint32 != nil {
+ return *m.F_Sint32
+ }
+ return Default_Defaults_F_Sint32
+}
+
+func (m *Defaults) GetF_Sint64() int64 {
+ if m != nil && m.F_Sint64 != nil {
+ return *m.F_Sint64
+ }
+ return Default_Defaults_F_Sint64
+}
+
+func (m *Defaults) GetF_Enum() Defaults_Color {
+ if m != nil && m.F_Enum != nil {
+ return *m.F_Enum
+ }
+ return Default_Defaults_F_Enum
+}
+
+func (m *Defaults) GetF_Pinf() float32 {
+ if m != nil && m.F_Pinf != nil {
+ return *m.F_Pinf
+ }
+ return Default_Defaults_F_Pinf
+}
+
+func (m *Defaults) GetF_Ninf() float32 {
+ if m != nil && m.F_Ninf != nil {
+ return *m.F_Ninf
+ }
+ return Default_Defaults_F_Ninf
+}
+
+func (m *Defaults) GetF_Nan() float32 {
+ if m != nil && m.F_Nan != nil {
+ return *m.F_Nan
+ }
+ return Default_Defaults_F_Nan
+}
+
+func (m *Defaults) GetSub() *SubDefaults {
+ if m != nil {
+ return m.Sub
+ }
+ return nil
+}
+
+func (m *Defaults) GetStrZero() string {
+ if m != nil && m.StrZero != nil {
+ return *m.StrZero
+ }
+ return ""
+}
+
+type SubDefaults struct {
+ N *int64 `protobuf:"varint,1,opt,name=n,def=7" json:"n,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SubDefaults) Reset() { *m = SubDefaults{} }
+func (m *SubDefaults) String() string { return proto.CompactTextString(m) }
+func (*SubDefaults) ProtoMessage() {}
+func (*SubDefaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} }
+
+const Default_SubDefaults_N int64 = 7
+
+func (m *SubDefaults) GetN() int64 {
+ if m != nil && m.N != nil {
+ return *m.N
+ }
+ return Default_SubDefaults_N
+}
+
+type RepeatedEnum struct {
+ Color []RepeatedEnum_Color `protobuf:"varint,1,rep,name=color,enum=testdata.RepeatedEnum_Color" json:"color,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *RepeatedEnum) Reset() { *m = RepeatedEnum{} }
+func (m *RepeatedEnum) String() string { return proto.CompactTextString(m) }
+func (*RepeatedEnum) ProtoMessage() {}
+func (*RepeatedEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} }
+
+func (m *RepeatedEnum) GetColor() []RepeatedEnum_Color {
+ if m != nil {
+ return m.Color
+ }
+ return nil
+}
+
+type MoreRepeated struct {
+ Bools []bool `protobuf:"varint,1,rep,name=bools" json:"bools,omitempty"`
+ BoolsPacked []bool `protobuf:"varint,2,rep,packed,name=bools_packed,json=boolsPacked" json:"bools_packed,omitempty"`
+ Ints []int32 `protobuf:"varint,3,rep,name=ints" json:"ints,omitempty"`
+ IntsPacked []int32 `protobuf:"varint,4,rep,packed,name=ints_packed,json=intsPacked" json:"ints_packed,omitempty"`
+ Int64SPacked []int64 `protobuf:"varint,7,rep,packed,name=int64s_packed,json=int64sPacked" json:"int64s_packed,omitempty"`
+ Strings []string `protobuf:"bytes,5,rep,name=strings" json:"strings,omitempty"`
+ Fixeds []uint32 `protobuf:"fixed32,6,rep,name=fixeds" json:"fixeds,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MoreRepeated) Reset() { *m = MoreRepeated{} }
+func (m *MoreRepeated) String() string { return proto.CompactTextString(m) }
+func (*MoreRepeated) ProtoMessage() {}
+func (*MoreRepeated) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} }
+
+func (m *MoreRepeated) GetBools() []bool {
+ if m != nil {
+ return m.Bools
+ }
+ return nil
+}
+
+func (m *MoreRepeated) GetBoolsPacked() []bool {
+ if m != nil {
+ return m.BoolsPacked
+ }
+ return nil
+}
+
+func (m *MoreRepeated) GetInts() []int32 {
+ if m != nil {
+ return m.Ints
+ }
+ return nil
+}
+
+func (m *MoreRepeated) GetIntsPacked() []int32 {
+ if m != nil {
+ return m.IntsPacked
+ }
+ return nil
+}
+
+func (m *MoreRepeated) GetInt64SPacked() []int64 {
+ if m != nil {
+ return m.Int64SPacked
+ }
+ return nil
+}
+
+func (m *MoreRepeated) GetStrings() []string {
+ if m != nil {
+ return m.Strings
+ }
+ return nil
+}
+
+func (m *MoreRepeated) GetFixeds() []uint32 {
+ if m != nil {
+ return m.Fixeds
+ }
+ return nil
+}
+
+type GroupOld struct {
+ G *GroupOld_G `protobuf:"group,101,opt,name=G,json=g" json:"g,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GroupOld) Reset() { *m = GroupOld{} }
+func (m *GroupOld) String() string { return proto.CompactTextString(m) }
+func (*GroupOld) ProtoMessage() {}
+func (*GroupOld) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} }
+
+func (m *GroupOld) GetG() *GroupOld_G {
+ if m != nil {
+ return m.G
+ }
+ return nil
+}
+
+type GroupOld_G struct {
+ X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GroupOld_G) Reset() { *m = GroupOld_G{} }
+func (m *GroupOld_G) String() string { return proto.CompactTextString(m) }
+func (*GroupOld_G) ProtoMessage() {}
+func (*GroupOld_G) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25, 0} }
+
+func (m *GroupOld_G) GetX() int32 {
+ if m != nil && m.X != nil {
+ return *m.X
+ }
+ return 0
+}
+
+type GroupNew struct {
+ G *GroupNew_G `protobuf:"group,101,opt,name=G,json=g" json:"g,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GroupNew) Reset() { *m = GroupNew{} }
+func (m *GroupNew) String() string { return proto.CompactTextString(m) }
+func (*GroupNew) ProtoMessage() {}
+func (*GroupNew) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} }
+
+func (m *GroupNew) GetG() *GroupNew_G {
+ if m != nil {
+ return m.G
+ }
+ return nil
+}
+
+type GroupNew_G struct {
+ X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"`
+ Y *int32 `protobuf:"varint,3,opt,name=y" json:"y,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GroupNew_G) Reset() { *m = GroupNew_G{} }
+func (m *GroupNew_G) String() string { return proto.CompactTextString(m) }
+func (*GroupNew_G) ProtoMessage() {}
+func (*GroupNew_G) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26, 0} }
+
+func (m *GroupNew_G) GetX() int32 {
+ if m != nil && m.X != nil {
+ return *m.X
+ }
+ return 0
+}
+
+func (m *GroupNew_G) GetY() int32 {
+ if m != nil && m.Y != nil {
+ return *m.Y
+ }
+ return 0
+}
+
+type FloatingPoint struct {
+ F *float64 `protobuf:"fixed64,1,req,name=f" json:"f,omitempty"`
+ Exact *bool `protobuf:"varint,2,opt,name=exact" json:"exact,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FloatingPoint) Reset() { *m = FloatingPoint{} }
+func (m *FloatingPoint) String() string { return proto.CompactTextString(m) }
+func (*FloatingPoint) ProtoMessage() {}
+func (*FloatingPoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} }
+
+func (m *FloatingPoint) GetF() float64 {
+ if m != nil && m.F != nil {
+ return *m.F
+ }
+ return 0
+}
+
+func (m *FloatingPoint) GetExact() bool {
+ if m != nil && m.Exact != nil {
+ return *m.Exact
+ }
+ return false
+}
+
+type MessageWithMap struct {
+ NameMapping map[int32]string `protobuf:"bytes,1,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ MsgMapping map[int64]*FloatingPoint `protobuf:"bytes,2,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ ByteMapping map[bool][]byte `protobuf:"bytes,3,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ StrToStr map[string]string `protobuf:"bytes,4,rep,name=str_to_str,json=strToStr" json:"str_to_str,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
+func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
+func (*MessageWithMap) ProtoMessage() {}
+func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} }
+
+func (m *MessageWithMap) GetNameMapping() map[int32]string {
+ if m != nil {
+ return m.NameMapping
+ }
+ return nil
+}
+
+func (m *MessageWithMap) GetMsgMapping() map[int64]*FloatingPoint {
+ if m != nil {
+ return m.MsgMapping
+ }
+ return nil
+}
+
+func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
+ if m != nil {
+ return m.ByteMapping
+ }
+ return nil
+}
+
+func (m *MessageWithMap) GetStrToStr() map[string]string {
+ if m != nil {
+ return m.StrToStr
+ }
+ return nil
+}
+
+type Oneof struct {
+ // Types that are valid to be assigned to Union:
+ // *Oneof_F_Bool
+ // *Oneof_F_Int32
+ // *Oneof_F_Int64
+ // *Oneof_F_Fixed32
+ // *Oneof_F_Fixed64
+ // *Oneof_F_Uint32
+ // *Oneof_F_Uint64
+ // *Oneof_F_Float
+ // *Oneof_F_Double
+ // *Oneof_F_String
+ // *Oneof_F_Bytes
+ // *Oneof_F_Sint32
+ // *Oneof_F_Sint64
+ // *Oneof_F_Enum
+ // *Oneof_F_Message
+ // *Oneof_FGroup
+ // *Oneof_F_Largest_Tag
+ Union isOneof_Union `protobuf_oneof:"union"`
+ // Types that are valid to be assigned to Tormato:
+ // *Oneof_Value
+ Tormato isOneof_Tormato `protobuf_oneof:"tormato"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Oneof) Reset() { *m = Oneof{} }
+func (m *Oneof) String() string { return proto.CompactTextString(m) }
+func (*Oneof) ProtoMessage() {}
+func (*Oneof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} }
+
+type isOneof_Union interface {
+ isOneof_Union()
+}
+type isOneof_Tormato interface {
+ isOneof_Tormato()
+}
+
+type Oneof_F_Bool struct {
+ F_Bool bool `protobuf:"varint,1,opt,name=F_Bool,json=FBool,oneof"`
+}
+type Oneof_F_Int32 struct {
+ F_Int32 int32 `protobuf:"varint,2,opt,name=F_Int32,json=FInt32,oneof"`
+}
+type Oneof_F_Int64 struct {
+ F_Int64 int64 `protobuf:"varint,3,opt,name=F_Int64,json=FInt64,oneof"`
+}
+type Oneof_F_Fixed32 struct {
+ F_Fixed32 uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,json=FFixed32,oneof"`
+}
+type Oneof_F_Fixed64 struct {
+ F_Fixed64 uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,json=FFixed64,oneof"`
+}
+type Oneof_F_Uint32 struct {
+ F_Uint32 uint32 `protobuf:"varint,6,opt,name=F_Uint32,json=FUint32,oneof"`
+}
+type Oneof_F_Uint64 struct {
+ F_Uint64 uint64 `protobuf:"varint,7,opt,name=F_Uint64,json=FUint64,oneof"`
+}
+type Oneof_F_Float struct {
+ F_Float float32 `protobuf:"fixed32,8,opt,name=F_Float,json=FFloat,oneof"`
+}
+type Oneof_F_Double struct {
+ F_Double float64 `protobuf:"fixed64,9,opt,name=F_Double,json=FDouble,oneof"`
+}
+type Oneof_F_String struct {
+ F_String string `protobuf:"bytes,10,opt,name=F_String,json=FString,oneof"`
+}
+type Oneof_F_Bytes struct {
+ F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,json=FBytes,oneof"`
+}
+type Oneof_F_Sint32 struct {
+ F_Sint32 int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,json=FSint32,oneof"`
+}
+type Oneof_F_Sint64 struct {
+ F_Sint64 int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,json=FSint64,oneof"`
+}
+type Oneof_F_Enum struct {
+ F_Enum MyMessage_Color `protobuf:"varint,14,opt,name=F_Enum,json=FEnum,enum=testdata.MyMessage_Color,oneof"`
+}
+type Oneof_F_Message struct {
+ F_Message *GoTestField `protobuf:"bytes,15,opt,name=F_Message,json=FMessage,oneof"`
+}
+type Oneof_FGroup struct {
+ FGroup *Oneof_F_Group `protobuf:"group,16,opt,name=F_Group,json=fGroup,oneof"`
+}
+type Oneof_F_Largest_Tag struct {
+ F_Largest_Tag int32 `protobuf:"varint,536870911,opt,name=F_Largest_Tag,json=FLargestTag,oneof"`
+}
+type Oneof_Value struct {
+ Value int32 `protobuf:"varint,100,opt,name=value,oneof"`
+}
+
+func (*Oneof_F_Bool) isOneof_Union() {}
+func (*Oneof_F_Int32) isOneof_Union() {}
+func (*Oneof_F_Int64) isOneof_Union() {}
+func (*Oneof_F_Fixed32) isOneof_Union() {}
+func (*Oneof_F_Fixed64) isOneof_Union() {}
+func (*Oneof_F_Uint32) isOneof_Union() {}
+func (*Oneof_F_Uint64) isOneof_Union() {}
+func (*Oneof_F_Float) isOneof_Union() {}
+func (*Oneof_F_Double) isOneof_Union() {}
+func (*Oneof_F_String) isOneof_Union() {}
+func (*Oneof_F_Bytes) isOneof_Union() {}
+func (*Oneof_F_Sint32) isOneof_Union() {}
+func (*Oneof_F_Sint64) isOneof_Union() {}
+func (*Oneof_F_Enum) isOneof_Union() {}
+func (*Oneof_F_Message) isOneof_Union() {}
+func (*Oneof_FGroup) isOneof_Union() {}
+func (*Oneof_F_Largest_Tag) isOneof_Union() {}
+func (*Oneof_Value) isOneof_Tormato() {}
+
+func (m *Oneof) GetUnion() isOneof_Union {
+ if m != nil {
+ return m.Union
+ }
+ return nil
+}
+func (m *Oneof) GetTormato() isOneof_Tormato {
+ if m != nil {
+ return m.Tormato
+ }
+ return nil
+}
+
+func (m *Oneof) GetF_Bool() bool {
+ if x, ok := m.GetUnion().(*Oneof_F_Bool); ok {
+ return x.F_Bool
+ }
+ return false
+}
+
+func (m *Oneof) GetF_Int32() int32 {
+ if x, ok := m.GetUnion().(*Oneof_F_Int32); ok {
+ return x.F_Int32
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Int64() int64 {
+ if x, ok := m.GetUnion().(*Oneof_F_Int64); ok {
+ return x.F_Int64
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Fixed32() uint32 {
+ if x, ok := m.GetUnion().(*Oneof_F_Fixed32); ok {
+ return x.F_Fixed32
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Fixed64() uint64 {
+ if x, ok := m.GetUnion().(*Oneof_F_Fixed64); ok {
+ return x.F_Fixed64
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Uint32() uint32 {
+ if x, ok := m.GetUnion().(*Oneof_F_Uint32); ok {
+ return x.F_Uint32
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Uint64() uint64 {
+ if x, ok := m.GetUnion().(*Oneof_F_Uint64); ok {
+ return x.F_Uint64
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Float() float32 {
+ if x, ok := m.GetUnion().(*Oneof_F_Float); ok {
+ return x.F_Float
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Double() float64 {
+ if x, ok := m.GetUnion().(*Oneof_F_Double); ok {
+ return x.F_Double
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_String() string {
+ if x, ok := m.GetUnion().(*Oneof_F_String); ok {
+ return x.F_String
+ }
+ return ""
+}
+
+func (m *Oneof) GetF_Bytes() []byte {
+ if x, ok := m.GetUnion().(*Oneof_F_Bytes); ok {
+ return x.F_Bytes
+ }
+ return nil
+}
+
+func (m *Oneof) GetF_Sint32() int32 {
+ if x, ok := m.GetUnion().(*Oneof_F_Sint32); ok {
+ return x.F_Sint32
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Sint64() int64 {
+ if x, ok := m.GetUnion().(*Oneof_F_Sint64); ok {
+ return x.F_Sint64
+ }
+ return 0
+}
+
+func (m *Oneof) GetF_Enum() MyMessage_Color {
+ if x, ok := m.GetUnion().(*Oneof_F_Enum); ok {
+ return x.F_Enum
+ }
+ return MyMessage_RED
+}
+
+func (m *Oneof) GetF_Message() *GoTestField {
+ if x, ok := m.GetUnion().(*Oneof_F_Message); ok {
+ return x.F_Message
+ }
+ return nil
+}
+
+func (m *Oneof) GetFGroup() *Oneof_F_Group {
+ if x, ok := m.GetUnion().(*Oneof_FGroup); ok {
+ return x.FGroup
+ }
+ return nil
+}
+
+func (m *Oneof) GetF_Largest_Tag() int32 {
+ if x, ok := m.GetUnion().(*Oneof_F_Largest_Tag); ok {
+ return x.F_Largest_Tag
+ }
+ return 0
+}
+
+func (m *Oneof) GetValue() int32 {
+ if x, ok := m.GetTormato().(*Oneof_Value); ok {
+ return x.Value
+ }
+ return 0
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*Oneof) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _Oneof_OneofMarshaler, _Oneof_OneofUnmarshaler, _Oneof_OneofSizer, []interface{}{
+ (*Oneof_F_Bool)(nil),
+ (*Oneof_F_Int32)(nil),
+ (*Oneof_F_Int64)(nil),
+ (*Oneof_F_Fixed32)(nil),
+ (*Oneof_F_Fixed64)(nil),
+ (*Oneof_F_Uint32)(nil),
+ (*Oneof_F_Uint64)(nil),
+ (*Oneof_F_Float)(nil),
+ (*Oneof_F_Double)(nil),
+ (*Oneof_F_String)(nil),
+ (*Oneof_F_Bytes)(nil),
+ (*Oneof_F_Sint32)(nil),
+ (*Oneof_F_Sint64)(nil),
+ (*Oneof_F_Enum)(nil),
+ (*Oneof_F_Message)(nil),
+ (*Oneof_FGroup)(nil),
+ (*Oneof_F_Largest_Tag)(nil),
+ (*Oneof_Value)(nil),
+ }
+}
+
+func _Oneof_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*Oneof)
+ // union
+ switch x := m.Union.(type) {
+ case *Oneof_F_Bool:
+ t := uint64(0)
+ if x.F_Bool {
+ t = 1
+ }
+ b.EncodeVarint(1<<3 | proto.WireVarint)
+ b.EncodeVarint(t)
+ case *Oneof_F_Int32:
+ b.EncodeVarint(2<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.F_Int32))
+ case *Oneof_F_Int64:
+ b.EncodeVarint(3<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.F_Int64))
+ case *Oneof_F_Fixed32:
+ b.EncodeVarint(4<<3 | proto.WireFixed32)
+ b.EncodeFixed32(uint64(x.F_Fixed32))
+ case *Oneof_F_Fixed64:
+ b.EncodeVarint(5<<3 | proto.WireFixed64)
+ b.EncodeFixed64(uint64(x.F_Fixed64))
+ case *Oneof_F_Uint32:
+ b.EncodeVarint(6<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.F_Uint32))
+ case *Oneof_F_Uint64:
+ b.EncodeVarint(7<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.F_Uint64))
+ case *Oneof_F_Float:
+ b.EncodeVarint(8<<3 | proto.WireFixed32)
+ b.EncodeFixed32(uint64(math.Float32bits(x.F_Float)))
+ case *Oneof_F_Double:
+ b.EncodeVarint(9<<3 | proto.WireFixed64)
+ b.EncodeFixed64(math.Float64bits(x.F_Double))
+ case *Oneof_F_String:
+ b.EncodeVarint(10<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.F_String)
+ case *Oneof_F_Bytes:
+ b.EncodeVarint(11<<3 | proto.WireBytes)
+ b.EncodeRawBytes(x.F_Bytes)
+ case *Oneof_F_Sint32:
+ b.EncodeVarint(12<<3 | proto.WireVarint)
+ b.EncodeZigzag32(uint64(x.F_Sint32))
+ case *Oneof_F_Sint64:
+ b.EncodeVarint(13<<3 | proto.WireVarint)
+ b.EncodeZigzag64(uint64(x.F_Sint64))
+ case *Oneof_F_Enum:
+ b.EncodeVarint(14<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.F_Enum))
+ case *Oneof_F_Message:
+ b.EncodeVarint(15<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.F_Message); err != nil {
+ return err
+ }
+ case *Oneof_FGroup:
+ b.EncodeVarint(16<<3 | proto.WireStartGroup)
+ if err := b.Marshal(x.FGroup); err != nil {
+ return err
+ }
+ b.EncodeVarint(16<<3 | proto.WireEndGroup)
+ case *Oneof_F_Largest_Tag:
+ b.EncodeVarint(536870911<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.F_Largest_Tag))
+ case nil:
+ default:
+ return fmt.Errorf("Oneof.Union has unexpected type %T", x)
+ }
+ // tormato
+ switch x := m.Tormato.(type) {
+ case *Oneof_Value:
+ b.EncodeVarint(100<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.Value))
+ case nil:
+ default:
+ return fmt.Errorf("Oneof.Tormato has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _Oneof_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*Oneof)
+ switch tag {
+ case 1: // union.F_Bool
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Oneof_F_Bool{x != 0}
+ return true, err
+ case 2: // union.F_Int32
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Oneof_F_Int32{int32(x)}
+ return true, err
+ case 3: // union.F_Int64
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Oneof_F_Int64{int64(x)}
+ return true, err
+ case 4: // union.F_Fixed32
+ if wire != proto.WireFixed32 {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeFixed32()
+ m.Union = &Oneof_F_Fixed32{uint32(x)}
+ return true, err
+ case 5: // union.F_Fixed64
+ if wire != proto.WireFixed64 {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeFixed64()
+ m.Union = &Oneof_F_Fixed64{x}
+ return true, err
+ case 6: // union.F_Uint32
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Oneof_F_Uint32{uint32(x)}
+ return true, err
+ case 7: // union.F_Uint64
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Oneof_F_Uint64{x}
+ return true, err
+ case 8: // union.F_Float
+ if wire != proto.WireFixed32 {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeFixed32()
+ m.Union = &Oneof_F_Float{math.Float32frombits(uint32(x))}
+ return true, err
+ case 9: // union.F_Double
+ if wire != proto.WireFixed64 {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeFixed64()
+ m.Union = &Oneof_F_Double{math.Float64frombits(x)}
+ return true, err
+ case 10: // union.F_String
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Union = &Oneof_F_String{x}
+ return true, err
+ case 11: // union.F_Bytes
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeRawBytes(true)
+ m.Union = &Oneof_F_Bytes{x}
+ return true, err
+ case 12: // union.F_Sint32
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeZigzag32()
+ m.Union = &Oneof_F_Sint32{int32(x)}
+ return true, err
+ case 13: // union.F_Sint64
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeZigzag64()
+ m.Union = &Oneof_F_Sint64{int64(x)}
+ return true, err
+ case 14: // union.F_Enum
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Oneof_F_Enum{MyMessage_Color(x)}
+ return true, err
+ case 15: // union.F_Message
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(GoTestField)
+ err := b.DecodeMessage(msg)
+ m.Union = &Oneof_F_Message{msg}
+ return true, err
+ case 16: // union.f_group
+ if wire != proto.WireStartGroup {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(Oneof_F_Group)
+ err := b.DecodeGroup(msg)
+ m.Union = &Oneof_FGroup{msg}
+ return true, err
+ case 536870911: // union.F_Largest_Tag
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Oneof_F_Largest_Tag{int32(x)}
+ return true, err
+ case 100: // tormato.value
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Tormato = &Oneof_Value{int32(x)}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _Oneof_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*Oneof)
+ // union
+ switch x := m.Union.(type) {
+ case *Oneof_F_Bool:
+ n += proto.SizeVarint(1<<3 | proto.WireVarint)
+ n += 1
+ case *Oneof_F_Int32:
+ n += proto.SizeVarint(2<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.F_Int32))
+ case *Oneof_F_Int64:
+ n += proto.SizeVarint(3<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.F_Int64))
+ case *Oneof_F_Fixed32:
+ n += proto.SizeVarint(4<<3 | proto.WireFixed32)
+ n += 4
+ case *Oneof_F_Fixed64:
+ n += proto.SizeVarint(5<<3 | proto.WireFixed64)
+ n += 8
+ case *Oneof_F_Uint32:
+ n += proto.SizeVarint(6<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.F_Uint32))
+ case *Oneof_F_Uint64:
+ n += proto.SizeVarint(7<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.F_Uint64))
+ case *Oneof_F_Float:
+ n += proto.SizeVarint(8<<3 | proto.WireFixed32)
+ n += 4
+ case *Oneof_F_Double:
+ n += proto.SizeVarint(9<<3 | proto.WireFixed64)
+ n += 8
+ case *Oneof_F_String:
+ n += proto.SizeVarint(10<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.F_String)))
+ n += len(x.F_String)
+ case *Oneof_F_Bytes:
+ n += proto.SizeVarint(11<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.F_Bytes)))
+ n += len(x.F_Bytes)
+ case *Oneof_F_Sint32:
+ n += proto.SizeVarint(12<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64((uint32(x.F_Sint32) << 1) ^ uint32((int32(x.F_Sint32) >> 31))))
+ case *Oneof_F_Sint64:
+ n += proto.SizeVarint(13<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(uint64(x.F_Sint64<<1) ^ uint64((int64(x.F_Sint64) >> 63))))
+ case *Oneof_F_Enum:
+ n += proto.SizeVarint(14<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.F_Enum))
+ case *Oneof_F_Message:
+ s := proto.Size(x.F_Message)
+ n += proto.SizeVarint(15<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *Oneof_FGroup:
+ n += proto.SizeVarint(16<<3 | proto.WireStartGroup)
+ n += proto.Size(x.FGroup)
+ n += proto.SizeVarint(16<<3 | proto.WireEndGroup)
+ case *Oneof_F_Largest_Tag:
+ n += proto.SizeVarint(536870911<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.F_Largest_Tag))
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ // tormato
+ switch x := m.Tormato.(type) {
+ case *Oneof_Value:
+ n += proto.SizeVarint(100<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.Value))
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+type Oneof_F_Group struct {
+ X *int32 `protobuf:"varint,17,opt,name=x" json:"x,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Oneof_F_Group) Reset() { *m = Oneof_F_Group{} }
+func (m *Oneof_F_Group) String() string { return proto.CompactTextString(m) }
+func (*Oneof_F_Group) ProtoMessage() {}
+func (*Oneof_F_Group) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29, 0} }
+
+func (m *Oneof_F_Group) GetX() int32 {
+ if m != nil && m.X != nil {
+ return *m.X
+ }
+ return 0
+}
+
+type Communique struct {
+ MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry,json=makeMeCry" json:"make_me_cry,omitempty"`
+ // This is a oneof, called "union".
+ //
+ // Types that are valid to be assigned to Union:
+ // *Communique_Number
+ // *Communique_Name
+ // *Communique_Data
+ // *Communique_TempC
+ // *Communique_Col
+ // *Communique_Msg
+ Union isCommunique_Union `protobuf_oneof:"union"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Communique) Reset() { *m = Communique{} }
+func (m *Communique) String() string { return proto.CompactTextString(m) }
+func (*Communique) ProtoMessage() {}
+func (*Communique) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} }
+
+type isCommunique_Union interface {
+ isCommunique_Union()
+}
+
+type Communique_Number struct {
+ Number int32 `protobuf:"varint,5,opt,name=number,oneof"`
+}
+type Communique_Name struct {
+ Name string `protobuf:"bytes,6,opt,name=name,oneof"`
+}
+type Communique_Data struct {
+ Data []byte `protobuf:"bytes,7,opt,name=data,oneof"`
+}
+type Communique_TempC struct {
+ TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,json=tempC,oneof"`
+}
+type Communique_Col struct {
+ Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color,oneof"`
+}
+type Communique_Msg struct {
+ Msg *Strings `protobuf:"bytes,10,opt,name=msg,oneof"`
+}
+
+func (*Communique_Number) isCommunique_Union() {}
+func (*Communique_Name) isCommunique_Union() {}
+func (*Communique_Data) isCommunique_Union() {}
+func (*Communique_TempC) isCommunique_Union() {}
+func (*Communique_Col) isCommunique_Union() {}
+func (*Communique_Msg) isCommunique_Union() {}
+
+func (m *Communique) GetUnion() isCommunique_Union {
+ if m != nil {
+ return m.Union
+ }
+ return nil
+}
+
+func (m *Communique) GetMakeMeCry() bool {
+ if m != nil && m.MakeMeCry != nil {
+ return *m.MakeMeCry
+ }
+ return false
+}
+
+func (m *Communique) GetNumber() int32 {
+ if x, ok := m.GetUnion().(*Communique_Number); ok {
+ return x.Number
+ }
+ return 0
+}
+
+func (m *Communique) GetName() string {
+ if x, ok := m.GetUnion().(*Communique_Name); ok {
+ return x.Name
+ }
+ return ""
+}
+
+func (m *Communique) GetData() []byte {
+ if x, ok := m.GetUnion().(*Communique_Data); ok {
+ return x.Data
+ }
+ return nil
+}
+
+func (m *Communique) GetTempC() float64 {
+ if x, ok := m.GetUnion().(*Communique_TempC); ok {
+ return x.TempC
+ }
+ return 0
+}
+
+func (m *Communique) GetCol() MyMessage_Color {
+ if x, ok := m.GetUnion().(*Communique_Col); ok {
+ return x.Col
+ }
+ return MyMessage_RED
+}
+
+func (m *Communique) GetMsg() *Strings {
+ if x, ok := m.GetUnion().(*Communique_Msg); ok {
+ return x.Msg
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{
+ (*Communique_Number)(nil),
+ (*Communique_Name)(nil),
+ (*Communique_Data)(nil),
+ (*Communique_TempC)(nil),
+ (*Communique_Col)(nil),
+ (*Communique_Msg)(nil),
+ }
+}
+
+func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*Communique)
+ // union
+ switch x := m.Union.(type) {
+ case *Communique_Number:
+ b.EncodeVarint(5<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.Number))
+ case *Communique_Name:
+ b.EncodeVarint(6<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.Name)
+ case *Communique_Data:
+ b.EncodeVarint(7<<3 | proto.WireBytes)
+ b.EncodeRawBytes(x.Data)
+ case *Communique_TempC:
+ b.EncodeVarint(8<<3 | proto.WireFixed64)
+ b.EncodeFixed64(math.Float64bits(x.TempC))
+ case *Communique_Col:
+ b.EncodeVarint(9<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.Col))
+ case *Communique_Msg:
+ b.EncodeVarint(10<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.Msg); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("Communique.Union has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*Communique)
+ switch tag {
+ case 5: // union.number
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Communique_Number{int32(x)}
+ return true, err
+ case 6: // union.name
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Union = &Communique_Name{x}
+ return true, err
+ case 7: // union.data
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeRawBytes(true)
+ m.Union = &Communique_Data{x}
+ return true, err
+ case 8: // union.temp_c
+ if wire != proto.WireFixed64 {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeFixed64()
+ m.Union = &Communique_TempC{math.Float64frombits(x)}
+ return true, err
+ case 9: // union.col
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Union = &Communique_Col{MyMessage_Color(x)}
+ return true, err
+ case 10: // union.msg
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(Strings)
+ err := b.DecodeMessage(msg)
+ m.Union = &Communique_Msg{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _Communique_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*Communique)
+ // union
+ switch x := m.Union.(type) {
+ case *Communique_Number:
+ n += proto.SizeVarint(5<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.Number))
+ case *Communique_Name:
+ n += proto.SizeVarint(6<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.Name)))
+ n += len(x.Name)
+ case *Communique_Data:
+ n += proto.SizeVarint(7<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.Data)))
+ n += len(x.Data)
+ case *Communique_TempC:
+ n += proto.SizeVarint(8<<3 | proto.WireFixed64)
+ n += 8
+ case *Communique_Col:
+ n += proto.SizeVarint(9<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.Col))
+ case *Communique_Msg:
+ s := proto.Size(x.Msg)
+ n += proto.SizeVarint(10<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+var E_Greeting = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessage)(nil),
+ ExtensionType: ([]string)(nil),
+ Field: 106,
+ Name: "testdata.greeting",
+ Tag: "bytes,106,rep,name=greeting",
+ Filename: "test.proto",
+}
+
+var E_Complex = &proto.ExtensionDesc{
+ ExtendedType: (*OtherMessage)(nil),
+ ExtensionType: (*ComplexExtension)(nil),
+ Field: 200,
+ Name: "testdata.complex",
+ Tag: "bytes,200,opt,name=complex",
+ Filename: "test.proto",
+}
+
+var E_RComplex = &proto.ExtensionDesc{
+ ExtendedType: (*OtherMessage)(nil),
+ ExtensionType: ([]*ComplexExtension)(nil),
+ Field: 201,
+ Name: "testdata.r_complex",
+ Tag: "bytes,201,rep,name=r_complex,json=rComplex",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultDouble = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*float64)(nil),
+ Field: 101,
+ Name: "testdata.no_default_double",
+ Tag: "fixed64,101,opt,name=no_default_double,json=noDefaultDouble",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultFloat = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*float32)(nil),
+ Field: 102,
+ Name: "testdata.no_default_float",
+ Tag: "fixed32,102,opt,name=no_default_float,json=noDefaultFloat",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultInt32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int32)(nil),
+ Field: 103,
+ Name: "testdata.no_default_int32",
+ Tag: "varint,103,opt,name=no_default_int32,json=noDefaultInt32",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultInt64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int64)(nil),
+ Field: 104,
+ Name: "testdata.no_default_int64",
+ Tag: "varint,104,opt,name=no_default_int64,json=noDefaultInt64",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultUint32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint32)(nil),
+ Field: 105,
+ Name: "testdata.no_default_uint32",
+ Tag: "varint,105,opt,name=no_default_uint32,json=noDefaultUint32",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultUint64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint64)(nil),
+ Field: 106,
+ Name: "testdata.no_default_uint64",
+ Tag: "varint,106,opt,name=no_default_uint64,json=noDefaultUint64",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultSint32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int32)(nil),
+ Field: 107,
+ Name: "testdata.no_default_sint32",
+ Tag: "zigzag32,107,opt,name=no_default_sint32,json=noDefaultSint32",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultSint64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int64)(nil),
+ Field: 108,
+ Name: "testdata.no_default_sint64",
+ Tag: "zigzag64,108,opt,name=no_default_sint64,json=noDefaultSint64",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultFixed32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint32)(nil),
+ Field: 109,
+ Name: "testdata.no_default_fixed32",
+ Tag: "fixed32,109,opt,name=no_default_fixed32,json=noDefaultFixed32",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultFixed64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint64)(nil),
+ Field: 110,
+ Name: "testdata.no_default_fixed64",
+ Tag: "fixed64,110,opt,name=no_default_fixed64,json=noDefaultFixed64",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultSfixed32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int32)(nil),
+ Field: 111,
+ Name: "testdata.no_default_sfixed32",
+ Tag: "fixed32,111,opt,name=no_default_sfixed32,json=noDefaultSfixed32",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultSfixed64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int64)(nil),
+ Field: 112,
+ Name: "testdata.no_default_sfixed64",
+ Tag: "fixed64,112,opt,name=no_default_sfixed64,json=noDefaultSfixed64",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultBool = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 113,
+ Name: "testdata.no_default_bool",
+ Tag: "varint,113,opt,name=no_default_bool,json=noDefaultBool",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultString = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 114,
+ Name: "testdata.no_default_string",
+ Tag: "bytes,114,opt,name=no_default_string,json=noDefaultString",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultBytes = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: ([]byte)(nil),
+ Field: 115,
+ Name: "testdata.no_default_bytes",
+ Tag: "bytes,115,opt,name=no_default_bytes,json=noDefaultBytes",
+ Filename: "test.proto",
+}
+
+var E_NoDefaultEnum = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil),
+ Field: 116,
+ Name: "testdata.no_default_enum",
+ Tag: "varint,116,opt,name=no_default_enum,json=noDefaultEnum,enum=testdata.DefaultsMessage_DefaultsEnum",
+ Filename: "test.proto",
+}
+
+var E_DefaultDouble = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*float64)(nil),
+ Field: 201,
+ Name: "testdata.default_double",
+ Tag: "fixed64,201,opt,name=default_double,json=defaultDouble,def=3.1415",
+ Filename: "test.proto",
+}
+
+var E_DefaultFloat = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*float32)(nil),
+ Field: 202,
+ Name: "testdata.default_float",
+ Tag: "fixed32,202,opt,name=default_float,json=defaultFloat,def=3.14",
+ Filename: "test.proto",
+}
+
+var E_DefaultInt32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int32)(nil),
+ Field: 203,
+ Name: "testdata.default_int32",
+ Tag: "varint,203,opt,name=default_int32,json=defaultInt32,def=42",
+ Filename: "test.proto",
+}
+
+var E_DefaultInt64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int64)(nil),
+ Field: 204,
+ Name: "testdata.default_int64",
+ Tag: "varint,204,opt,name=default_int64,json=defaultInt64,def=43",
+ Filename: "test.proto",
+}
+
+var E_DefaultUint32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint32)(nil),
+ Field: 205,
+ Name: "testdata.default_uint32",
+ Tag: "varint,205,opt,name=default_uint32,json=defaultUint32,def=44",
+ Filename: "test.proto",
+}
+
+var E_DefaultUint64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint64)(nil),
+ Field: 206,
+ Name: "testdata.default_uint64",
+ Tag: "varint,206,opt,name=default_uint64,json=defaultUint64,def=45",
+ Filename: "test.proto",
+}
+
+var E_DefaultSint32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int32)(nil),
+ Field: 207,
+ Name: "testdata.default_sint32",
+ Tag: "zigzag32,207,opt,name=default_sint32,json=defaultSint32,def=46",
+ Filename: "test.proto",
+}
+
+var E_DefaultSint64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int64)(nil),
+ Field: 208,
+ Name: "testdata.default_sint64",
+ Tag: "zigzag64,208,opt,name=default_sint64,json=defaultSint64,def=47",
+ Filename: "test.proto",
+}
+
+var E_DefaultFixed32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint32)(nil),
+ Field: 209,
+ Name: "testdata.default_fixed32",
+ Tag: "fixed32,209,opt,name=default_fixed32,json=defaultFixed32,def=48",
+ Filename: "test.proto",
+}
+
+var E_DefaultFixed64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*uint64)(nil),
+ Field: 210,
+ Name: "testdata.default_fixed64",
+ Tag: "fixed64,210,opt,name=default_fixed64,json=defaultFixed64,def=49",
+ Filename: "test.proto",
+}
+
+var E_DefaultSfixed32 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int32)(nil),
+ Field: 211,
+ Name: "testdata.default_sfixed32",
+ Tag: "fixed32,211,opt,name=default_sfixed32,json=defaultSfixed32,def=50",
+ Filename: "test.proto",
+}
+
+var E_DefaultSfixed64 = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*int64)(nil),
+ Field: 212,
+ Name: "testdata.default_sfixed64",
+ Tag: "fixed64,212,opt,name=default_sfixed64,json=defaultSfixed64,def=51",
+ Filename: "test.proto",
+}
+
+var E_DefaultBool = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 213,
+ Name: "testdata.default_bool",
+ Tag: "varint,213,opt,name=default_bool,json=defaultBool,def=1",
+ Filename: "test.proto",
+}
+
+var E_DefaultString = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*string)(nil),
+ Field: 214,
+ Name: "testdata.default_string",
+ Tag: "bytes,214,opt,name=default_string,json=defaultString,def=Hello, string",
+ Filename: "test.proto",
+}
+
+var E_DefaultBytes = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: ([]byte)(nil),
+ Field: 215,
+ Name: "testdata.default_bytes",
+ Tag: "bytes,215,opt,name=default_bytes,json=defaultBytes,def=Hello, bytes",
+ Filename: "test.proto",
+}
+
+var E_DefaultEnum = &proto.ExtensionDesc{
+ ExtendedType: (*DefaultsMessage)(nil),
+ ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil),
+ Field: 216,
+ Name: "testdata.default_enum",
+ Tag: "varint,216,opt,name=default_enum,json=defaultEnum,enum=testdata.DefaultsMessage_DefaultsEnum,def=1",
+ Filename: "test.proto",
+}
+
+var E_X201 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 201,
+ Name: "testdata.x201",
+ Tag: "bytes,201,opt,name=x201",
+ Filename: "test.proto",
+}
+
+var E_X202 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 202,
+ Name: "testdata.x202",
+ Tag: "bytes,202,opt,name=x202",
+ Filename: "test.proto",
+}
+
+var E_X203 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 203,
+ Name: "testdata.x203",
+ Tag: "bytes,203,opt,name=x203",
+ Filename: "test.proto",
+}
+
+var E_X204 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 204,
+ Name: "testdata.x204",
+ Tag: "bytes,204,opt,name=x204",
+ Filename: "test.proto",
+}
+
+var E_X205 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 205,
+ Name: "testdata.x205",
+ Tag: "bytes,205,opt,name=x205",
+ Filename: "test.proto",
+}
+
+var E_X206 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 206,
+ Name: "testdata.x206",
+ Tag: "bytes,206,opt,name=x206",
+ Filename: "test.proto",
+}
+
+var E_X207 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 207,
+ Name: "testdata.x207",
+ Tag: "bytes,207,opt,name=x207",
+ Filename: "test.proto",
+}
+
+var E_X208 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 208,
+ Name: "testdata.x208",
+ Tag: "bytes,208,opt,name=x208",
+ Filename: "test.proto",
+}
+
+var E_X209 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 209,
+ Name: "testdata.x209",
+ Tag: "bytes,209,opt,name=x209",
+ Filename: "test.proto",
+}
+
+var E_X210 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 210,
+ Name: "testdata.x210",
+ Tag: "bytes,210,opt,name=x210",
+ Filename: "test.proto",
+}
+
+var E_X211 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 211,
+ Name: "testdata.x211",
+ Tag: "bytes,211,opt,name=x211",
+ Filename: "test.proto",
+}
+
+var E_X212 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 212,
+ Name: "testdata.x212",
+ Tag: "bytes,212,opt,name=x212",
+ Filename: "test.proto",
+}
+
+var E_X213 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 213,
+ Name: "testdata.x213",
+ Tag: "bytes,213,opt,name=x213",
+ Filename: "test.proto",
+}
+
+var E_X214 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 214,
+ Name: "testdata.x214",
+ Tag: "bytes,214,opt,name=x214",
+ Filename: "test.proto",
+}
+
+var E_X215 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 215,
+ Name: "testdata.x215",
+ Tag: "bytes,215,opt,name=x215",
+ Filename: "test.proto",
+}
+
+var E_X216 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 216,
+ Name: "testdata.x216",
+ Tag: "bytes,216,opt,name=x216",
+ Filename: "test.proto",
+}
+
+var E_X217 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 217,
+ Name: "testdata.x217",
+ Tag: "bytes,217,opt,name=x217",
+ Filename: "test.proto",
+}
+
+var E_X218 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 218,
+ Name: "testdata.x218",
+ Tag: "bytes,218,opt,name=x218",
+ Filename: "test.proto",
+}
+
+var E_X219 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 219,
+ Name: "testdata.x219",
+ Tag: "bytes,219,opt,name=x219",
+ Filename: "test.proto",
+}
+
+var E_X220 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 220,
+ Name: "testdata.x220",
+ Tag: "bytes,220,opt,name=x220",
+ Filename: "test.proto",
+}
+
+var E_X221 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 221,
+ Name: "testdata.x221",
+ Tag: "bytes,221,opt,name=x221",
+ Filename: "test.proto",
+}
+
+var E_X222 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 222,
+ Name: "testdata.x222",
+ Tag: "bytes,222,opt,name=x222",
+ Filename: "test.proto",
+}
+
+var E_X223 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 223,
+ Name: "testdata.x223",
+ Tag: "bytes,223,opt,name=x223",
+ Filename: "test.proto",
+}
+
+var E_X224 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 224,
+ Name: "testdata.x224",
+ Tag: "bytes,224,opt,name=x224",
+ Filename: "test.proto",
+}
+
+var E_X225 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 225,
+ Name: "testdata.x225",
+ Tag: "bytes,225,opt,name=x225",
+ Filename: "test.proto",
+}
+
+var E_X226 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 226,
+ Name: "testdata.x226",
+ Tag: "bytes,226,opt,name=x226",
+ Filename: "test.proto",
+}
+
+var E_X227 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 227,
+ Name: "testdata.x227",
+ Tag: "bytes,227,opt,name=x227",
+ Filename: "test.proto",
+}
+
+var E_X228 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 228,
+ Name: "testdata.x228",
+ Tag: "bytes,228,opt,name=x228",
+ Filename: "test.proto",
+}
+
+var E_X229 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 229,
+ Name: "testdata.x229",
+ Tag: "bytes,229,opt,name=x229",
+ Filename: "test.proto",
+}
+
+var E_X230 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 230,
+ Name: "testdata.x230",
+ Tag: "bytes,230,opt,name=x230",
+ Filename: "test.proto",
+}
+
+var E_X231 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 231,
+ Name: "testdata.x231",
+ Tag: "bytes,231,opt,name=x231",
+ Filename: "test.proto",
+}
+
+var E_X232 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 232,
+ Name: "testdata.x232",
+ Tag: "bytes,232,opt,name=x232",
+ Filename: "test.proto",
+}
+
+var E_X233 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 233,
+ Name: "testdata.x233",
+ Tag: "bytes,233,opt,name=x233",
+ Filename: "test.proto",
+}
+
+var E_X234 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 234,
+ Name: "testdata.x234",
+ Tag: "bytes,234,opt,name=x234",
+ Filename: "test.proto",
+}
+
+var E_X235 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 235,
+ Name: "testdata.x235",
+ Tag: "bytes,235,opt,name=x235",
+ Filename: "test.proto",
+}
+
+var E_X236 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 236,
+ Name: "testdata.x236",
+ Tag: "bytes,236,opt,name=x236",
+ Filename: "test.proto",
+}
+
+var E_X237 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 237,
+ Name: "testdata.x237",
+ Tag: "bytes,237,opt,name=x237",
+ Filename: "test.proto",
+}
+
+var E_X238 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 238,
+ Name: "testdata.x238",
+ Tag: "bytes,238,opt,name=x238",
+ Filename: "test.proto",
+}
+
+var E_X239 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 239,
+ Name: "testdata.x239",
+ Tag: "bytes,239,opt,name=x239",
+ Filename: "test.proto",
+}
+
+var E_X240 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 240,
+ Name: "testdata.x240",
+ Tag: "bytes,240,opt,name=x240",
+ Filename: "test.proto",
+}
+
+var E_X241 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 241,
+ Name: "testdata.x241",
+ Tag: "bytes,241,opt,name=x241",
+ Filename: "test.proto",
+}
+
+var E_X242 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 242,
+ Name: "testdata.x242",
+ Tag: "bytes,242,opt,name=x242",
+ Filename: "test.proto",
+}
+
+var E_X243 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 243,
+ Name: "testdata.x243",
+ Tag: "bytes,243,opt,name=x243",
+ Filename: "test.proto",
+}
+
+var E_X244 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 244,
+ Name: "testdata.x244",
+ Tag: "bytes,244,opt,name=x244",
+ Filename: "test.proto",
+}
+
+var E_X245 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 245,
+ Name: "testdata.x245",
+ Tag: "bytes,245,opt,name=x245",
+ Filename: "test.proto",
+}
+
+var E_X246 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 246,
+ Name: "testdata.x246",
+ Tag: "bytes,246,opt,name=x246",
+ Filename: "test.proto",
+}
+
+var E_X247 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 247,
+ Name: "testdata.x247",
+ Tag: "bytes,247,opt,name=x247",
+ Filename: "test.proto",
+}
+
+var E_X248 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 248,
+ Name: "testdata.x248",
+ Tag: "bytes,248,opt,name=x248",
+ Filename: "test.proto",
+}
+
+var E_X249 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 249,
+ Name: "testdata.x249",
+ Tag: "bytes,249,opt,name=x249",
+ Filename: "test.proto",
+}
+
+var E_X250 = &proto.ExtensionDesc{
+ ExtendedType: (*MyMessageSet)(nil),
+ ExtensionType: (*Empty)(nil),
+ Field: 250,
+ Name: "testdata.x250",
+ Tag: "bytes,250,opt,name=x250",
+ Filename: "test.proto",
+}
+
+func init() {
+ proto.RegisterType((*GoEnum)(nil), "testdata.GoEnum")
+ proto.RegisterType((*GoTestField)(nil), "testdata.GoTestField")
+ proto.RegisterType((*GoTest)(nil), "testdata.GoTest")
+ proto.RegisterType((*GoTest_RequiredGroup)(nil), "testdata.GoTest.RequiredGroup")
+ proto.RegisterType((*GoTest_RepeatedGroup)(nil), "testdata.GoTest.RepeatedGroup")
+ proto.RegisterType((*GoTest_OptionalGroup)(nil), "testdata.GoTest.OptionalGroup")
+ proto.RegisterType((*GoTestRequiredGroupField)(nil), "testdata.GoTestRequiredGroupField")
+ proto.RegisterType((*GoTestRequiredGroupField_Group)(nil), "testdata.GoTestRequiredGroupField.Group")
+ proto.RegisterType((*GoSkipTest)(nil), "testdata.GoSkipTest")
+ proto.RegisterType((*GoSkipTest_SkipGroup)(nil), "testdata.GoSkipTest.SkipGroup")
+ proto.RegisterType((*NonPackedTest)(nil), "testdata.NonPackedTest")
+ proto.RegisterType((*PackedTest)(nil), "testdata.PackedTest")
+ proto.RegisterType((*MaxTag)(nil), "testdata.MaxTag")
+ proto.RegisterType((*OldMessage)(nil), "testdata.OldMessage")
+ proto.RegisterType((*OldMessage_Nested)(nil), "testdata.OldMessage.Nested")
+ proto.RegisterType((*NewMessage)(nil), "testdata.NewMessage")
+ proto.RegisterType((*NewMessage_Nested)(nil), "testdata.NewMessage.Nested")
+ proto.RegisterType((*InnerMessage)(nil), "testdata.InnerMessage")
+ proto.RegisterType((*OtherMessage)(nil), "testdata.OtherMessage")
+ proto.RegisterType((*RequiredInnerMessage)(nil), "testdata.RequiredInnerMessage")
+ proto.RegisterType((*MyMessage)(nil), "testdata.MyMessage")
+ proto.RegisterType((*MyMessage_SomeGroup)(nil), "testdata.MyMessage.SomeGroup")
+ proto.RegisterType((*Ext)(nil), "testdata.Ext")
+ proto.RegisterType((*ComplexExtension)(nil), "testdata.ComplexExtension")
+ proto.RegisterType((*DefaultsMessage)(nil), "testdata.DefaultsMessage")
+ proto.RegisterType((*MyMessageSet)(nil), "testdata.MyMessageSet")
+ proto.RegisterType((*Empty)(nil), "testdata.Empty")
+ proto.RegisterType((*MessageList)(nil), "testdata.MessageList")
+ proto.RegisterType((*MessageList_Message)(nil), "testdata.MessageList.Message")
+ proto.RegisterType((*Strings)(nil), "testdata.Strings")
+ proto.RegisterType((*Defaults)(nil), "testdata.Defaults")
+ proto.RegisterType((*SubDefaults)(nil), "testdata.SubDefaults")
+ proto.RegisterType((*RepeatedEnum)(nil), "testdata.RepeatedEnum")
+ proto.RegisterType((*MoreRepeated)(nil), "testdata.MoreRepeated")
+ proto.RegisterType((*GroupOld)(nil), "testdata.GroupOld")
+ proto.RegisterType((*GroupOld_G)(nil), "testdata.GroupOld.G")
+ proto.RegisterType((*GroupNew)(nil), "testdata.GroupNew")
+ proto.RegisterType((*GroupNew_G)(nil), "testdata.GroupNew.G")
+ proto.RegisterType((*FloatingPoint)(nil), "testdata.FloatingPoint")
+ proto.RegisterType((*MessageWithMap)(nil), "testdata.MessageWithMap")
+ proto.RegisterType((*Oneof)(nil), "testdata.Oneof")
+ proto.RegisterType((*Oneof_F_Group)(nil), "testdata.Oneof.F_Group")
+ proto.RegisterType((*Communique)(nil), "testdata.Communique")
+ proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value)
+ proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value)
+ proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value)
+ proto.RegisterEnum("testdata.DefaultsMessage_DefaultsEnum", DefaultsMessage_DefaultsEnum_name, DefaultsMessage_DefaultsEnum_value)
+ proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value)
+ proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value)
+ proto.RegisterExtension(E_Ext_More)
+ proto.RegisterExtension(E_Ext_Text)
+ proto.RegisterExtension(E_Ext_Number)
+ proto.RegisterExtension(E_Greeting)
+ proto.RegisterExtension(E_Complex)
+ proto.RegisterExtension(E_RComplex)
+ proto.RegisterExtension(E_NoDefaultDouble)
+ proto.RegisterExtension(E_NoDefaultFloat)
+ proto.RegisterExtension(E_NoDefaultInt32)
+ proto.RegisterExtension(E_NoDefaultInt64)
+ proto.RegisterExtension(E_NoDefaultUint32)
+ proto.RegisterExtension(E_NoDefaultUint64)
+ proto.RegisterExtension(E_NoDefaultSint32)
+ proto.RegisterExtension(E_NoDefaultSint64)
+ proto.RegisterExtension(E_NoDefaultFixed32)
+ proto.RegisterExtension(E_NoDefaultFixed64)
+ proto.RegisterExtension(E_NoDefaultSfixed32)
+ proto.RegisterExtension(E_NoDefaultSfixed64)
+ proto.RegisterExtension(E_NoDefaultBool)
+ proto.RegisterExtension(E_NoDefaultString)
+ proto.RegisterExtension(E_NoDefaultBytes)
+ proto.RegisterExtension(E_NoDefaultEnum)
+ proto.RegisterExtension(E_DefaultDouble)
+ proto.RegisterExtension(E_DefaultFloat)
+ proto.RegisterExtension(E_DefaultInt32)
+ proto.RegisterExtension(E_DefaultInt64)
+ proto.RegisterExtension(E_DefaultUint32)
+ proto.RegisterExtension(E_DefaultUint64)
+ proto.RegisterExtension(E_DefaultSint32)
+ proto.RegisterExtension(E_DefaultSint64)
+ proto.RegisterExtension(E_DefaultFixed32)
+ proto.RegisterExtension(E_DefaultFixed64)
+ proto.RegisterExtension(E_DefaultSfixed32)
+ proto.RegisterExtension(E_DefaultSfixed64)
+ proto.RegisterExtension(E_DefaultBool)
+ proto.RegisterExtension(E_DefaultString)
+ proto.RegisterExtension(E_DefaultBytes)
+ proto.RegisterExtension(E_DefaultEnum)
+ proto.RegisterExtension(E_X201)
+ proto.RegisterExtension(E_X202)
+ proto.RegisterExtension(E_X203)
+ proto.RegisterExtension(E_X204)
+ proto.RegisterExtension(E_X205)
+ proto.RegisterExtension(E_X206)
+ proto.RegisterExtension(E_X207)
+ proto.RegisterExtension(E_X208)
+ proto.RegisterExtension(E_X209)
+ proto.RegisterExtension(E_X210)
+ proto.RegisterExtension(E_X211)
+ proto.RegisterExtension(E_X212)
+ proto.RegisterExtension(E_X213)
+ proto.RegisterExtension(E_X214)
+ proto.RegisterExtension(E_X215)
+ proto.RegisterExtension(E_X216)
+ proto.RegisterExtension(E_X217)
+ proto.RegisterExtension(E_X218)
+ proto.RegisterExtension(E_X219)
+ proto.RegisterExtension(E_X220)
+ proto.RegisterExtension(E_X221)
+ proto.RegisterExtension(E_X222)
+ proto.RegisterExtension(E_X223)
+ proto.RegisterExtension(E_X224)
+ proto.RegisterExtension(E_X225)
+ proto.RegisterExtension(E_X226)
+ proto.RegisterExtension(E_X227)
+ proto.RegisterExtension(E_X228)
+ proto.RegisterExtension(E_X229)
+ proto.RegisterExtension(E_X230)
+ proto.RegisterExtension(E_X231)
+ proto.RegisterExtension(E_X232)
+ proto.RegisterExtension(E_X233)
+ proto.RegisterExtension(E_X234)
+ proto.RegisterExtension(E_X235)
+ proto.RegisterExtension(E_X236)
+ proto.RegisterExtension(E_X237)
+ proto.RegisterExtension(E_X238)
+ proto.RegisterExtension(E_X239)
+ proto.RegisterExtension(E_X240)
+ proto.RegisterExtension(E_X241)
+ proto.RegisterExtension(E_X242)
+ proto.RegisterExtension(E_X243)
+ proto.RegisterExtension(E_X244)
+ proto.RegisterExtension(E_X245)
+ proto.RegisterExtension(E_X246)
+ proto.RegisterExtension(E_X247)
+ proto.RegisterExtension(E_X248)
+ proto.RegisterExtension(E_X249)
+ proto.RegisterExtension(E_X250)
+}
+
+func init() { proto.RegisterFile("test.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 4453 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x5a, 0xc9, 0x77, 0xdb, 0x48,
+ 0x7a, 0x37, 0xc0, 0xfd, 0x23, 0x25, 0x42, 0x65, 0xb5, 0x9b, 0x96, 0xbc, 0xc0, 0x9c, 0xe9, 0x6e,
+ 0x7a, 0xd3, 0x48, 0x20, 0x44, 0xdb, 0x74, 0xa7, 0xdf, 0xf3, 0x42, 0xca, 0x7a, 0x63, 0x89, 0x0a,
+ 0xa4, 0xee, 0x7e, 0xd3, 0x39, 0xf0, 0x51, 0x22, 0x44, 0xb3, 0x4d, 0x02, 0x34, 0x09, 0xc5, 0x52,
+ 0x72, 0xe9, 0x4b, 0x72, 0xcd, 0x76, 0xc9, 0x35, 0xa7, 0x9c, 0x92, 0xbc, 0x97, 0x7f, 0x22, 0xe9,
+ 0xee, 0x59, 0x7b, 0xd6, 0xac, 0x93, 0x7d, 0x99, 0xec, 0xdb, 0x4c, 0x92, 0x4b, 0xcf, 0xab, 0xaf,
+ 0x0a, 0x40, 0x01, 0x24, 0x20, 0xf9, 0x24, 0x56, 0xd5, 0xef, 0xf7, 0xd5, 0xf6, 0xab, 0xef, 0xab,
+ 0xaf, 0x20, 0x00, 0xc7, 0x9c, 0x38, 0x2b, 0xa3, 0xb1, 0xed, 0xd8, 0x24, 0x4b, 0x7f, 0x77, 0x3b,
+ 0x4e, 0xa7, 0x7c, 0x1d, 0xd2, 0x1b, 0x76, 0xc3, 0x3a, 0x1a, 0x92, 0xab, 0x90, 0x38, 0xb4, 0xed,
+ 0x92, 0xa4, 0xca, 0x95, 0x79, 0x6d, 0x6e, 0xc5, 0x45, 0xac, 0x34, 0x5b, 0x2d, 0x83, 0xb6, 0x94,
+ 0xef, 0x40, 0x7e, 0xc3, 0xde, 0x33, 0x27, 0x4e, 0xb3, 0x6f, 0x0e, 0xba, 0x64, 0x11, 0x52, 0x4f,
+ 0x3b, 0xfb, 0xe6, 0x00, 0x19, 0x39, 0x83, 0x15, 0x08, 0x81, 0xe4, 0xde, 0xc9, 0xc8, 0x2c, 0xc9,
+ 0x58, 0x89, 0xbf, 0xcb, 0xbf, 0x72, 0x85, 0x76, 0x42, 0x99, 0xe4, 0x3a, 0x24, 0xbf, 0xdc, 0xb7,
+ 0xba, 0xbc, 0x97, 0xd7, 0xfc, 0x5e, 0x58, 0xfb, 0xca, 0x97, 0x37, 0xb7, 0x1f, 0x1b, 0x08, 0xa1,
+ 0xf6, 0xf7, 0x3a, 0xfb, 0x03, 0x6a, 0x4a, 0xa2, 0xf6, 0xb1, 0x40, 0x6b, 0x77, 0x3a, 0xe3, 0xce,
+ 0xb0, 0x94, 0x50, 0xa5, 0x4a, 0xca, 0x60, 0x05, 0x72, 0x1f, 0xe6, 0x0c, 0xf3, 0xc5, 0x51, 0x7f,
+ 0x6c, 0x76, 0x71, 0x70, 0xa5, 0xa4, 0x2a, 0x57, 0xf2, 0xd3, 0xf6, 0xb1, 0xd1, 0x08, 0x62, 0x19,
+ 0x79, 0x64, 0x76, 0x1c, 0x97, 0x9c, 0x52, 0x13, 0xb1, 0x64, 0x01, 0x4b, 0xc9, 0xad, 0x91, 0xd3,
+ 0xb7, 0xad, 0xce, 0x80, 0x91, 0xd3, 0xaa, 0x14, 0x43, 0x0e, 0x60, 0xc9, 0x9b, 0x50, 0x6c, 0xb6,
+ 0x1f, 0xda, 0xf6, 0xa0, 0x3d, 0xe6, 0x23, 0x2a, 0x81, 0x2a, 0x57, 0xb2, 0xc6, 0x5c, 0x93, 0xd6,
+ 0xba, 0xc3, 0x24, 0x15, 0x50, 0x9a, 0xed, 0x4d, 0xcb, 0xa9, 0x6a, 0x3e, 0x30, 0xaf, 0xca, 0x95,
+ 0x94, 0x31, 0xdf, 0xc4, 0xea, 0x29, 0x64, 0x4d, 0xf7, 0x91, 0x05, 0x55, 0xae, 0x24, 0x18, 0xb2,
+ 0xa6, 0x7b, 0xc8, 0x5b, 0x40, 0x9a, 0xed, 0x66, 0xff, 0xd8, 0xec, 0x8a, 0x56, 0xe7, 0x54, 0xb9,
+ 0x92, 0x31, 0x94, 0x26, 0x6f, 0x98, 0x81, 0x16, 0x2d, 0xcf, 0xab, 0x72, 0x25, 0xed, 0xa2, 0x05,
+ 0xdb, 0x37, 0x60, 0xa1, 0xd9, 0x7e, 0xb7, 0x1f, 0x1c, 0x70, 0x51, 0x95, 0x2b, 0x73, 0x46, 0xb1,
+ 0xc9, 0xea, 0xa7, 0xb1, 0xa2, 0x61, 0x45, 0x95, 0x2b, 0x49, 0x8e, 0x15, 0xec, 0xe2, 0xec, 0x9a,
+ 0x03, 0xbb, 0xe3, 0xf8, 0xd0, 0x05, 0x55, 0xae, 0xc8, 0xc6, 0x7c, 0x13, 0xab, 0x83, 0x56, 0x1f,
+ 0xdb, 0x47, 0xfb, 0x03, 0xd3, 0x87, 0x12, 0x55, 0xae, 0x48, 0x46, 0xb1, 0xc9, 0xea, 0x83, 0xd8,
+ 0x5d, 0x67, 0xdc, 0xb7, 0x7a, 0x3e, 0xf6, 0x3c, 0xea, 0xb7, 0xd8, 0x64, 0xf5, 0xc1, 0x11, 0x3c,
+ 0x3c, 0x71, 0xcc, 0x89, 0x0f, 0x35, 0x55, 0xb9, 0x52, 0x30, 0xe6, 0x9b, 0x58, 0x1d, 0xb2, 0x1a,
+ 0x5a, 0x83, 0x43, 0x55, 0xae, 0x2c, 0x50, 0xab, 0x33, 0xd6, 0x60, 0x37, 0xb4, 0x06, 0x3d, 0x55,
+ 0xae, 0x10, 0x8e, 0x15, 0xd6, 0x40, 0xd4, 0x0c, 0x13, 0x62, 0x69, 0x51, 0x4d, 0x08, 0x9a, 0x61,
+ 0x95, 0x41, 0xcd, 0x70, 0xe0, 0x6b, 0x6a, 0x42, 0xd4, 0x4c, 0x08, 0x89, 0x9d, 0x73, 0xe4, 0x05,
+ 0x35, 0x21, 0x6a, 0x86, 0x23, 0x43, 0x9a, 0xe1, 0xd8, 0xd7, 0xd5, 0x44, 0x50, 0x33, 0x53, 0x68,
+ 0xd1, 0x72, 0x49, 0x4d, 0x04, 0x35, 0xc3, 0xd1, 0x41, 0xcd, 0x70, 0xf0, 0x45, 0x35, 0x11, 0xd0,
+ 0x4c, 0x18, 0x2b, 0x1a, 0x5e, 0x52, 0x13, 0x01, 0xcd, 0x88, 0xb3, 0x73, 0x35, 0xc3, 0xa1, 0xcb,
+ 0x6a, 0x42, 0xd4, 0x8c, 0x68, 0xd5, 0xd3, 0x0c, 0x87, 0x5e, 0x52, 0x13, 0x01, 0xcd, 0x88, 0x58,
+ 0x4f, 0x33, 0x1c, 0x7b, 0x59, 0x4d, 0x04, 0x34, 0xc3, 0xb1, 0xd7, 0x45, 0xcd, 0x70, 0xe8, 0xc7,
+ 0x92, 0x9a, 0x10, 0x45, 0xc3, 0xa1, 0x37, 0x03, 0xa2, 0xe1, 0xd8, 0x4f, 0x28, 0x56, 0x54, 0x4d,
+ 0x18, 0x2c, 0xae, 0xc2, 0xa7, 0x14, 0x2c, 0xca, 0x86, 0x83, 0x7d, 0xd9, 0xd8, 0xdc, 0x05, 0x95,
+ 0xae, 0xa8, 0x92, 0x27, 0x1b, 0xd7, 0x2f, 0x89, 0xb2, 0xf1, 0x80, 0x57, 0xd1, 0xd5, 0x72, 0xd9,
+ 0x4c, 0x21, 0x6b, 0xba, 0x8f, 0x54, 0x55, 0xc9, 0x97, 0x8d, 0x87, 0x0c, 0xc8, 0xc6, 0xc3, 0x5e,
+ 0x53, 0x25, 0x51, 0x36, 0x33, 0xd0, 0xa2, 0xe5, 0xb2, 0x2a, 0x89, 0xb2, 0xf1, 0xd0, 0xa2, 0x6c,
+ 0x3c, 0xf0, 0x17, 0x54, 0x49, 0x90, 0xcd, 0x34, 0x56, 0x34, 0xfc, 0x45, 0x55, 0x12, 0x64, 0x13,
+ 0x9c, 0x1d, 0x93, 0x8d, 0x07, 0x7d, 0x43, 0x95, 0x7c, 0xd9, 0x04, 0xad, 0x72, 0xd9, 0x78, 0xd0,
+ 0x37, 0x55, 0x49, 0x90, 0x4d, 0x10, 0xcb, 0x65, 0xe3, 0x61, 0xdf, 0xc2, 0xf8, 0xe6, 0xca, 0xc6,
+ 0xc3, 0x0a, 0xb2, 0xf1, 0xa0, 0xbf, 0x43, 0x63, 0xa1, 0x27, 0x1b, 0x0f, 0x2a, 0xca, 0xc6, 0xc3,
+ 0xfe, 0x2e, 0xc5, 0xfa, 0xb2, 0x99, 0x06, 0x8b, 0xab, 0xf0, 0x7b, 0x14, 0xec, 0xcb, 0xc6, 0x03,
+ 0xaf, 0xe0, 0x20, 0xa8, 0x6c, 0xba, 0xe6, 0x61, 0xe7, 0x68, 0x40, 0x25, 0x56, 0xa1, 0xba, 0xa9,
+ 0x27, 0x9d, 0xf1, 0x91, 0x49, 0x47, 0x62, 0xdb, 0x83, 0xc7, 0x6e, 0x1b, 0x59, 0xa1, 0xc6, 0x99,
+ 0x7c, 0x7c, 0xc2, 0x75, 0xaa, 0x9f, 0xba, 0x5c, 0xd5, 0x8c, 0x22, 0xd3, 0xd0, 0x34, 0xbe, 0xa6,
+ 0x0b, 0xf8, 0x1b, 0x54, 0x45, 0x75, 0xb9, 0xa6, 0x33, 0x7c, 0x4d, 0xf7, 0xf1, 0x55, 0x38, 0xef,
+ 0x4b, 0xc9, 0x67, 0xdc, 0xa4, 0x5a, 0xaa, 0x27, 0xaa, 0xda, 0xaa, 0xb1, 0xe0, 0x0a, 0x6a, 0x16,
+ 0x29, 0xd0, 0xcd, 0x2d, 0x2a, 0xa9, 0x7a, 0xa2, 0xa6, 0x7b, 0x24, 0xb1, 0x27, 0x8d, 0xca, 0x90,
+ 0x0b, 0xcb, 0xe7, 0xdc, 0xa6, 0xca, 0xaa, 0x27, 0xab, 0xda, 0xea, 0xaa, 0xa1, 0x70, 0x7d, 0xcd,
+ 0xe0, 0x04, 0xfa, 0x59, 0xa1, 0x0a, 0xab, 0x27, 0x6b, 0xba, 0xc7, 0x09, 0xf6, 0xb3, 0xe0, 0x0a,
+ 0xcd, 0xa7, 0x7c, 0x89, 0x2a, 0xad, 0x9e, 0xae, 0xae, 0xe9, 0x6b, 0xeb, 0xf7, 0x8c, 0x22, 0x53,
+ 0x9c, 0xcf, 0xd1, 0x69, 0x3f, 0x5c, 0x72, 0x3e, 0x69, 0x95, 0x6a, 0xae, 0x9e, 0xd6, 0xee, 0xac,
+ 0xdd, 0xd5, 0xee, 0x1a, 0x0a, 0xd7, 0x9e, 0xcf, 0x7a, 0x87, 0xb2, 0xb8, 0xf8, 0x7c, 0xd6, 0x1a,
+ 0x55, 0x5f, 0x5d, 0x79, 0x66, 0x0e, 0x06, 0xf6, 0x2d, 0xb5, 0xfc, 0xd2, 0x1e, 0x0f, 0xba, 0xd7,
+ 0xca, 0x60, 0x28, 0x5c, 0x8f, 0x62, 0xaf, 0x0b, 0xae, 0x20, 0x7d, 0xfa, 0xaf, 0xd1, 0x7b, 0x58,
+ 0xa1, 0x9e, 0x79, 0xd8, 0xef, 0x59, 0xf6, 0xc4, 0x34, 0x8a, 0x4c, 0x9a, 0xa1, 0x35, 0xd9, 0x0d,
+ 0xaf, 0xe3, 0xaf, 0x53, 0xda, 0x42, 0x3d, 0x71, 0xbb, 0xaa, 0xd1, 0x9e, 0x66, 0xad, 0xe3, 0x6e,
+ 0x78, 0x1d, 0x7f, 0x83, 0x72, 0x48, 0x3d, 0x71, 0xbb, 0xa6, 0x73, 0x8e, 0xb8, 0x8e, 0x77, 0xe0,
+ 0x42, 0x28, 0x2e, 0xb6, 0x47, 0x9d, 0x83, 0xe7, 0x66, 0xb7, 0xa4, 0xd1, 0xf0, 0xf8, 0x50, 0x56,
+ 0x24, 0xe3, 0x7c, 0x20, 0x44, 0xee, 0x60, 0x33, 0xb9, 0x07, 0xaf, 0x87, 0x03, 0xa5, 0xcb, 0xac,
+ 0xd2, 0x78, 0x89, 0xcc, 0xc5, 0x60, 0xcc, 0x0c, 0x51, 0x05, 0x07, 0xec, 0x52, 0x75, 0x1a, 0x40,
+ 0x7d, 0xaa, 0xef, 0x89, 0x39, 0xf5, 0x67, 0xe0, 0xe2, 0x74, 0x28, 0x75, 0xc9, 0xeb, 0x34, 0xa2,
+ 0x22, 0xf9, 0x42, 0x38, 0xaa, 0x4e, 0xd1, 0x67, 0xf4, 0x5d, 0xa3, 0x21, 0x56, 0xa4, 0x4f, 0xf5,
+ 0x7e, 0x1f, 0x4a, 0x53, 0xc1, 0xd6, 0x65, 0xdf, 0xa1, 0x31, 0x17, 0xd9, 0xaf, 0x85, 0xe2, 0x6e,
+ 0x98, 0x3c, 0xa3, 0xeb, 0xbb, 0x34, 0x08, 0x0b, 0xe4, 0xa9, 0x9e, 0x71, 0xc9, 0x82, 0xe1, 0xd8,
+ 0xe5, 0xde, 0xa3, 0x51, 0x99, 0x2f, 0x59, 0x20, 0x32, 0x8b, 0xfd, 0x86, 0xe2, 0xb3, 0xcb, 0xad,
+ 0xd3, 0x30, 0xcd, 0xfb, 0x0d, 0x86, 0x6a, 0x4e, 0x7e, 0x9b, 0x92, 0x77, 0x67, 0xcf, 0xf8, 0xc7,
+ 0x09, 0x1a, 0x60, 0x39, 0x7b, 0x77, 0xd6, 0x94, 0x3d, 0xf6, 0x8c, 0x29, 0xff, 0x84, 0xb2, 0x89,
+ 0xc0, 0x9e, 0x9a, 0xf3, 0x63, 0x98, 0x73, 0x6f, 0x75, 0xbd, 0xb1, 0x7d, 0x34, 0x2a, 0x35, 0x55,
+ 0xb9, 0x02, 0xda, 0x95, 0xa9, 0xec, 0xc7, 0xbd, 0xe4, 0x6d, 0x50, 0x94, 0x11, 0x24, 0x31, 0x2b,
+ 0xcc, 0x2e, 0xb3, 0xb2, 0xa3, 0x26, 0x22, 0xac, 0x30, 0x94, 0x67, 0x45, 0x20, 0x51, 0x2b, 0xae,
+ 0xd3, 0x67, 0x56, 0x3e, 0x50, 0xa5, 0x99, 0x56, 0xdc, 0x10, 0xc0, 0xad, 0x04, 0x48, 0x4b, 0xeb,
+ 0x7e, 0xbe, 0x85, 0xed, 0xe4, 0x8b, 0xe1, 0x04, 0x6c, 0x03, 0xef, 0xcf, 0xc1, 0x4a, 0x46, 0x13,
+ 0x06, 0x37, 0x4d, 0xfb, 0xd9, 0x08, 0x5a, 0x60, 0x34, 0xd3, 0xb4, 0x9f, 0x9b, 0x41, 0x2b, 0xff,
+ 0xa6, 0x04, 0x49, 0x9a, 0x4f, 0x92, 0x2c, 0x24, 0xdf, 0x6b, 0x6d, 0x3e, 0x56, 0xce, 0xd1, 0x5f,
+ 0x0f, 0x5b, 0xad, 0xa7, 0x8a, 0x44, 0x72, 0x90, 0x7a, 0xf8, 0x95, 0xbd, 0xc6, 0xae, 0x22, 0x93,
+ 0x22, 0xe4, 0x9b, 0x9b, 0xdb, 0x1b, 0x0d, 0x63, 0xc7, 0xd8, 0xdc, 0xde, 0x53, 0x12, 0xb4, 0xad,
+ 0xf9, 0xb4, 0xf5, 0x60, 0x4f, 0x49, 0x92, 0x0c, 0x24, 0x68, 0x5d, 0x8a, 0x00, 0xa4, 0x77, 0xf7,
+ 0x8c, 0xcd, 0xed, 0x0d, 0x25, 0x4d, 0xad, 0xec, 0x6d, 0x6e, 0x35, 0x94, 0x0c, 0x45, 0xee, 0xbd,
+ 0xbb, 0xf3, 0xb4, 0xa1, 0x64, 0xe9, 0xcf, 0x07, 0x86, 0xf1, 0xe0, 0x2b, 0x4a, 0x8e, 0x92, 0xb6,
+ 0x1e, 0xec, 0x28, 0x80, 0xcd, 0x0f, 0x1e, 0x3e, 0x6d, 0x28, 0x79, 0x52, 0x80, 0x6c, 0xf3, 0xdd,
+ 0xed, 0x47, 0x7b, 0x9b, 0xad, 0x6d, 0xa5, 0x50, 0x3e, 0x81, 0x12, 0x5b, 0xe6, 0xc0, 0x2a, 0xb2,
+ 0xa4, 0xf0, 0x1d, 0x48, 0xb1, 0x9d, 0x91, 0x50, 0x25, 0x95, 0xf0, 0xce, 0x4c, 0x53, 0x56, 0xd8,
+ 0x1e, 0x31, 0xda, 0xd2, 0x65, 0x48, 0xb1, 0x55, 0x5a, 0x84, 0x14, 0x5b, 0x1d, 0x19, 0x53, 0x45,
+ 0x56, 0x28, 0xff, 0x96, 0x0c, 0xb0, 0x61, 0xef, 0x3e, 0xef, 0x8f, 0x30, 0x21, 0xbf, 0x0c, 0x30,
+ 0x79, 0xde, 0x1f, 0xb5, 0x51, 0xf5, 0x3c, 0xa9, 0xcc, 0xd1, 0x1a, 0xf4, 0x77, 0xe4, 0x1a, 0x14,
+ 0xb0, 0xf9, 0x90, 0x79, 0x21, 0xcc, 0x25, 0x33, 0x46, 0x9e, 0xd6, 0x71, 0xc7, 0x14, 0x84, 0xd4,
+ 0x74, 0x4c, 0x21, 0xd3, 0x02, 0xa4, 0xa6, 0x93, 0xab, 0x80, 0xc5, 0xf6, 0x04, 0x23, 0x0a, 0xa6,
+ 0x8d, 0x39, 0x03, 0xfb, 0x65, 0x31, 0x86, 0xbc, 0x0d, 0xd8, 0x27, 0x9b, 0x77, 0x71, 0xfa, 0x74,
+ 0xb8, 0xc3, 0x5d, 0xa1, 0x3f, 0xd8, 0x6c, 0x7d, 0xc2, 0x52, 0x0b, 0x72, 0x5e, 0x3d, 0xed, 0x0b,
+ 0x6b, 0xf9, 0x8c, 0x14, 0x9c, 0x11, 0x60, 0x95, 0x37, 0x25, 0x06, 0xe0, 0xa3, 0x59, 0xc0, 0xd1,
+ 0x30, 0x12, 0x1b, 0x4e, 0xf9, 0x32, 0xcc, 0x6d, 0xdb, 0x16, 0x3b, 0xbd, 0xb8, 0x4a, 0x05, 0x90,
+ 0x3a, 0x25, 0x09, 0xb3, 0x27, 0xa9, 0x53, 0xbe, 0x02, 0x20, 0xb4, 0x29, 0x20, 0xed, 0xb3, 0x36,
+ 0xf4, 0x01, 0xd2, 0x7e, 0xf9, 0x26, 0xa4, 0xb7, 0x3a, 0xc7, 0x7b, 0x9d, 0x1e, 0xb9, 0x06, 0x30,
+ 0xe8, 0x4c, 0x9c, 0xf6, 0x21, 0xee, 0xc3, 0xe7, 0x9f, 0x7f, 0xfe, 0xb9, 0x84, 0x97, 0xbd, 0x1c,
+ 0xad, 0x65, 0xfb, 0xf1, 0x02, 0xa0, 0x35, 0xe8, 0x6e, 0x99, 0x93, 0x49, 0xa7, 0x67, 0x92, 0x2a,
+ 0xa4, 0x2d, 0x73, 0x42, 0xa3, 0x9d, 0x84, 0xef, 0x08, 0xcb, 0xfe, 0x2a, 0xf8, 0xa8, 0x95, 0x6d,
+ 0x84, 0x18, 0x1c, 0x4a, 0x14, 0x48, 0x58, 0x47, 0x43, 0x7c, 0x27, 0x49, 0x19, 0xf4, 0xe7, 0xd2,
+ 0x25, 0x48, 0x33, 0x0c, 0x21, 0x90, 0xb4, 0x3a, 0x43, 0xb3, 0xc4, 0xfa, 0xc5, 0xdf, 0xe5, 0x5f,
+ 0x95, 0x00, 0xb6, 0xcd, 0x97, 0x67, 0xe8, 0xd3, 0x47, 0xc5, 0xf4, 0x99, 0x60, 0x7d, 0xde, 0x8f,
+ 0xeb, 0x93, 0xea, 0xec, 0xd0, 0xb6, 0xbb, 0x6d, 0xb6, 0xc5, 0xec, 0x49, 0x27, 0x47, 0x6b, 0x70,
+ 0xd7, 0xca, 0x1f, 0x40, 0x61, 0xd3, 0xb2, 0xcc, 0xb1, 0x3b, 0x26, 0x02, 0xc9, 0x67, 0xf6, 0xc4,
+ 0xe1, 0x6f, 0x4b, 0xf8, 0x9b, 0x94, 0x20, 0x39, 0xb2, 0xc7, 0x0e, 0x9b, 0x67, 0x3d, 0xa9, 0xaf,
+ 0xae, 0xae, 0x1a, 0x58, 0x43, 0x2e, 0x41, 0xee, 0xc0, 0xb6, 0x2c, 0xf3, 0x80, 0x4e, 0x22, 0x81,
+ 0x69, 0x8d, 0x5f, 0x51, 0xfe, 0x65, 0x09, 0x0a, 0x2d, 0xe7, 0x99, 0x6f, 0x5c, 0x81, 0xc4, 0x73,
+ 0xf3, 0x04, 0x87, 0x97, 0x30, 0xe8, 0x4f, 0x7a, 0x54, 0x7e, 0xbe, 0x33, 0x38, 0x62, 0x6f, 0x4d,
+ 0x05, 0x83, 0x15, 0xc8, 0x05, 0x48, 0xbf, 0x34, 0xfb, 0xbd, 0x67, 0x0e, 0xda, 0x94, 0x0d, 0x5e,
+ 0x22, 0xb7, 0x20, 0xd5, 0xa7, 0x83, 0x2d, 0x25, 0x71, 0xbd, 0x2e, 0xf8, 0xeb, 0x25, 0xce, 0xc1,
+ 0x60, 0xa0, 0x1b, 0xd9, 0x6c, 0x57, 0xf9, 0xe8, 0xa3, 0x8f, 0x3e, 0x92, 0xcb, 0x87, 0xb0, 0xe8,
+ 0x1e, 0xde, 0xc0, 0x64, 0xb7, 0xa1, 0x34, 0x30, 0xed, 0xf6, 0x61, 0xdf, 0xea, 0x0c, 0x06, 0x27,
+ 0xed, 0x97, 0xb6, 0xd5, 0xee, 0x58, 0x6d, 0x7b, 0x72, 0xd0, 0x19, 0xe3, 0x02, 0x44, 0x77, 0xb1,
+ 0x38, 0x30, 0xed, 0x26, 0xa3, 0xbd, 0x6f, 0x5b, 0x0f, 0xac, 0x16, 0xe5, 0x94, 0xff, 0x20, 0x09,
+ 0xb9, 0xad, 0x13, 0xd7, 0xfa, 0x22, 0xa4, 0x0e, 0xec, 0x23, 0x8b, 0xad, 0x65, 0xca, 0x60, 0x05,
+ 0x6f, 0x8f, 0x64, 0x61, 0x8f, 0x16, 0x21, 0xf5, 0xe2, 0xc8, 0x76, 0x4c, 0x9c, 0x6e, 0xce, 0x60,
+ 0x05, 0xba, 0x5a, 0x23, 0xd3, 0x29, 0x25, 0x31, 0xb9, 0xa5, 0x3f, 0xfd, 0xf9, 0xa7, 0xce, 0x30,
+ 0x7f, 0xb2, 0x02, 0x69, 0x9b, 0xae, 0xfe, 0xa4, 0x94, 0xc6, 0x77, 0x35, 0x01, 0x2e, 0xee, 0x8a,
+ 0xc1, 0x51, 0x64, 0x13, 0x16, 0x5e, 0x9a, 0xed, 0xe1, 0xd1, 0xc4, 0x69, 0xf7, 0xec, 0x76, 0xd7,
+ 0x34, 0x47, 0xe6, 0xb8, 0x34, 0x87, 0x3d, 0x09, 0x3e, 0x61, 0xd6, 0x42, 0x1a, 0xf3, 0x2f, 0xcd,
+ 0xad, 0xa3, 0x89, 0xb3, 0x61, 0x3f, 0x46, 0x16, 0xa9, 0x42, 0x6e, 0x6c, 0x52, 0x4f, 0x40, 0x07,
+ 0x5b, 0x08, 0xf7, 0x1e, 0xa0, 0x66, 0xc7, 0xe6, 0x08, 0x2b, 0xc8, 0x3a, 0x64, 0xf7, 0xfb, 0xcf,
+ 0xcd, 0xc9, 0x33, 0xb3, 0x5b, 0xca, 0xa8, 0x52, 0x65, 0x5e, 0xbb, 0xe8, 0x73, 0xbc, 0x65, 0x5d,
+ 0x79, 0x64, 0x0f, 0xec, 0xb1, 0xe1, 0x41, 0xc9, 0x7d, 0xc8, 0x4d, 0xec, 0xa1, 0xc9, 0xf4, 0x9d,
+ 0xc5, 0xa0, 0x7a, 0x79, 0x16, 0x6f, 0xd7, 0x1e, 0x9a, 0xae, 0x07, 0x73, 0xf1, 0x64, 0x99, 0x0d,
+ 0x74, 0x9f, 0x5e, 0x9d, 0x4b, 0x80, 0x4f, 0x03, 0x74, 0x40, 0x78, 0x95, 0x26, 0x4b, 0x74, 0x40,
+ 0xbd, 0x43, 0x7a, 0x23, 0x2a, 0xe5, 0x31, 0xaf, 0xf4, 0xca, 0x4b, 0xb7, 0x20, 0xe7, 0x19, 0xf4,
+ 0x5d, 0x1f, 0x73, 0x37, 0x39, 0xf4, 0x07, 0xcc, 0xf5, 0x31, 0x5f, 0xf3, 0x06, 0xa4, 0x70, 0xd8,
+ 0x34, 0x42, 0x19, 0x0d, 0x1a, 0x10, 0x73, 0x90, 0xda, 0x30, 0x1a, 0x8d, 0x6d, 0x45, 0xc2, 0xd8,
+ 0xf8, 0xf4, 0xdd, 0x86, 0x22, 0x0b, 0x8a, 0xfd, 0x6d, 0x09, 0x12, 0x8d, 0x63, 0x54, 0x0b, 0x9d,
+ 0x86, 0x7b, 0xa2, 0xe9, 0x6f, 0xad, 0x06, 0xc9, 0xa1, 0x3d, 0x36, 0xc9, 0xf9, 0x19, 0xb3, 0x2c,
+ 0xf5, 0x70, 0xbf, 0x84, 0x57, 0xe4, 0xc6, 0xb1, 0x63, 0x20, 0x5e, 0x7b, 0x0b, 0x92, 0x8e, 0x79,
+ 0xec, 0xcc, 0xe6, 0x3d, 0x63, 0x1d, 0x50, 0x80, 0x76, 0x13, 0xd2, 0xd6, 0xd1, 0x70, 0xdf, 0x1c,
+ 0xcf, 0x86, 0xf6, 0x71, 0x7a, 0x1c, 0x52, 0x7e, 0x0f, 0x94, 0x47, 0xf6, 0x70, 0x34, 0x30, 0x8f,
+ 0x1b, 0xc7, 0x8e, 0x69, 0x4d, 0xfa, 0xb6, 0x45, 0xf5, 0x7c, 0xd8, 0x1f, 0xa3, 0x17, 0xc1, 0xb7,
+ 0x62, 0x2c, 0xd0, 0x53, 0x3d, 0x31, 0x0f, 0x6c, 0xab, 0xcb, 0x1d, 0x26, 0x2f, 0x51, 0xb4, 0xf3,
+ 0xac, 0x3f, 0xa6, 0x0e, 0x84, 0xfa, 0x79, 0x56, 0x28, 0x6f, 0x40, 0x91, 0xe7, 0x18, 0x13, 0xde,
+ 0x71, 0xf9, 0x06, 0x14, 0xdc, 0x2a, 0x7c, 0x38, 0xcf, 0x42, 0xf2, 0x83, 0x86, 0xd1, 0x52, 0xce,
+ 0xd1, 0x65, 0x6d, 0x6d, 0x37, 0x14, 0x89, 0xfe, 0xd8, 0x7b, 0xbf, 0x15, 0x58, 0xca, 0x4b, 0x50,
+ 0xf0, 0xc6, 0xbe, 0x6b, 0x3a, 0xd8, 0x42, 0x03, 0x42, 0xa6, 0x2e, 0x67, 0xa5, 0x72, 0x06, 0x52,
+ 0x8d, 0xe1, 0xc8, 0x39, 0x29, 0xff, 0x22, 0xe4, 0x39, 0xe8, 0x69, 0x7f, 0xe2, 0x90, 0x3b, 0x90,
+ 0x19, 0xf2, 0xf9, 0x4a, 0x78, 0xdd, 0x13, 0x35, 0xe5, 0xe3, 0xdc, 0xdf, 0x86, 0x8b, 0x5e, 0xaa,
+ 0x42, 0x46, 0xf0, 0xa5, 0xfc, 0xa8, 0xcb, 0xe2, 0x51, 0x67, 0x4e, 0x21, 0x21, 0x38, 0x85, 0xf2,
+ 0x16, 0x64, 0x58, 0x04, 0x9c, 0x60, 0x54, 0x67, 0xa9, 0x22, 0x13, 0x13, 0xdb, 0xf9, 0x3c, 0xab,
+ 0x63, 0x17, 0x95, 0xab, 0x90, 0x47, 0xc1, 0x72, 0x04, 0x73, 0x9d, 0x80, 0x55, 0x4c, 0x6e, 0xbf,
+ 0x9f, 0x82, 0xac, 0xbb, 0x52, 0x64, 0x19, 0xd2, 0x2c, 0x3f, 0x43, 0x53, 0xee, 0xfb, 0x41, 0x0a,
+ 0x33, 0x32, 0xb2, 0x0c, 0x19, 0x9e, 0x83, 0x71, 0xef, 0x2e, 0x57, 0x35, 0x23, 0xcd, 0x72, 0x2e,
+ 0xaf, 0xb1, 0xa6, 0xa3, 0x63, 0x62, 0x2f, 0x03, 0x69, 0x96, 0x55, 0x11, 0x15, 0x72, 0x5e, 0x1e,
+ 0x85, 0xfe, 0x98, 0x3f, 0x03, 0x64, 0xdd, 0xc4, 0x49, 0x40, 0xd4, 0x74, 0xf4, 0x58, 0x3c, 0xe7,
+ 0xcf, 0x36, 0xfd, 0xeb, 0x49, 0xd6, 0xcd, 0x86, 0xf0, 0xf9, 0xde, 0x4d, 0xf0, 0x33, 0x3c, 0xff,
+ 0xf1, 0x01, 0x35, 0x1d, 0x5d, 0x82, 0x9b, 0xcd, 0x67, 0x78, 0x8e, 0x43, 0xae, 0xd2, 0x21, 0x62,
+ 0xce, 0x82, 0x47, 0xdf, 0x4f, 0xdd, 0xd3, 0x2c, 0x93, 0x21, 0xd7, 0xa8, 0x05, 0x96, 0x98, 0xe0,
+ 0xb9, 0xf4, 0xf3, 0xf4, 0x0c, 0xcf, 0x57, 0xc8, 0x4d, 0x0a, 0x61, 0xcb, 0x5f, 0x82, 0x88, 0xa4,
+ 0x3c, 0xc3, 0x93, 0x72, 0xa2, 0xd2, 0x0e, 0xd1, 0x3d, 0xa0, 0x4b, 0x10, 0x12, 0xf0, 0x34, 0x4b,
+ 0xc0, 0xc9, 0x15, 0x34, 0xc7, 0x26, 0x55, 0xf0, 0x93, 0xed, 0x0c, 0x4f, 0x70, 0xfc, 0x76, 0xbc,
+ 0xb2, 0x79, 0x89, 0x75, 0x86, 0xa7, 0x30, 0xa4, 0x46, 0xf7, 0x8b, 0xea, 0xbb, 0x34, 0x8f, 0x4e,
+ 0xb0, 0xe4, 0x0b, 0xcf, 0xdd, 0x53, 0xe6, 0x03, 0xeb, 0xcc, 0x83, 0x18, 0xa9, 0x26, 0x9e, 0x86,
+ 0x25, 0xca, 0xdb, 0xe9, 0x5b, 0x87, 0xa5, 0x22, 0xae, 0x44, 0xa2, 0x6f, 0x1d, 0x1a, 0xa9, 0x26,
+ 0xad, 0x61, 0x1a, 0xd8, 0xa6, 0x6d, 0x0a, 0xb6, 0x25, 0x6f, 0xb3, 0x46, 0x5a, 0x45, 0x4a, 0x90,
+ 0x6a, 0xb6, 0xb7, 0x3b, 0x56, 0x69, 0x81, 0xf1, 0xac, 0x8e, 0x65, 0x24, 0x9b, 0xdb, 0x1d, 0x8b,
+ 0xbc, 0x05, 0x89, 0xc9, 0xd1, 0x7e, 0x89, 0x84, 0xbf, 0xac, 0xec, 0x1e, 0xed, 0xbb, 0x43, 0x31,
+ 0x28, 0x82, 0x2c, 0x43, 0x76, 0xe2, 0x8c, 0xdb, 0xbf, 0x60, 0x8e, 0xed, 0xd2, 0x79, 0x5c, 0xc2,
+ 0x73, 0x46, 0x66, 0xe2, 0x8c, 0x3f, 0x30, 0xc7, 0xf6, 0x19, 0x9d, 0x5f, 0xf9, 0x0a, 0xe4, 0x05,
+ 0xbb, 0xa4, 0x08, 0x92, 0xc5, 0x6e, 0x0a, 0x75, 0xe9, 0x8e, 0x21, 0x59, 0xe5, 0x3d, 0x28, 0xb8,
+ 0x39, 0x0c, 0xce, 0x57, 0xa3, 0x27, 0x69, 0x60, 0x8f, 0xf1, 0x7c, 0xce, 0x6b, 0x97, 0xc4, 0x10,
+ 0xe5, 0xc3, 0x78, 0xb8, 0x60, 0xd0, 0xb2, 0x12, 0x1a, 0x8a, 0x54, 0xfe, 0xa1, 0x04, 0x85, 0x2d,
+ 0x7b, 0xec, 0x3f, 0x30, 0x2f, 0x42, 0x6a, 0xdf, 0xb6, 0x07, 0x13, 0x34, 0x9b, 0x35, 0x58, 0x81,
+ 0xbc, 0x01, 0x05, 0xfc, 0xe1, 0xe6, 0x9e, 0xb2, 0xf7, 0xb4, 0x91, 0xc7, 0x7a, 0x9e, 0x70, 0x12,
+ 0x48, 0xf6, 0x2d, 0x67, 0xc2, 0x3d, 0x19, 0xfe, 0x26, 0x5f, 0x80, 0x3c, 0xfd, 0xeb, 0x32, 0x93,
+ 0xde, 0x85, 0x15, 0x68, 0x35, 0x27, 0xbe, 0x05, 0x73, 0xb8, 0xfb, 0x1e, 0x2c, 0xe3, 0x3d, 0x63,
+ 0x14, 0x58, 0x03, 0x07, 0x96, 0x20, 0xc3, 0x5c, 0xc1, 0x04, 0xbf, 0x96, 0xe5, 0x0c, 0xb7, 0x48,
+ 0xdd, 0x2b, 0x66, 0x02, 0x2c, 0xdc, 0x67, 0x0c, 0x5e, 0x2a, 0x3f, 0x80, 0x2c, 0x46, 0xa9, 0xd6,
+ 0xa0, 0x4b, 0xca, 0x20, 0xf5, 0x4a, 0x26, 0xc6, 0xc8, 0x45, 0xe1, 0x9a, 0xcf, 0x9b, 0x57, 0x36,
+ 0x0c, 0xa9, 0xb7, 0xb4, 0x00, 0xd2, 0x06, 0xbd, 0x77, 0x1f, 0x73, 0x37, 0x2d, 0x1d, 0x97, 0x5b,
+ 0xdc, 0xc4, 0xb6, 0xf9, 0x32, 0xce, 0xc4, 0xb6, 0xf9, 0x92, 0x99, 0xb8, 0x3a, 0x65, 0x82, 0x96,
+ 0x4e, 0xf8, 0xa7, 0x43, 0xe9, 0xa4, 0x5c, 0x85, 0x39, 0x3c, 0x9e, 0x7d, 0xab, 0xb7, 0x63, 0xf7,
+ 0x2d, 0xbc, 0xe7, 0x1f, 0xe2, 0x3d, 0x49, 0x32, 0xa4, 0x43, 0xba, 0x07, 0xe6, 0x71, 0xe7, 0x80,
+ 0xdd, 0x38, 0xb3, 0x06, 0x2b, 0x94, 0x3f, 0x4b, 0xc2, 0x3c, 0x77, 0xad, 0xef, 0xf7, 0x9d, 0x67,
+ 0x5b, 0x9d, 0x11, 0x79, 0x0a, 0x05, 0xea, 0x55, 0xdb, 0xc3, 0xce, 0x68, 0x44, 0x8f, 0xaf, 0x84,
+ 0x57, 0x8d, 0xeb, 0x53, 0xae, 0x9a, 0xe3, 0x57, 0xb6, 0x3b, 0x43, 0x73, 0x8b, 0x61, 0x1b, 0x96,
+ 0x33, 0x3e, 0x31, 0xf2, 0x96, 0x5f, 0x43, 0x36, 0x21, 0x3f, 0x9c, 0xf4, 0x3c, 0x63, 0x32, 0x1a,
+ 0xab, 0x44, 0x1a, 0xdb, 0x9a, 0xf4, 0x02, 0xb6, 0x60, 0xe8, 0x55, 0xd0, 0x81, 0x51, 0x7f, 0xec,
+ 0xd9, 0x4a, 0x9c, 0x32, 0x30, 0xea, 0x3a, 0x82, 0x03, 0xdb, 0xf7, 0x6b, 0xc8, 0x63, 0x00, 0x7a,
+ 0xbc, 0x1c, 0x9b, 0xa6, 0x4e, 0xa8, 0xa0, 0xbc, 0xf6, 0x66, 0xa4, 0xad, 0x5d, 0x67, 0xbc, 0x67,
+ 0xef, 0x3a, 0x63, 0x66, 0x88, 0x1e, 0x4c, 0x2c, 0x2e, 0xbd, 0x03, 0x4a, 0x78, 0xfe, 0xe2, 0x8d,
+ 0x3c, 0x35, 0xe3, 0x46, 0x9e, 0xe3, 0x37, 0xf2, 0xba, 0x7c, 0x57, 0x5a, 0x7a, 0x0f, 0x8a, 0xa1,
+ 0x29, 0x8b, 0x74, 0xc2, 0xe8, 0xb7, 0x45, 0x7a, 0x5e, 0x7b, 0x5d, 0xf8, 0x9c, 0x2d, 0x6e, 0xb8,
+ 0x68, 0xf7, 0x1d, 0x50, 0xc2, 0xd3, 0x17, 0x0d, 0x67, 0x63, 0x32, 0x05, 0xe4, 0xdf, 0x87, 0xb9,
+ 0xc0, 0x94, 0x45, 0x72, 0xee, 0x94, 0x49, 0x95, 0x7f, 0x29, 0x05, 0xa9, 0x96, 0x65, 0xda, 0x87,
+ 0xe4, 0xf5, 0x60, 0x9c, 0x7c, 0x72, 0xce, 0x8d, 0x91, 0x17, 0x43, 0x31, 0xf2, 0xc9, 0x39, 0x2f,
+ 0x42, 0x5e, 0x0c, 0x45, 0x48, 0xb7, 0xa9, 0xa6, 0x93, 0xcb, 0x53, 0xf1, 0xf1, 0xc9, 0x39, 0x21,
+ 0x38, 0x5e, 0x9e, 0x0a, 0x8e, 0x7e, 0x73, 0x4d, 0xa7, 0x0e, 0x35, 0x18, 0x19, 0x9f, 0x9c, 0xf3,
+ 0xa3, 0xe2, 0x72, 0x38, 0x2a, 0x7a, 0x8d, 0x35, 0x9d, 0x0d, 0x49, 0x88, 0x88, 0x38, 0x24, 0x16,
+ 0x0b, 0x97, 0xc3, 0xb1, 0x10, 0x79, 0x3c, 0x0a, 0x2e, 0x87, 0xa3, 0x20, 0x36, 0xf2, 0xa8, 0x77,
+ 0x31, 0x14, 0xf5, 0xd0, 0x28, 0x0b, 0x77, 0xcb, 0xe1, 0x70, 0xc7, 0x78, 0xc2, 0x48, 0xc5, 0x58,
+ 0xe7, 0x35, 0xd6, 0x74, 0xa2, 0x85, 0x02, 0x5d, 0xf4, 0x6d, 0x1f, 0xf7, 0x02, 0x9d, 0xbe, 0x4e,
+ 0x97, 0xcd, 0xbd, 0x88, 0x16, 0x63, 0xbe, 0xf8, 0xe3, 0x6a, 0xba, 0x17, 0x31, 0x0d, 0x32, 0x87,
+ 0x3c, 0x01, 0x56, 0xd0, 0x73, 0x09, 0xb2, 0xc4, 0xcd, 0x5f, 0x69, 0xb6, 0xd1, 0x83, 0xd1, 0x79,
+ 0x1d, 0xb2, 0x3b, 0x7d, 0x05, 0xe6, 0x9a, 0xed, 0xa7, 0x9d, 0x71, 0xcf, 0x9c, 0x38, 0xed, 0xbd,
+ 0x4e, 0xcf, 0x7b, 0x44, 0xa0, 0xfb, 0x9f, 0x6f, 0xf2, 0x96, 0xbd, 0x4e, 0x8f, 0x5c, 0x70, 0xc5,
+ 0xd5, 0xc5, 0x56, 0x89, 0xcb, 0x6b, 0xe9, 0x75, 0xba, 0x68, 0xcc, 0x18, 0xfa, 0xc2, 0x05, 0xee,
+ 0x0b, 0x1f, 0x66, 0x20, 0x75, 0x64, 0xf5, 0x6d, 0xeb, 0x61, 0x0e, 0x32, 0x8e, 0x3d, 0x1e, 0x76,
+ 0x1c, 0xbb, 0xfc, 0x23, 0x09, 0xe0, 0x91, 0x3d, 0x1c, 0x1e, 0x59, 0xfd, 0x17, 0x47, 0x26, 0xb9,
+ 0x02, 0xf9, 0x61, 0xe7, 0xb9, 0xd9, 0x1e, 0x9a, 0xed, 0x83, 0xb1, 0x7b, 0x0e, 0x72, 0xb4, 0x6a,
+ 0xcb, 0x7c, 0x34, 0x3e, 0x21, 0x25, 0xf7, 0x8a, 0x8e, 0xda, 0x41, 0x49, 0xf2, 0x2b, 0xfb, 0x22,
+ 0xbf, 0x74, 0xa6, 0xf9, 0x1e, 0xba, 0xd7, 0x4e, 0x96, 0x47, 0x64, 0xf8, 0xee, 0x61, 0x89, 0x4a,
+ 0xde, 0x31, 0x87, 0xa3, 0xf6, 0x01, 0x4a, 0x85, 0xca, 0x21, 0x45, 0xcb, 0x8f, 0xc8, 0x6d, 0x48,
+ 0x1c, 0xd8, 0x03, 0x14, 0xc9, 0x29, 0xfb, 0x42, 0x71, 0xe4, 0x0d, 0x48, 0x0c, 0x27, 0x4c, 0x36,
+ 0x79, 0x6d, 0x41, 0xb8, 0x27, 0xb0, 0xd0, 0x44, 0x61, 0xc3, 0x49, 0xcf, 0x9b, 0xf7, 0x8d, 0x22,
+ 0x24, 0x9a, 0xad, 0x16, 0x8d, 0xfd, 0xcd, 0x56, 0x6b, 0x4d, 0x91, 0xea, 0x5f, 0x82, 0x6c, 0x6f,
+ 0x6c, 0x9a, 0xd4, 0x3d, 0xcc, 0xce, 0x39, 0x3e, 0xc4, 0x58, 0xe7, 0x81, 0xea, 0x5b, 0x90, 0x39,
+ 0x60, 0x59, 0x07, 0x89, 0x48, 0x6b, 0x4b, 0x7f, 0xc8, 0x1e, 0x55, 0x96, 0xfc, 0xe6, 0x70, 0x9e,
+ 0x62, 0xb8, 0x36, 0xea, 0x3b, 0x90, 0x1b, 0xb7, 0x4f, 0x33, 0xf8, 0x31, 0x8b, 0x2e, 0x71, 0x06,
+ 0xb3, 0x63, 0x5e, 0x55, 0x6f, 0xc0, 0x82, 0x65, 0xbb, 0xdf, 0x50, 0xda, 0x5d, 0x76, 0xc6, 0x2e,
+ 0x4e, 0x5f, 0xe5, 0x5c, 0xe3, 0x26, 0xfb, 0x6e, 0x69, 0xd9, 0xbc, 0x81, 0x9d, 0xca, 0xfa, 0x23,
+ 0x50, 0x04, 0x33, 0x98, 0x7a, 0xc6, 0x59, 0x39, 0x64, 0x1f, 0x4a, 0x3d, 0x2b, 0x78, 0xee, 0x43,
+ 0x46, 0xd8, 0xc9, 0x8c, 0x31, 0xd2, 0x63, 0x5f, 0x9d, 0x3d, 0x23, 0xe8, 0xea, 0xa6, 0x8d, 0x50,
+ 0x5f, 0x13, 0x6d, 0xe4, 0x19, 0xfb, 0x20, 0x2d, 0x1a, 0xa9, 0xe9, 0xa1, 0x55, 0x39, 0x3a, 0x75,
+ 0x28, 0x7d, 0xf6, 0x3d, 0xd9, 0xb3, 0xc2, 0x1c, 0xe0, 0x0c, 0x33, 0xf1, 0x83, 0xf9, 0x90, 0x7d,
+ 0x6a, 0x0e, 0x98, 0x99, 0x1a, 0xcd, 0xe4, 0xd4, 0xd1, 0x3c, 0x67, 0xdf, 0x75, 0x3d, 0x33, 0xbb,
+ 0xb3, 0x46, 0x33, 0x39, 0x75, 0x34, 0x03, 0xf6, 0xc5, 0x37, 0x60, 0xa6, 0xa6, 0xd7, 0x37, 0x80,
+ 0x88, 0x5b, 0xcd, 0xe3, 0x44, 0x8c, 0x9d, 0x21, 0xfb, 0x8e, 0xef, 0x6f, 0x36, 0xa3, 0xcc, 0x32,
+ 0x14, 0x3f, 0x20, 0x8b, 0x7d, 0xe2, 0x0f, 0x1a, 0xaa, 0xe9, 0xf5, 0x4d, 0x38, 0x2f, 0x4e, 0xec,
+ 0x0c, 0x43, 0xb2, 0x55, 0xa9, 0x52, 0x34, 0x16, 0xfc, 0xa9, 0x71, 0xce, 0x4c, 0x53, 0xf1, 0x83,
+ 0x1a, 0xa9, 0x52, 0x45, 0x99, 0x32, 0x55, 0xd3, 0xeb, 0x0f, 0xa0, 0x28, 0x98, 0xda, 0xc7, 0x08,
+ 0x1d, 0x6d, 0xe6, 0x05, 0xfb, 0x5f, 0x0b, 0xcf, 0x0c, 0x8d, 0xe8, 0xe1, 0x1d, 0xe3, 0x31, 0x2e,
+ 0xda, 0xc8, 0x98, 0xfd, 0xa3, 0x80, 0x3f, 0x16, 0x64, 0x84, 0x8e, 0x04, 0xe6, 0xdf, 0x71, 0x56,
+ 0x26, 0xec, 0x5f, 0x08, 0xfc, 0xa1, 0x50, 0x42, 0xbd, 0x1f, 0x98, 0x8e, 0x49, 0x83, 0x5c, 0x8c,
+ 0x0d, 0x07, 0x3d, 0xf2, 0x9b, 0x91, 0x80, 0x15, 0xf1, 0x81, 0x44, 0x98, 0x36, 0x2d, 0xd6, 0x37,
+ 0x61, 0xfe, 0xec, 0x0e, 0xe9, 0x63, 0x89, 0x65, 0xcb, 0xd5, 0x15, 0x9a, 0x50, 0x1b, 0x73, 0xdd,
+ 0x80, 0x5f, 0x6a, 0xc0, 0xdc, 0x99, 0x9d, 0xd2, 0x27, 0x12, 0xcb, 0x39, 0xa9, 0x25, 0xa3, 0xd0,
+ 0x0d, 0x7a, 0xa6, 0xb9, 0x33, 0xbb, 0xa5, 0x4f, 0x25, 0xf6, 0x40, 0xa1, 0x6b, 0x9e, 0x11, 0xd7,
+ 0x33, 0xcd, 0x9d, 0xd9, 0x2d, 0x7d, 0x95, 0x65, 0x94, 0xb2, 0x5e, 0x15, 0x8d, 0xa0, 0x2f, 0x98,
+ 0x3f, 0xbb, 0x5b, 0xfa, 0x9a, 0x84, 0x8f, 0x15, 0xb2, 0xae, 0x7b, 0xeb, 0xe2, 0x79, 0xa6, 0xf9,
+ 0xb3, 0xbb, 0xa5, 0xaf, 0x4b, 0xf8, 0xa4, 0x21, 0xeb, 0xeb, 0x01, 0x33, 0xc1, 0xd1, 0x9c, 0xee,
+ 0x96, 0xbe, 0x21, 0xe1, 0x2b, 0x83, 0xac, 0xd7, 0x3c, 0x33, 0xbb, 0x53, 0xa3, 0x39, 0xdd, 0x2d,
+ 0x7d, 0x13, 0x6f, 0xf1, 0x75, 0x59, 0xbf, 0x13, 0x30, 0x83, 0x9e, 0xa9, 0xf8, 0x0a, 0x6e, 0xe9,
+ 0x5b, 0x12, 0x3e, 0x06, 0xc9, 0xfa, 0x5d, 0xc3, 0xed, 0xdd, 0xf7, 0x4c, 0xc5, 0x57, 0x70, 0x4b,
+ 0x9f, 0x49, 0xf8, 0x66, 0x24, 0xeb, 0xf7, 0x82, 0x86, 0xd0, 0x33, 0x29, 0xaf, 0xe2, 0x96, 0xbe,
+ 0x4d, 0x2d, 0x15, 0xeb, 0xf2, 0xfa, 0xaa, 0xe1, 0x0e, 0x40, 0xf0, 0x4c, 0xca, 0xab, 0xb8, 0xa5,
+ 0xef, 0x50, 0x53, 0x4a, 0x5d, 0x5e, 0x5f, 0x0b, 0x99, 0xaa, 0xe9, 0xf5, 0x47, 0x50, 0x38, 0xab,
+ 0x5b, 0xfa, 0xae, 0xf8, 0x16, 0x97, 0xef, 0x0a, 0xbe, 0x69, 0x47, 0xd8, 0xb3, 0x53, 0x1d, 0xd3,
+ 0xf7, 0x30, 0xc7, 0xa9, 0xcf, 0x3d, 0x61, 0xef, 0x55, 0x8c, 0xe0, 0x6f, 0x1f, 0x73, 0x53, 0x5b,
+ 0xfe, 0xf9, 0x38, 0xd5, 0x47, 0x7d, 0x5f, 0xc2, 0x47, 0xad, 0x02, 0x37, 0x88, 0x78, 0xef, 0xa4,
+ 0x30, 0x87, 0xf5, 0xa1, 0x3f, 0xcb, 0xd3, 0xbc, 0xd5, 0x0f, 0xa4, 0x57, 0x71, 0x57, 0xf5, 0x44,
+ 0x6b, 0xbb, 0xe1, 0x2d, 0x06, 0xd6, 0xbc, 0x0d, 0xc9, 0x63, 0x6d, 0x75, 0x4d, 0xbc, 0x92, 0x89,
+ 0x6f, 0xb9, 0xcc, 0x49, 0xe5, 0xb5, 0xa2, 0xf0, 0xdc, 0x3d, 0x1c, 0x39, 0x27, 0x06, 0xb2, 0x38,
+ 0x5b, 0x8b, 0x64, 0x7f, 0x12, 0xc3, 0xd6, 0x38, 0xbb, 0x1a, 0xc9, 0xfe, 0x34, 0x86, 0x5d, 0xe5,
+ 0x6c, 0x3d, 0x92, 0xfd, 0xd5, 0x18, 0xb6, 0xce, 0xd9, 0xeb, 0x91, 0xec, 0xaf, 0xc5, 0xb0, 0xd7,
+ 0x39, 0xbb, 0x16, 0xc9, 0xfe, 0x7a, 0x0c, 0xbb, 0xc6, 0xd9, 0x77, 0x22, 0xd9, 0xdf, 0x88, 0x61,
+ 0xdf, 0xe1, 0xec, 0xbb, 0x91, 0xec, 0x6f, 0xc6, 0xb0, 0xef, 0x72, 0xf6, 0xbd, 0x48, 0xf6, 0xb7,
+ 0x62, 0xd8, 0xf7, 0x18, 0x7b, 0x6d, 0x35, 0x92, 0xfd, 0x59, 0x34, 0x7b, 0x6d, 0x95, 0xb3, 0xa3,
+ 0xb5, 0xf6, 0xed, 0x18, 0x36, 0xd7, 0xda, 0x5a, 0xb4, 0xd6, 0xbe, 0x13, 0xc3, 0xe6, 0x5a, 0x5b,
+ 0x8b, 0xd6, 0xda, 0x77, 0x63, 0xd8, 0x5c, 0x6b, 0x6b, 0xd1, 0x5a, 0xfb, 0x5e, 0x0c, 0x9b, 0x6b,
+ 0x6d, 0x2d, 0x5a, 0x6b, 0xdf, 0x8f, 0x61, 0x73, 0xad, 0xad, 0x45, 0x6b, 0xed, 0x07, 0x31, 0x6c,
+ 0xae, 0xb5, 0xb5, 0x68, 0xad, 0xfd, 0x51, 0x0c, 0x9b, 0x6b, 0x6d, 0x2d, 0x5a, 0x6b, 0x7f, 0x1c,
+ 0xc3, 0xe6, 0x5a, 0x5b, 0x8b, 0xd6, 0xda, 0x9f, 0xc4, 0xb0, 0xb9, 0xd6, 0xb4, 0x68, 0xad, 0xfd,
+ 0x69, 0x34, 0x5b, 0xe3, 0x5a, 0xd3, 0xa2, 0xb5, 0xf6, 0x67, 0x31, 0x6c, 0xae, 0x35, 0x2d, 0x5a,
+ 0x6b, 0x7f, 0x1e, 0xc3, 0xe6, 0x5a, 0xd3, 0xa2, 0xb5, 0xf6, 0xc3, 0x18, 0x36, 0xd7, 0x9a, 0x16,
+ 0xad, 0xb5, 0xbf, 0x88, 0x61, 0x73, 0xad, 0x69, 0xd1, 0x5a, 0xfb, 0xcb, 0x18, 0x36, 0xd7, 0x9a,
+ 0x16, 0xad, 0xb5, 0xbf, 0x8a, 0x61, 0x73, 0xad, 0x69, 0xd1, 0x5a, 0xfb, 0xeb, 0x18, 0x36, 0xd7,
+ 0x9a, 0x16, 0xad, 0xb5, 0xbf, 0x89, 0x61, 0x73, 0xad, 0x69, 0xd1, 0x5a, 0xfb, 0xdb, 0x18, 0x36,
+ 0xd7, 0x5a, 0x35, 0x5a, 0x6b, 0x7f, 0x17, 0xcd, 0xae, 0x72, 0xad, 0x55, 0xa3, 0xb5, 0xf6, 0xf7,
+ 0x31, 0x6c, 0xae, 0xb5, 0x6a, 0xb4, 0xd6, 0xfe, 0x21, 0x86, 0xcd, 0xb5, 0x56, 0x8d, 0xd6, 0xda,
+ 0x3f, 0xc6, 0xb0, 0xb9, 0xd6, 0xaa, 0xd1, 0x5a, 0xfb, 0x51, 0x0c, 0x9b, 0x6b, 0xad, 0x1a, 0xad,
+ 0xb5, 0x7f, 0x8a, 0x61, 0x73, 0xad, 0x55, 0xa3, 0xb5, 0xf6, 0xcf, 0x31, 0x6c, 0xae, 0xb5, 0x6a,
+ 0xb4, 0xd6, 0xfe, 0x25, 0x86, 0xcd, 0xb5, 0x56, 0x8d, 0xd6, 0xda, 0xbf, 0xc6, 0xb0, 0xb9, 0xd6,
+ 0xaa, 0xd1, 0x5a, 0xfb, 0xb7, 0x18, 0x36, 0xd7, 0x9a, 0x1e, 0xad, 0xb5, 0x7f, 0x8f, 0x66, 0xeb,
+ 0x5c, 0x6b, 0x7a, 0xb4, 0xd6, 0xfe, 0x23, 0x86, 0xcd, 0xb5, 0xa6, 0x47, 0x6b, 0xed, 0x3f, 0x63,
+ 0xd8, 0x5c, 0x6b, 0x7a, 0xb4, 0xd6, 0xfe, 0x2b, 0x86, 0xcd, 0xb5, 0xa6, 0x47, 0x6b, 0xed, 0xbf,
+ 0x63, 0xd8, 0x5c, 0x6b, 0x7a, 0xb4, 0xd6, 0xfe, 0x27, 0x86, 0xcd, 0xb5, 0xa6, 0x47, 0x6b, 0xed,
+ 0xc7, 0x31, 0x6c, 0xae, 0x35, 0x3d, 0x5a, 0x6b, 0x3f, 0x89, 0x61, 0x73, 0xad, 0xe9, 0xd1, 0x5a,
+ 0xfb, 0xdf, 0x18, 0x36, 0xd7, 0x9a, 0x1e, 0xad, 0xb5, 0xff, 0x8b, 0x61, 0x73, 0xad, 0xad, 0x47,
+ 0x6b, 0xed, 0xff, 0xa3, 0xd9, 0xeb, 0xab, 0x3f, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x00, 0xcd,
+ 0x32, 0x57, 0x39, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/proto/testdata/test.proto b/vendor/github.com/golang/protobuf/proto/testdata/test.proto
new file mode 100644
index 0000000..70e3cfc
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/testdata/test.proto
@@ -0,0 +1,548 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A feature-rich test file for the protocol compiler and libraries.
+
+syntax = "proto2";
+
+package testdata;
+
+enum FOO { FOO1 = 1; };
+
+message GoEnum {
+ required FOO foo = 1;
+}
+
+message GoTestField {
+ required string Label = 1;
+ required string Type = 2;
+}
+
+message GoTest {
+ // An enum, for completeness.
+ enum KIND {
+ VOID = 0;
+
+ // Basic types
+ BOOL = 1;
+ BYTES = 2;
+ FINGERPRINT = 3;
+ FLOAT = 4;
+ INT = 5;
+ STRING = 6;
+ TIME = 7;
+
+ // Groupings
+ TUPLE = 8;
+ ARRAY = 9;
+ MAP = 10;
+
+ // Table types
+ TABLE = 11;
+
+ // Functions
+ FUNCTION = 12; // last tag
+ };
+
+ // Some typical parameters
+ required KIND Kind = 1;
+ optional string Table = 2;
+ optional int32 Param = 3;
+
+ // Required, repeated and optional foreign fields.
+ required GoTestField RequiredField = 4;
+ repeated GoTestField RepeatedField = 5;
+ optional GoTestField OptionalField = 6;
+
+ // Required fields of all basic types
+ required bool F_Bool_required = 10;
+ required int32 F_Int32_required = 11;
+ required int64 F_Int64_required = 12;
+ required fixed32 F_Fixed32_required = 13;
+ required fixed64 F_Fixed64_required = 14;
+ required uint32 F_Uint32_required = 15;
+ required uint64 F_Uint64_required = 16;
+ required float F_Float_required = 17;
+ required double F_Double_required = 18;
+ required string F_String_required = 19;
+ required bytes F_Bytes_required = 101;
+ required sint32 F_Sint32_required = 102;
+ required sint64 F_Sint64_required = 103;
+
+ // Repeated fields of all basic types
+ repeated bool F_Bool_repeated = 20;
+ repeated int32 F_Int32_repeated = 21;
+ repeated int64 F_Int64_repeated = 22;
+ repeated fixed32 F_Fixed32_repeated = 23;
+ repeated fixed64 F_Fixed64_repeated = 24;
+ repeated uint32 F_Uint32_repeated = 25;
+ repeated uint64 F_Uint64_repeated = 26;
+ repeated float F_Float_repeated = 27;
+ repeated double F_Double_repeated = 28;
+ repeated string F_String_repeated = 29;
+ repeated bytes F_Bytes_repeated = 201;
+ repeated sint32 F_Sint32_repeated = 202;
+ repeated sint64 F_Sint64_repeated = 203;
+
+ // Optional fields of all basic types
+ optional bool F_Bool_optional = 30;
+ optional int32 F_Int32_optional = 31;
+ optional int64 F_Int64_optional = 32;
+ optional fixed32 F_Fixed32_optional = 33;
+ optional fixed64 F_Fixed64_optional = 34;
+ optional uint32 F_Uint32_optional = 35;
+ optional uint64 F_Uint64_optional = 36;
+ optional float F_Float_optional = 37;
+ optional double F_Double_optional = 38;
+ optional string F_String_optional = 39;
+ optional bytes F_Bytes_optional = 301;
+ optional sint32 F_Sint32_optional = 302;
+ optional sint64 F_Sint64_optional = 303;
+
+ // Default-valued fields of all basic types
+ optional bool F_Bool_defaulted = 40 [default=true];
+ optional int32 F_Int32_defaulted = 41 [default=32];
+ optional int64 F_Int64_defaulted = 42 [default=64];
+ optional fixed32 F_Fixed32_defaulted = 43 [default=320];
+ optional fixed64 F_Fixed64_defaulted = 44 [default=640];
+ optional uint32 F_Uint32_defaulted = 45 [default=3200];
+ optional uint64 F_Uint64_defaulted = 46 [default=6400];
+ optional float F_Float_defaulted = 47 [default=314159.];
+ optional double F_Double_defaulted = 48 [default=271828.];
+ optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"];
+ optional bytes F_Bytes_defaulted = 401 [default="Bignose"];
+ optional sint32 F_Sint32_defaulted = 402 [default = -32];
+ optional sint64 F_Sint64_defaulted = 403 [default = -64];
+
+ // Packed repeated fields (no string or bytes).
+ repeated bool F_Bool_repeated_packed = 50 [packed=true];
+ repeated int32 F_Int32_repeated_packed = 51 [packed=true];
+ repeated int64 F_Int64_repeated_packed = 52 [packed=true];
+ repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true];
+ repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true];
+ repeated uint32 F_Uint32_repeated_packed = 55 [packed=true];
+ repeated uint64 F_Uint64_repeated_packed = 56 [packed=true];
+ repeated float F_Float_repeated_packed = 57 [packed=true];
+ repeated double F_Double_repeated_packed = 58 [packed=true];
+ repeated sint32 F_Sint32_repeated_packed = 502 [packed=true];
+ repeated sint64 F_Sint64_repeated_packed = 503 [packed=true];
+
+ // Required, repeated, and optional groups.
+ required group RequiredGroup = 70 {
+ required string RequiredField = 71;
+ };
+
+ repeated group RepeatedGroup = 80 {
+ required string RequiredField = 81;
+ };
+
+ optional group OptionalGroup = 90 {
+ required string RequiredField = 91;
+ };
+}
+
+// For testing a group containing a required field.
+message GoTestRequiredGroupField {
+ required group Group = 1 {
+ required int32 Field = 2;
+ };
+}
+
+// For testing skipping of unrecognized fields.
+// Numbers are all big, larger than tag numbers in GoTestField,
+// the message used in the corresponding test.
+message GoSkipTest {
+ required int32 skip_int32 = 11;
+ required fixed32 skip_fixed32 = 12;
+ required fixed64 skip_fixed64 = 13;
+ required string skip_string = 14;
+ required group SkipGroup = 15 {
+ required int32 group_int32 = 16;
+ required string group_string = 17;
+ }
+}
+
+// For testing packed/non-packed decoder switching.
+// A serialized instance of one should be deserializable as the other.
+message NonPackedTest {
+ repeated int32 a = 1;
+}
+
+message PackedTest {
+ repeated int32 b = 1 [packed=true];
+}
+
+message MaxTag {
+ // Maximum possible tag number.
+ optional string last_field = 536870911;
+}
+
+message OldMessage {
+ message Nested {
+ optional string name = 1;
+ }
+ optional Nested nested = 1;
+
+ optional int32 num = 2;
+}
+
+// NewMessage is wire compatible with OldMessage;
+// imagine it as a future version.
+message NewMessage {
+ message Nested {
+ optional string name = 1;
+ optional string food_group = 2;
+ }
+ optional Nested nested = 1;
+
+ // This is an int32 in OldMessage.
+ optional int64 num = 2;
+}
+
+// Smaller tests for ASCII formatting.
+
+message InnerMessage {
+ required string host = 1;
+ optional int32 port = 2 [default=4000];
+ optional bool connected = 3;
+}
+
+message OtherMessage {
+ optional int64 key = 1;
+ optional bytes value = 2;
+ optional float weight = 3;
+ optional InnerMessage inner = 4;
+
+ extensions 100 to max;
+}
+
+message RequiredInnerMessage {
+ required InnerMessage leo_finally_won_an_oscar = 1;
+}
+
+message MyMessage {
+ required int32 count = 1;
+ optional string name = 2;
+ optional string quote = 3;
+ repeated string pet = 4;
+ optional InnerMessage inner = 5;
+ repeated OtherMessage others = 6;
+ optional RequiredInnerMessage we_must_go_deeper = 13;
+ repeated InnerMessage rep_inner = 12;
+
+ enum Color {
+ RED = 0;
+ GREEN = 1;
+ BLUE = 2;
+ };
+ optional Color bikeshed = 7;
+
+ optional group SomeGroup = 8 {
+ optional int32 group_field = 9;
+ }
+
+ // This field becomes [][]byte in the generated code.
+ repeated bytes rep_bytes = 10;
+
+ optional double bigfloat = 11;
+
+ extensions 100 to max;
+}
+
+message Ext {
+ extend MyMessage {
+ optional Ext more = 103;
+ optional string text = 104;
+ optional int32 number = 105;
+ }
+
+ optional string data = 1;
+}
+
+extend MyMessage {
+ repeated string greeting = 106;
+}
+
+message ComplexExtension {
+ optional int32 first = 1;
+ optional int32 second = 2;
+ repeated int32 third = 3;
+}
+
+extend OtherMessage {
+ optional ComplexExtension complex = 200;
+ repeated ComplexExtension r_complex = 201;
+}
+
+message DefaultsMessage {
+ enum DefaultsEnum {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ };
+ extensions 100 to max;
+}
+
+extend DefaultsMessage {
+ optional double no_default_double = 101;
+ optional float no_default_float = 102;
+ optional int32 no_default_int32 = 103;
+ optional int64 no_default_int64 = 104;
+ optional uint32 no_default_uint32 = 105;
+ optional uint64 no_default_uint64 = 106;
+ optional sint32 no_default_sint32 = 107;
+ optional sint64 no_default_sint64 = 108;
+ optional fixed32 no_default_fixed32 = 109;
+ optional fixed64 no_default_fixed64 = 110;
+ optional sfixed32 no_default_sfixed32 = 111;
+ optional sfixed64 no_default_sfixed64 = 112;
+ optional bool no_default_bool = 113;
+ optional string no_default_string = 114;
+ optional bytes no_default_bytes = 115;
+ optional DefaultsMessage.DefaultsEnum no_default_enum = 116;
+
+ optional double default_double = 201 [default = 3.1415];
+ optional float default_float = 202 [default = 3.14];
+ optional int32 default_int32 = 203 [default = 42];
+ optional int64 default_int64 = 204 [default = 43];
+ optional uint32 default_uint32 = 205 [default = 44];
+ optional uint64 default_uint64 = 206 [default = 45];
+ optional sint32 default_sint32 = 207 [default = 46];
+ optional sint64 default_sint64 = 208 [default = 47];
+ optional fixed32 default_fixed32 = 209 [default = 48];
+ optional fixed64 default_fixed64 = 210 [default = 49];
+ optional sfixed32 default_sfixed32 = 211 [default = 50];
+ optional sfixed64 default_sfixed64 = 212 [default = 51];
+ optional bool default_bool = 213 [default = true];
+ optional string default_string = 214 [default = "Hello, string"];
+ optional bytes default_bytes = 215 [default = "Hello, bytes"];
+ optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
+}
+
+message MyMessageSet {
+ option message_set_wire_format = true;
+ extensions 100 to max;
+}
+
+message Empty {
+}
+
+extend MyMessageSet {
+ optional Empty x201 = 201;
+ optional Empty x202 = 202;
+ optional Empty x203 = 203;
+ optional Empty x204 = 204;
+ optional Empty x205 = 205;
+ optional Empty x206 = 206;
+ optional Empty x207 = 207;
+ optional Empty x208 = 208;
+ optional Empty x209 = 209;
+ optional Empty x210 = 210;
+ optional Empty x211 = 211;
+ optional Empty x212 = 212;
+ optional Empty x213 = 213;
+ optional Empty x214 = 214;
+ optional Empty x215 = 215;
+ optional Empty x216 = 216;
+ optional Empty x217 = 217;
+ optional Empty x218 = 218;
+ optional Empty x219 = 219;
+ optional Empty x220 = 220;
+ optional Empty x221 = 221;
+ optional Empty x222 = 222;
+ optional Empty x223 = 223;
+ optional Empty x224 = 224;
+ optional Empty x225 = 225;
+ optional Empty x226 = 226;
+ optional Empty x227 = 227;
+ optional Empty x228 = 228;
+ optional Empty x229 = 229;
+ optional Empty x230 = 230;
+ optional Empty x231 = 231;
+ optional Empty x232 = 232;
+ optional Empty x233 = 233;
+ optional Empty x234 = 234;
+ optional Empty x235 = 235;
+ optional Empty x236 = 236;
+ optional Empty x237 = 237;
+ optional Empty x238 = 238;
+ optional Empty x239 = 239;
+ optional Empty x240 = 240;
+ optional Empty x241 = 241;
+ optional Empty x242 = 242;
+ optional Empty x243 = 243;
+ optional Empty x244 = 244;
+ optional Empty x245 = 245;
+ optional Empty x246 = 246;
+ optional Empty x247 = 247;
+ optional Empty x248 = 248;
+ optional Empty x249 = 249;
+ optional Empty x250 = 250;
+}
+
+message MessageList {
+ repeated group Message = 1 {
+ required string name = 2;
+ required int32 count = 3;
+ }
+}
+
+message Strings {
+ optional string string_field = 1;
+ optional bytes bytes_field = 2;
+}
+
+message Defaults {
+ enum Color {
+ RED = 0;
+ GREEN = 1;
+ BLUE = 2;
+ }
+
+ // Default-valued fields of all basic types.
+ // Same as GoTest, but copied here to make testing easier.
+ optional bool F_Bool = 1 [default=true];
+ optional int32 F_Int32 = 2 [default=32];
+ optional int64 F_Int64 = 3 [default=64];
+ optional fixed32 F_Fixed32 = 4 [default=320];
+ optional fixed64 F_Fixed64 = 5 [default=640];
+ optional uint32 F_Uint32 = 6 [default=3200];
+ optional uint64 F_Uint64 = 7 [default=6400];
+ optional float F_Float = 8 [default=314159.];
+ optional double F_Double = 9 [default=271828.];
+ optional string F_String = 10 [default="hello, \"world!\"\n"];
+ optional bytes F_Bytes = 11 [default="Bignose"];
+ optional sint32 F_Sint32 = 12 [default=-32];
+ optional sint64 F_Sint64 = 13 [default=-64];
+ optional Color F_Enum = 14 [default=GREEN];
+
+ // More fields with crazy defaults.
+ optional float F_Pinf = 15 [default=inf];
+ optional float F_Ninf = 16 [default=-inf];
+ optional float F_Nan = 17 [default=nan];
+
+ // Sub-message.
+ optional SubDefaults sub = 18;
+
+ // Redundant but explicit defaults.
+ optional string str_zero = 19 [default=""];
+}
+
+message SubDefaults {
+ optional int64 n = 1 [default=7];
+}
+
+message RepeatedEnum {
+ enum Color {
+ RED = 1;
+ }
+ repeated Color color = 1;
+}
+
+message MoreRepeated {
+ repeated bool bools = 1;
+ repeated bool bools_packed = 2 [packed=true];
+ repeated int32 ints = 3;
+ repeated int32 ints_packed = 4 [packed=true];
+ repeated int64 int64s_packed = 7 [packed=true];
+ repeated string strings = 5;
+ repeated fixed32 fixeds = 6;
+}
+
+// GroupOld and GroupNew have the same wire format.
+// GroupNew has a new field inside a group.
+
+message GroupOld {
+ optional group G = 101 {
+ optional int32 x = 2;
+ }
+}
+
+message GroupNew {
+ optional group G = 101 {
+ optional int32 x = 2;
+ optional int32 y = 3;
+ }
+}
+
+message FloatingPoint {
+ required double f = 1;
+ optional bool exact = 2;
+}
+
+message MessageWithMap {
+ map name_mapping = 1;
+ map msg_mapping = 2;
+ map byte_mapping = 3;
+ map str_to_str = 4;
+}
+
+message Oneof {
+ oneof union {
+ bool F_Bool = 1;
+ int32 F_Int32 = 2;
+ int64 F_Int64 = 3;
+ fixed32 F_Fixed32 = 4;
+ fixed64 F_Fixed64 = 5;
+ uint32 F_Uint32 = 6;
+ uint64 F_Uint64 = 7;
+ float F_Float = 8;
+ double F_Double = 9;
+ string F_String = 10;
+ bytes F_Bytes = 11;
+ sint32 F_Sint32 = 12;
+ sint64 F_Sint64 = 13;
+ MyMessage.Color F_Enum = 14;
+ GoTestField F_Message = 15;
+ group F_Group = 16 {
+ optional int32 x = 17;
+ }
+ int32 F_Largest_Tag = 536870911;
+ }
+
+ oneof tormato {
+ int32 value = 100;
+ }
+}
+
+message Communique {
+ optional bool make_me_cry = 1;
+
+ // This is a oneof, called "union".
+ oneof union {
+ int32 number = 5;
+ string name = 6;
+ bytes data = 7;
+ double temp_c = 8;
+ MyMessage.Color col = 9;
+ Strings msg = 10;
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go
new file mode 100644
index 0000000..965876b
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/text.go
@@ -0,0 +1,854 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// Functions for writing the text protocol buffer format.
+
+import (
+ "bufio"
+ "bytes"
+ "encoding"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+ "reflect"
+ "sort"
+ "strings"
+)
+
+var (
+ newline = []byte("\n")
+ spaces = []byte(" ")
+ gtNewline = []byte(">\n")
+ endBraceNewline = []byte("}\n")
+ backslashN = []byte{'\\', 'n'}
+ backslashR = []byte{'\\', 'r'}
+ backslashT = []byte{'\\', 't'}
+ backslashDQ = []byte{'\\', '"'}
+ backslashBS = []byte{'\\', '\\'}
+ posInf = []byte("inf")
+ negInf = []byte("-inf")
+ nan = []byte("nan")
+)
+
+type writer interface {
+ io.Writer
+ WriteByte(byte) error
+}
+
+// textWriter is an io.Writer that tracks its indentation level.
+type textWriter struct {
+ ind int
+ complete bool // if the current position is a complete line
+ compact bool // whether to write out as a one-liner
+ w writer
+}
+
+func (w *textWriter) WriteString(s string) (n int, err error) {
+ if !strings.Contains(s, "\n") {
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ w.complete = false
+ return io.WriteString(w.w, s)
+ }
+ // WriteString is typically called without newlines, so this
+ // codepath and its copy are rare. We copy to avoid
+ // duplicating all of Write's logic here.
+ return w.Write([]byte(s))
+}
+
+func (w *textWriter) Write(p []byte) (n int, err error) {
+ newlines := bytes.Count(p, newline)
+ if newlines == 0 {
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ n, err = w.w.Write(p)
+ w.complete = false
+ return n, err
+ }
+
+ frags := bytes.SplitN(p, newline, newlines+1)
+ if w.compact {
+ for i, frag := range frags {
+ if i > 0 {
+ if err := w.w.WriteByte(' '); err != nil {
+ return n, err
+ }
+ n++
+ }
+ nn, err := w.w.Write(frag)
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+ }
+
+ for i, frag := range frags {
+ if w.complete {
+ w.writeIndent()
+ }
+ nn, err := w.w.Write(frag)
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ if i+1 < len(frags) {
+ if err := w.w.WriteByte('\n'); err != nil {
+ return n, err
+ }
+ n++
+ }
+ }
+ w.complete = len(frags[len(frags)-1]) == 0
+ return n, nil
+}
+
+func (w *textWriter) WriteByte(c byte) error {
+ if w.compact && c == '\n' {
+ c = ' '
+ }
+ if !w.compact && w.complete {
+ w.writeIndent()
+ }
+ err := w.w.WriteByte(c)
+ w.complete = c == '\n'
+ return err
+}
+
+func (w *textWriter) indent() { w.ind++ }
+
+func (w *textWriter) unindent() {
+ if w.ind == 0 {
+ log.Print("proto: textWriter unindented too far")
+ return
+ }
+ w.ind--
+}
+
+func writeName(w *textWriter, props *Properties) error {
+ if _, err := w.WriteString(props.OrigName); err != nil {
+ return err
+ }
+ if props.Wire != "group" {
+ return w.WriteByte(':')
+ }
+ return nil
+}
+
+// raw is the interface satisfied by RawMessage.
+type raw interface {
+ Bytes() []byte
+}
+
+func requiresQuotes(u string) bool {
+ // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
+ for _, ch := range u {
+ switch {
+ case ch == '.' || ch == '/' || ch == '_':
+ continue
+ case '0' <= ch && ch <= '9':
+ continue
+ case 'A' <= ch && ch <= 'Z':
+ continue
+ case 'a' <= ch && ch <= 'z':
+ continue
+ default:
+ return true
+ }
+ }
+ return false
+}
+
+// isAny reports whether sv is a google.protobuf.Any message
+func isAny(sv reflect.Value) bool {
+ type wkt interface {
+ XXX_WellKnownType() string
+ }
+ t, ok := sv.Addr().Interface().(wkt)
+ return ok && t.XXX_WellKnownType() == "Any"
+}
+
+// writeProto3Any writes an expanded google.protobuf.Any message.
+//
+// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
+// required messages are not linked in).
+//
+// It returns (true, error) when sv was written in expanded format or an error
+// was encountered.
+func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
+ turl := sv.FieldByName("TypeUrl")
+ val := sv.FieldByName("Value")
+ if !turl.IsValid() || !val.IsValid() {
+ return true, errors.New("proto: invalid google.protobuf.Any message")
+ }
+
+ b, ok := val.Interface().([]byte)
+ if !ok {
+ return true, errors.New("proto: invalid google.protobuf.Any message")
+ }
+
+ parts := strings.Split(turl.String(), "/")
+ mt := MessageType(parts[len(parts)-1])
+ if mt == nil {
+ return false, nil
+ }
+ m := reflect.New(mt.Elem())
+ if err := Unmarshal(b, m.Interface().(Message)); err != nil {
+ return false, nil
+ }
+ w.Write([]byte("["))
+ u := turl.String()
+ if requiresQuotes(u) {
+ writeString(w, u)
+ } else {
+ w.Write([]byte(u))
+ }
+ if w.compact {
+ w.Write([]byte("]:<"))
+ } else {
+ w.Write([]byte("]: <\n"))
+ w.ind++
+ }
+ if err := tm.writeStruct(w, m.Elem()); err != nil {
+ return true, err
+ }
+ if w.compact {
+ w.Write([]byte("> "))
+ } else {
+ w.ind--
+ w.Write([]byte(">\n"))
+ }
+ return true, nil
+}
+
+func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
+ if tm.ExpandAny && isAny(sv) {
+ if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
+ return err
+ }
+ }
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < sv.NumField(); i++ {
+ fv := sv.Field(i)
+ props := sprops.Prop[i]
+ name := st.Field(i).Name
+
+ if strings.HasPrefix(name, "XXX_") {
+ // There are two XXX_ fields:
+ // XXX_unrecognized []byte
+ // XXX_extensions map[int32]proto.Extension
+ // The first is handled here;
+ // the second is handled at the bottom of this function.
+ if name == "XXX_unrecognized" && !fv.IsNil() {
+ if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ // Field not filled in. This could be an optional field or
+ // a required field that wasn't filled in. Either way, there
+ // isn't anything we can show for it.
+ continue
+ }
+ if fv.Kind() == reflect.Slice && fv.IsNil() {
+ // Repeated field that is empty, or a bytes field that is unused.
+ continue
+ }
+
+ if props.Repeated && fv.Kind() == reflect.Slice {
+ // Repeated field.
+ for j := 0; j < fv.Len(); j++ {
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ v := fv.Index(j)
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ // A nil message in a repeated field is not valid,
+ // but we can handle that more gracefully than panicking.
+ if _, err := w.Write([]byte("\n")); err != nil {
+ return err
+ }
+ continue
+ }
+ if err := tm.writeAny(w, v, props); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if fv.Kind() == reflect.Map {
+ // Map fields are rendered as a repeated struct with key/value fields.
+ keys := fv.MapKeys()
+ sort.Sort(mapKeys(keys))
+ for _, key := range keys {
+ val := fv.MapIndex(key)
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ // open struct
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ // key
+ if _, err := w.WriteString("key:"); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ // nil values aren't legal, but we can avoid panicking because of them.
+ if val.Kind() != reflect.Ptr || !val.IsNil() {
+ // value
+ if _, err := w.WriteString("value:"); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, val, props.mvalprop); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ // close struct
+ w.unindent()
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
+ // empty bytes field
+ continue
+ }
+ if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
+ // proto3 non-repeated scalar field; skip if zero value
+ if isProto3Zero(fv) {
+ continue
+ }
+ }
+
+ if fv.Kind() == reflect.Interface {
+ // Check if it is a oneof.
+ if st.Field(i).Tag.Get("protobuf_oneof") != "" {
+ // fv is nil, or holds a pointer to generated struct.
+ // That generated struct has exactly one field,
+ // which has a protobuf struct tag.
+ if fv.IsNil() {
+ continue
+ }
+ inner := fv.Elem().Elem() // interface -> *T -> T
+ tag := inner.Type().Field(0).Tag.Get("protobuf")
+ props = new(Properties) // Overwrite the outer props var, but not its pointee.
+ props.Parse(tag)
+ // Write the value in the oneof, not the oneof itself.
+ fv = inner.Field(0)
+
+ // Special case to cope with malformed messages gracefully:
+ // If the value in the oneof is a nil pointer, don't panic
+ // in writeAny.
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ // Use errors.New so writeAny won't render quotes.
+ msg := errors.New("/* nil */")
+ fv = reflect.ValueOf(&msg).Elem()
+ }
+ }
+ }
+
+ if err := writeName(w, props); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if b, ok := fv.Interface().(raw); ok {
+ if err := writeRaw(w, b.Bytes()); err != nil {
+ return err
+ }
+ continue
+ }
+
+ // Enums have a String method, so writeAny will work fine.
+ if err := tm.writeAny(w, fv, props); err != nil {
+ return err
+ }
+
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+
+ // Extensions (the XXX_extensions field).
+ pv := sv.Addr()
+ if _, ok := extendable(pv.Interface()); ok {
+ if err := tm.writeExtensions(w, pv); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// writeRaw writes an uninterpreted raw message.
+func writeRaw(w *textWriter, b []byte) error {
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ if err := writeUnknownStruct(w, b); err != nil {
+ return err
+ }
+ w.unindent()
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+ return nil
+}
+
+// writeAny writes an arbitrary field.
+func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
+ v = reflect.Indirect(v)
+
+ // Floats have special cases.
+ if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
+ x := v.Float()
+ var b []byte
+ switch {
+ case math.IsInf(x, 1):
+ b = posInf
+ case math.IsInf(x, -1):
+ b = negInf
+ case math.IsNaN(x):
+ b = nan
+ }
+ if b != nil {
+ _, err := w.Write(b)
+ return err
+ }
+ // Other values are handled below.
+ }
+
+ // We don't attempt to serialise every possible value type; only those
+ // that can occur in protocol buffers.
+ switch v.Kind() {
+ case reflect.Slice:
+ // Should only be a []byte; repeated fields are handled in writeStruct.
+ if err := writeString(w, string(v.Bytes())); err != nil {
+ return err
+ }
+ case reflect.String:
+ if err := writeString(w, v.String()); err != nil {
+ return err
+ }
+ case reflect.Struct:
+ // Required/optional group/message.
+ var bra, ket byte = '<', '>'
+ if props != nil && props.Wire == "group" {
+ bra, ket = '{', '}'
+ }
+ if err := w.WriteByte(bra); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ w.indent()
+ if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
+ text, err := etm.MarshalText()
+ if err != nil {
+ return err
+ }
+ if _, err = w.Write(text); err != nil {
+ return err
+ }
+ } else if err := tm.writeStruct(w, v); err != nil {
+ return err
+ }
+ w.unindent()
+ if err := w.WriteByte(ket); err != nil {
+ return err
+ }
+ default:
+ _, err := fmt.Fprint(w, v.Interface())
+ return err
+ }
+ return nil
+}
+
+// equivalent to C's isprint.
+func isprint(c byte) bool {
+ return c >= 0x20 && c < 0x7f
+}
+
+// writeString writes a string in the protocol buffer text format.
+// It is similar to strconv.Quote except we don't use Go escape sequences,
+// we treat the string as a byte sequence, and we use octal escapes.
+// These differences are to maintain interoperability with the other
+// languages' implementations of the text format.
+func writeString(w *textWriter, s string) error {
+ // use WriteByte here to get any needed indent
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ // Loop over the bytes, not the runes.
+ for i := 0; i < len(s); i++ {
+ var err error
+ // Divergence from C++: we don't escape apostrophes.
+ // There's no need to escape them, and the C++ parser
+ // copes with a naked apostrophe.
+ switch c := s[i]; c {
+ case '\n':
+ _, err = w.w.Write(backslashN)
+ case '\r':
+ _, err = w.w.Write(backslashR)
+ case '\t':
+ _, err = w.w.Write(backslashT)
+ case '"':
+ _, err = w.w.Write(backslashDQ)
+ case '\\':
+ _, err = w.w.Write(backslashBS)
+ default:
+ if isprint(c) {
+ err = w.w.WriteByte(c)
+ } else {
+ _, err = fmt.Fprintf(w.w, "\\%03o", c)
+ }
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return w.WriteByte('"')
+}
+
+func writeUnknownStruct(w *textWriter, data []byte) (err error) {
+ if !w.compact {
+ if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
+ return err
+ }
+ }
+ b := NewBuffer(data)
+ for b.index < len(b.buf) {
+ x, err := b.DecodeVarint()
+ if err != nil {
+ _, err := fmt.Fprintf(w, "/* %v */\n", err)
+ return err
+ }
+ wire, tag := x&7, x>>3
+ if wire == WireEndGroup {
+ w.unindent()
+ if _, err := w.Write(endBraceNewline); err != nil {
+ return err
+ }
+ continue
+ }
+ if _, err := fmt.Fprint(w, tag); err != nil {
+ return err
+ }
+ if wire != WireStartGroup {
+ if err := w.WriteByte(':'); err != nil {
+ return err
+ }
+ }
+ if !w.compact || wire == WireStartGroup {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ switch wire {
+ case WireBytes:
+ buf, e := b.DecodeRawBytes(false)
+ if e == nil {
+ _, err = fmt.Fprintf(w, "%q", buf)
+ } else {
+ _, err = fmt.Fprintf(w, "/* %v */", e)
+ }
+ case WireFixed32:
+ x, err = b.DecodeFixed32()
+ err = writeUnknownInt(w, x, err)
+ case WireFixed64:
+ x, err = b.DecodeFixed64()
+ err = writeUnknownInt(w, x, err)
+ case WireStartGroup:
+ err = w.WriteByte('{')
+ w.indent()
+ case WireVarint:
+ x, err = b.DecodeVarint()
+ err = writeUnknownInt(w, x, err)
+ default:
+ _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
+ }
+ if err != nil {
+ return err
+ }
+ if err = w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func writeUnknownInt(w *textWriter, x uint64, err error) error {
+ if err == nil {
+ _, err = fmt.Fprint(w, x)
+ } else {
+ _, err = fmt.Fprintf(w, "/* %v */", err)
+ }
+ return err
+}
+
+type int32Slice []int32
+
+func (s int32Slice) Len() int { return len(s) }
+func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
+func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// writeExtensions writes all the extensions in pv.
+// pv is assumed to be a pointer to a protocol message struct that is extendable.
+func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
+ emap := extensionMaps[pv.Type().Elem()]
+ ep, _ := extendable(pv.Interface())
+
+ // Order the extensions by ID.
+ // This isn't strictly necessary, but it will give us
+ // canonical output, which will also make testing easier.
+ m, mu := ep.extensionsRead()
+ if m == nil {
+ return nil
+ }
+ mu.Lock()
+ ids := make([]int32, 0, len(m))
+ for id := range m {
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids))
+ mu.Unlock()
+
+ for _, extNum := range ids {
+ ext := m[extNum]
+ var desc *ExtensionDesc
+ if emap != nil {
+ desc = emap[extNum]
+ }
+ if desc == nil {
+ // Unknown extension.
+ if err := writeUnknownStruct(w, ext.enc); err != nil {
+ return err
+ }
+ continue
+ }
+
+ pb, err := GetExtension(ep, desc)
+ if err != nil {
+ return fmt.Errorf("failed getting extension: %v", err)
+ }
+
+ // Repeated extensions will appear as a slice.
+ if !desc.repeated() {
+ if err := tm.writeExtension(w, desc.Name, pb); err != nil {
+ return err
+ }
+ } else {
+ v := reflect.ValueOf(pb)
+ for i := 0; i < v.Len(); i++ {
+ if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
+ if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
+ return err
+ }
+ if !w.compact {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ }
+ if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
+ return err
+ }
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (w *textWriter) writeIndent() {
+ if !w.complete {
+ return
+ }
+ remain := w.ind * 2
+ for remain > 0 {
+ n := remain
+ if n > len(spaces) {
+ n = len(spaces)
+ }
+ w.w.Write(spaces[:n])
+ remain -= n
+ }
+ w.complete = false
+}
+
+// TextMarshaler is a configurable text format marshaler.
+type TextMarshaler struct {
+ Compact bool // use compact text format (one line).
+ ExpandAny bool // expand google.protobuf.Any messages of known types
+}
+
+// Marshal writes a given protocol buffer in text format.
+// The only errors returned are from w.
+func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
+ val := reflect.ValueOf(pb)
+ if pb == nil || val.IsNil() {
+ w.Write([]byte(""))
+ return nil
+ }
+ var bw *bufio.Writer
+ ww, ok := w.(writer)
+ if !ok {
+ bw = bufio.NewWriter(w)
+ ww = bw
+ }
+ aw := &textWriter{
+ w: ww,
+ complete: true,
+ compact: tm.Compact,
+ }
+
+ if etm, ok := pb.(encoding.TextMarshaler); ok {
+ text, err := etm.MarshalText()
+ if err != nil {
+ return err
+ }
+ if _, err = aw.Write(text); err != nil {
+ return err
+ }
+ if bw != nil {
+ return bw.Flush()
+ }
+ return nil
+ }
+ // Dereference the received pointer so we don't have outer < and >.
+ v := reflect.Indirect(val)
+ if err := tm.writeStruct(aw, v); err != nil {
+ return err
+ }
+ if bw != nil {
+ return bw.Flush()
+ }
+ return nil
+}
+
+// Text is the same as Marshal, but returns the string directly.
+func (tm *TextMarshaler) Text(pb Message) string {
+ var buf bytes.Buffer
+ tm.Marshal(&buf, pb)
+ return buf.String()
+}
+
+var (
+ defaultTextMarshaler = TextMarshaler{}
+ compactTextMarshaler = TextMarshaler{Compact: true}
+)
+
+// TODO: consider removing some of the Marshal functions below.
+
+// MarshalText writes a given protocol buffer in text format.
+// The only errors returned are from w.
+func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
+
+// MarshalTextString is the same as MarshalText, but returns the string directly.
+func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
+
+// CompactText writes a given protocol buffer in compact text format (one line).
+func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
+
+// CompactTextString is the same as CompactText, but returns the string directly.
+func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
diff --git a/vendor/github.com/golang/protobuf/proto/text_parser.go b/vendor/github.com/golang/protobuf/proto/text_parser.go
new file mode 100644
index 0000000..5e14513
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/text_parser.go
@@ -0,0 +1,895 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+// Functions for parsing the Text protocol buffer format.
+// TODO: message sets.
+
+import (
+ "encoding"
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+)
+
+// Error string emitted when deserializing Any and fields are already set
+const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set"
+
+type ParseError struct {
+ Message string
+ Line int // 1-based line number
+ Offset int // 0-based byte offset from start of input
+}
+
+func (p *ParseError) Error() string {
+ if p.Line == 1 {
+ // show offset only for first line
+ return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
+ }
+ return fmt.Sprintf("line %d: %v", p.Line, p.Message)
+}
+
+type token struct {
+ value string
+ err *ParseError
+ line int // line number
+ offset int // byte number from start of input, not start of line
+ unquoted string // the unquoted version of value, if it was a quoted string
+}
+
+func (t *token) String() string {
+ if t.err == nil {
+ return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
+ }
+ return fmt.Sprintf("parse error: %v", t.err)
+}
+
+type textParser struct {
+ s string // remaining input
+ done bool // whether the parsing is finished (success or error)
+ backed bool // whether back() was called
+ offset, line int
+ cur token
+}
+
+func newTextParser(s string) *textParser {
+ p := new(textParser)
+ p.s = s
+ p.line = 1
+ p.cur.line = 1
+ return p
+}
+
+func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
+ pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
+ p.cur.err = pe
+ p.done = true
+ return pe
+}
+
+// Numbers and identifiers are matched by [-+._A-Za-z0-9]
+func isIdentOrNumberChar(c byte) bool {
+ switch {
+ case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
+ return true
+ case '0' <= c && c <= '9':
+ return true
+ }
+ switch c {
+ case '-', '+', '.', '_':
+ return true
+ }
+ return false
+}
+
+func isWhitespace(c byte) bool {
+ switch c {
+ case ' ', '\t', '\n', '\r':
+ return true
+ }
+ return false
+}
+
+func isQuote(c byte) bool {
+ switch c {
+ case '"', '\'':
+ return true
+ }
+ return false
+}
+
+func (p *textParser) skipWhitespace() {
+ i := 0
+ for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
+ if p.s[i] == '#' {
+ // comment; skip to end of line or input
+ for i < len(p.s) && p.s[i] != '\n' {
+ i++
+ }
+ if i == len(p.s) {
+ break
+ }
+ }
+ if p.s[i] == '\n' {
+ p.line++
+ }
+ i++
+ }
+ p.offset += i
+ p.s = p.s[i:len(p.s)]
+ if len(p.s) == 0 {
+ p.done = true
+ }
+}
+
+func (p *textParser) advance() {
+ // Skip whitespace
+ p.skipWhitespace()
+ if p.done {
+ return
+ }
+
+ // Start of non-whitespace
+ p.cur.err = nil
+ p.cur.offset, p.cur.line = p.offset, p.line
+ p.cur.unquoted = ""
+ switch p.s[0] {
+ case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
+ // Single symbol
+ p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
+ case '"', '\'':
+ // Quoted string
+ i := 1
+ for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
+ if p.s[i] == '\\' && i+1 < len(p.s) {
+ // skip escaped char
+ i++
+ }
+ i++
+ }
+ if i >= len(p.s) || p.s[i] != p.s[0] {
+ p.errorf("unmatched quote")
+ return
+ }
+ unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
+ if err != nil {
+ p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
+ return
+ }
+ p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
+ p.cur.unquoted = unq
+ default:
+ i := 0
+ for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
+ i++
+ }
+ if i == 0 {
+ p.errorf("unexpected byte %#x", p.s[0])
+ return
+ }
+ p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
+ }
+ p.offset += len(p.cur.value)
+}
+
+var (
+ errBadUTF8 = errors.New("proto: bad UTF-8")
+ errBadHex = errors.New("proto: bad hexadecimal")
+)
+
+func unquoteC(s string, quote rune) (string, error) {
+ // This is based on C++'s tokenizer.cc.
+ // Despite its name, this is *not* parsing C syntax.
+ // For instance, "\0" is an invalid quoted string.
+
+ // Avoid allocation in trivial cases.
+ simple := true
+ for _, r := range s {
+ if r == '\\' || r == quote {
+ simple = false
+ break
+ }
+ }
+ if simple {
+ return s, nil
+ }
+
+ buf := make([]byte, 0, 3*len(s)/2)
+ for len(s) > 0 {
+ r, n := utf8.DecodeRuneInString(s)
+ if r == utf8.RuneError && n == 1 {
+ return "", errBadUTF8
+ }
+ s = s[n:]
+ if r != '\\' {
+ if r < utf8.RuneSelf {
+ buf = append(buf, byte(r))
+ } else {
+ buf = append(buf, string(r)...)
+ }
+ continue
+ }
+
+ ch, tail, err := unescape(s)
+ if err != nil {
+ return "", err
+ }
+ buf = append(buf, ch...)
+ s = tail
+ }
+ return string(buf), nil
+}
+
+func unescape(s string) (ch string, tail string, err error) {
+ r, n := utf8.DecodeRuneInString(s)
+ if r == utf8.RuneError && n == 1 {
+ return "", "", errBadUTF8
+ }
+ s = s[n:]
+ switch r {
+ case 'a':
+ return "\a", s, nil
+ case 'b':
+ return "\b", s, nil
+ case 'f':
+ return "\f", s, nil
+ case 'n':
+ return "\n", s, nil
+ case 'r':
+ return "\r", s, nil
+ case 't':
+ return "\t", s, nil
+ case 'v':
+ return "\v", s, nil
+ case '?':
+ return "?", s, nil // trigraph workaround
+ case '\'', '"', '\\':
+ return string(r), s, nil
+ case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
+ if len(s) < 2 {
+ return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
+ }
+ base := 8
+ ss := s[:2]
+ s = s[2:]
+ if r == 'x' || r == 'X' {
+ base = 16
+ } else {
+ ss = string(r) + ss
+ }
+ i, err := strconv.ParseUint(ss, base, 8)
+ if err != nil {
+ return "", "", err
+ }
+ return string([]byte{byte(i)}), s, nil
+ case 'u', 'U':
+ n := 4
+ if r == 'U' {
+ n = 8
+ }
+ if len(s) < n {
+ return "", "", fmt.Errorf(`\%c requires %d digits`, r, n)
+ }
+
+ bs := make([]byte, n/2)
+ for i := 0; i < n; i += 2 {
+ a, ok1 := unhex(s[i])
+ b, ok2 := unhex(s[i+1])
+ if !ok1 || !ok2 {
+ return "", "", errBadHex
+ }
+ bs[i/2] = a<<4 | b
+ }
+ s = s[n:]
+ return string(bs), s, nil
+ }
+ return "", "", fmt.Errorf(`unknown escape \%c`, r)
+}
+
+// Adapted from src/pkg/strconv/quote.go.
+func unhex(b byte) (v byte, ok bool) {
+ switch {
+ case '0' <= b && b <= '9':
+ return b - '0', true
+ case 'a' <= b && b <= 'f':
+ return b - 'a' + 10, true
+ case 'A' <= b && b <= 'F':
+ return b - 'A' + 10, true
+ }
+ return 0, false
+}
+
+// Back off the parser by one token. Can only be done between calls to next().
+// It makes the next advance() a no-op.
+func (p *textParser) back() { p.backed = true }
+
+// Advances the parser and returns the new current token.
+func (p *textParser) next() *token {
+ if p.backed || p.done {
+ p.backed = false
+ return &p.cur
+ }
+ p.advance()
+ if p.done {
+ p.cur.value = ""
+ } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
+ // Look for multiple quoted strings separated by whitespace,
+ // and concatenate them.
+ cat := p.cur
+ for {
+ p.skipWhitespace()
+ if p.done || !isQuote(p.s[0]) {
+ break
+ }
+ p.advance()
+ if p.cur.err != nil {
+ return &p.cur
+ }
+ cat.value += " " + p.cur.value
+ cat.unquoted += p.cur.unquoted
+ }
+ p.done = false // parser may have seen EOF, but we want to return cat
+ p.cur = cat
+ }
+ return &p.cur
+}
+
+func (p *textParser) consumeToken(s string) error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != s {
+ p.back()
+ return p.errorf("expected %q, found %q", s, tok.value)
+ }
+ return nil
+}
+
+// Return a RequiredNotSetError indicating which required field was not set.
+func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError {
+ st := sv.Type()
+ sprops := GetProperties(st)
+ for i := 0; i < st.NumField(); i++ {
+ if !isNil(sv.Field(i)) {
+ continue
+ }
+
+ props := sprops.Prop[i]
+ if props.Required {
+ return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)}
+ }
+ }
+ return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen
+}
+
+// Returns the index in the struct for the named field, as well as the parsed tag properties.
+func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
+ i, ok := sprops.decoderOrigNames[name]
+ if ok {
+ return i, sprops.Prop[i], true
+ }
+ return -1, nil, false
+}
+
+// Consume a ':' from the input stream (if the next token is a colon),
+// returning an error if a colon is needed but not present.
+func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != ":" {
+ // Colon is optional when the field is a group or message.
+ needColon := true
+ switch props.Wire {
+ case "group":
+ needColon = false
+ case "bytes":
+ // A "bytes" field is either a message, a string, or a repeated field;
+ // those three become *T, *string and []T respectively, so we can check for
+ // this field being a pointer to a non-string.
+ if typ.Kind() == reflect.Ptr {
+ // *T or *string
+ if typ.Elem().Kind() == reflect.String {
+ break
+ }
+ } else if typ.Kind() == reflect.Slice {
+ // []T or []*T
+ if typ.Elem().Kind() != reflect.Ptr {
+ break
+ }
+ } else if typ.Kind() == reflect.String {
+ // The proto3 exception is for a string field,
+ // which requires a colon.
+ break
+ }
+ needColon = false
+ }
+ if needColon {
+ return p.errorf("expected ':', found %q", tok.value)
+ }
+ p.back()
+ }
+ return nil
+}
+
+func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
+ st := sv.Type()
+ sprops := GetProperties(st)
+ reqCount := sprops.reqCount
+ var reqFieldErr error
+ fieldSet := make(map[string]bool)
+ // A struct is a sequence of "name: value", terminated by one of
+ // '>' or '}', or the end of the input. A name may also be
+ // "[extension]" or "[type/url]".
+ //
+ // The whole struct can also be an expanded Any message, like:
+ // [type/url] < ... struct contents ... >
+ for {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == terminator {
+ break
+ }
+ if tok.value == "[" {
+ // Looks like an extension or an Any.
+ //
+ // TODO: Check whether we need to handle
+ // namespace rooted names (e.g. ".something.Foo").
+ extName, err := p.consumeExtName()
+ if err != nil {
+ return err
+ }
+
+ if s := strings.LastIndex(extName, "/"); s >= 0 {
+ // If it contains a slash, it's an Any type URL.
+ messageName := extName[s+1:]
+ mt := MessageType(messageName)
+ if mt == nil {
+ return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
+ }
+ tok = p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ // consume an optional colon
+ if tok.value == ":" {
+ tok = p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ }
+ var terminator string
+ switch tok.value {
+ case "<":
+ terminator = ">"
+ case "{":
+ terminator = "}"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ v := reflect.New(mt.Elem())
+ if pe := p.readStruct(v.Elem(), terminator); pe != nil {
+ return pe
+ }
+ b, err := Marshal(v.Interface().(Message))
+ if err != nil {
+ return p.errorf("failed to marshal message of type %q: %v", messageName, err)
+ }
+ if fieldSet["type_url"] {
+ return p.errorf(anyRepeatedlyUnpacked, "type_url")
+ }
+ if fieldSet["value"] {
+ return p.errorf(anyRepeatedlyUnpacked, "value")
+ }
+ sv.FieldByName("TypeUrl").SetString(extName)
+ sv.FieldByName("Value").SetBytes(b)
+ fieldSet["type_url"] = true
+ fieldSet["value"] = true
+ continue
+ }
+
+ var desc *ExtensionDesc
+ // This could be faster, but it's functional.
+ // TODO: Do something smarter than a linear scan.
+ for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
+ if d.Name == extName {
+ desc = d
+ break
+ }
+ }
+ if desc == nil {
+ return p.errorf("unrecognized extension %q", extName)
+ }
+
+ props := &Properties{}
+ props.Parse(desc.Tag)
+
+ typ := reflect.TypeOf(desc.ExtensionType)
+ if err := p.checkForColon(props, typ); err != nil {
+ return err
+ }
+
+ rep := desc.repeated()
+
+ // Read the extension structure, and set it in
+ // the value we're constructing.
+ var ext reflect.Value
+ if !rep {
+ ext = reflect.New(typ).Elem()
+ } else {
+ ext = reflect.New(typ.Elem()).Elem()
+ }
+ if err := p.readAny(ext, props); err != nil {
+ if _, ok := err.(*RequiredNotSetError); !ok {
+ return err
+ }
+ reqFieldErr = err
+ }
+ ep := sv.Addr().Interface().(Message)
+ if !rep {
+ SetExtension(ep, desc, ext.Interface())
+ } else {
+ old, err := GetExtension(ep, desc)
+ var sl reflect.Value
+ if err == nil {
+ sl = reflect.ValueOf(old) // existing slice
+ } else {
+ sl = reflect.MakeSlice(typ, 0, 1)
+ }
+ sl = reflect.Append(sl, ext)
+ SetExtension(ep, desc, sl.Interface())
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ continue
+ }
+
+ // This is a normal, non-extension field.
+ name := tok.value
+ var dst reflect.Value
+ fi, props, ok := structFieldByName(sprops, name)
+ if ok {
+ dst = sv.Field(fi)
+ } else if oop, ok := sprops.OneofTypes[name]; ok {
+ // It is a oneof.
+ props = oop.Prop
+ nv := reflect.New(oop.Type.Elem())
+ dst = nv.Elem().Field(0)
+ field := sv.Field(oop.Field)
+ if !field.IsNil() {
+ return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name)
+ }
+ field.Set(nv)
+ }
+ if !dst.IsValid() {
+ return p.errorf("unknown field name %q in %v", name, st)
+ }
+
+ if dst.Kind() == reflect.Map {
+ // Consume any colon.
+ if err := p.checkForColon(props, dst.Type()); err != nil {
+ return err
+ }
+
+ // Construct the map if it doesn't already exist.
+ if dst.IsNil() {
+ dst.Set(reflect.MakeMap(dst.Type()))
+ }
+ key := reflect.New(dst.Type().Key()).Elem()
+ val := reflect.New(dst.Type().Elem()).Elem()
+
+ // The map entry should be this sequence of tokens:
+ // < key : KEY value : VALUE >
+ // However, implementations may omit key or value, and technically
+ // we should support them in any order. See b/28924776 for a time
+ // this went wrong.
+
+ tok := p.next()
+ var terminator string
+ switch tok.value {
+ case "<":
+ terminator = ">"
+ case "{":
+ terminator = "}"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ for {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == terminator {
+ break
+ }
+ switch tok.value {
+ case "key":
+ if err := p.consumeToken(":"); err != nil {
+ return err
+ }
+ if err := p.readAny(key, props.mkeyprop); err != nil {
+ return err
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ case "value":
+ if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
+ return err
+ }
+ if err := p.readAny(val, props.mvalprop); err != nil {
+ return err
+ }
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+ default:
+ p.back()
+ return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
+ }
+ }
+
+ dst.SetMapIndex(key, val)
+ continue
+ }
+
+ // Check that it's not already set if it's not a repeated field.
+ if !props.Repeated && fieldSet[name] {
+ return p.errorf("non-repeated field %q was repeated", name)
+ }
+
+ if err := p.checkForColon(props, dst.Type()); err != nil {
+ return err
+ }
+
+ // Parse into the field.
+ fieldSet[name] = true
+ if err := p.readAny(dst, props); err != nil {
+ if _, ok := err.(*RequiredNotSetError); !ok {
+ return err
+ }
+ reqFieldErr = err
+ }
+ if props.Required {
+ reqCount--
+ }
+
+ if err := p.consumeOptionalSeparator(); err != nil {
+ return err
+ }
+
+ }
+
+ if reqCount > 0 {
+ return p.missingRequiredFieldError(sv)
+ }
+ return reqFieldErr
+}
+
+// consumeExtName consumes extension name or expanded Any type URL and the
+// following ']'. It returns the name or URL consumed.
+func (p *textParser) consumeExtName() (string, error) {
+ tok := p.next()
+ if tok.err != nil {
+ return "", tok.err
+ }
+
+ // If extension name or type url is quoted, it's a single token.
+ if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
+ name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
+ if err != nil {
+ return "", err
+ }
+ return name, p.consumeToken("]")
+ }
+
+ // Consume everything up to "]"
+ var parts []string
+ for tok.value != "]" {
+ parts = append(parts, tok.value)
+ tok = p.next()
+ if tok.err != nil {
+ return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
+ }
+ }
+ return strings.Join(parts, ""), nil
+}
+
+// consumeOptionalSeparator consumes an optional semicolon or comma.
+// It is used in readStruct to provide backward compatibility.
+func (p *textParser) consumeOptionalSeparator() error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value != ";" && tok.value != "," {
+ p.back()
+ }
+ return nil
+}
+
+func (p *textParser) readAny(v reflect.Value, props *Properties) error {
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == "" {
+ return p.errorf("unexpected EOF")
+ }
+
+ switch fv := v; fv.Kind() {
+ case reflect.Slice:
+ at := v.Type()
+ if at.Elem().Kind() == reflect.Uint8 {
+ // Special case for []byte
+ if tok.value[0] != '"' && tok.value[0] != '\'' {
+ // Deliberately written out here, as the error after
+ // this switch statement would write "invalid []byte: ...",
+ // which is not as user-friendly.
+ return p.errorf("invalid string: %v", tok.value)
+ }
+ bytes := []byte(tok.unquoted)
+ fv.Set(reflect.ValueOf(bytes))
+ return nil
+ }
+ // Repeated field.
+ if tok.value == "[" {
+ // Repeated field with list notation, like [1,2,3].
+ for {
+ fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+ err := p.readAny(fv.Index(fv.Len()-1), props)
+ if err != nil {
+ return err
+ }
+ tok := p.next()
+ if tok.err != nil {
+ return tok.err
+ }
+ if tok.value == "]" {
+ break
+ }
+ if tok.value != "," {
+ return p.errorf("Expected ']' or ',' found %q", tok.value)
+ }
+ }
+ return nil
+ }
+ // One value of the repeated field.
+ p.back()
+ fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+ return p.readAny(fv.Index(fv.Len()-1), props)
+ case reflect.Bool:
+ // true/1/t/True or false/f/0/False.
+ switch tok.value {
+ case "true", "1", "t", "True":
+ fv.SetBool(true)
+ return nil
+ case "false", "0", "f", "False":
+ fv.SetBool(false)
+ return nil
+ }
+ case reflect.Float32, reflect.Float64:
+ v := tok.value
+ // Ignore 'f' for compatibility with output generated by C++, but don't
+ // remove 'f' when the value is "-inf" or "inf".
+ if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" {
+ v = v[:len(v)-1]
+ }
+ if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil {
+ fv.SetFloat(f)
+ return nil
+ }
+ case reflect.Int32:
+ if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
+ fv.SetInt(x)
+ return nil
+ }
+
+ if len(props.Enum) == 0 {
+ break
+ }
+ m, ok := enumValueMaps[props.Enum]
+ if !ok {
+ break
+ }
+ x, ok := m[tok.value]
+ if !ok {
+ break
+ }
+ fv.SetInt(int64(x))
+ return nil
+ case reflect.Int64:
+ if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
+ fv.SetInt(x)
+ return nil
+ }
+
+ case reflect.Ptr:
+ // A basic field (indirected through pointer), or a repeated message/group
+ p.back()
+ fv.Set(reflect.New(fv.Type().Elem()))
+ return p.readAny(fv.Elem(), props)
+ case reflect.String:
+ if tok.value[0] == '"' || tok.value[0] == '\'' {
+ fv.SetString(tok.unquoted)
+ return nil
+ }
+ case reflect.Struct:
+ var terminator string
+ switch tok.value {
+ case "{":
+ terminator = "}"
+ case "<":
+ terminator = ">"
+ default:
+ return p.errorf("expected '{' or '<', found %q", tok.value)
+ }
+ // TODO: Handle nested messages which implement encoding.TextUnmarshaler.
+ return p.readStruct(fv, terminator)
+ case reflect.Uint32:
+ if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
+ fv.SetUint(x)
+ return nil
+ }
+ case reflect.Uint64:
+ if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
+ fv.SetUint(x)
+ return nil
+ }
+ }
+ return p.errorf("invalid %v: %v", v.Type(), tok.value)
+}
+
+// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
+// before starting to unmarshal, so any existing data in pb is always removed.
+// If a required field is not set and no other error occurs,
+// UnmarshalText returns *RequiredNotSetError.
+func UnmarshalText(s string, pb Message) error {
+ if um, ok := pb.(encoding.TextUnmarshaler); ok {
+ err := um.UnmarshalText([]byte(s))
+ return err
+ }
+ pb.Reset()
+ v := reflect.ValueOf(pb)
+ if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
+ return pe
+ }
+ return nil
+}
diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile
new file mode 100644
index 0000000..f706871
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile
@@ -0,0 +1,37 @@
+# Go support for Protocol Buffers - Google's data interchange format
+#
+# Copyright 2010 The Go Authors. All rights reserved.
+# https://github.com/golang/protobuf
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Not stored here, but descriptor.proto is in https://github.com/google/protobuf/
+# at src/google/protobuf/descriptor.proto
+regenerate:
+ @echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
+ cp $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto .
+ protoc --go_out=../../../../.. -I$(HOME)/src/protobuf/include $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto
diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
new file mode 100644
index 0000000..c6a91bc
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
@@ -0,0 +1,2215 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/descriptor.proto
+
+/*
+Package descriptor is a generated protocol buffer package.
+
+It is generated from these files:
+ google/protobuf/descriptor.proto
+
+It has these top-level messages:
+ FileDescriptorSet
+ FileDescriptorProto
+ DescriptorProto
+ ExtensionRangeOptions
+ FieldDescriptorProto
+ OneofDescriptorProto
+ EnumDescriptorProto
+ EnumValueDescriptorProto
+ ServiceDescriptorProto
+ MethodDescriptorProto
+ FileOptions
+ MessageOptions
+ FieldOptions
+ OneofOptions
+ EnumOptions
+ EnumValueOptions
+ ServiceOptions
+ MethodOptions
+ UninterpretedOption
+ SourceCodeInfo
+ GeneratedCodeInfo
+*/
+package descriptor
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type FieldDescriptorProto_Type int32
+
+const (
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1
+ FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3
+ FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5
+ FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6
+ FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7
+ FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8
+ FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9
+ // Tag-delimited aggregate.
+ // Group type is deprecated and not supported in proto3. However, Proto3
+ // implementations should still be able to parse the group wire format and
+ // treat group fields as unknown fields.
+ FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10
+ FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11
+ // New in version 2.
+ FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12
+ FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13
+ FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14
+ FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15
+ FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16
+ FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17
+ FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18
+)
+
+var FieldDescriptorProto_Type_name = map[int32]string{
+ 1: "TYPE_DOUBLE",
+ 2: "TYPE_FLOAT",
+ 3: "TYPE_INT64",
+ 4: "TYPE_UINT64",
+ 5: "TYPE_INT32",
+ 6: "TYPE_FIXED64",
+ 7: "TYPE_FIXED32",
+ 8: "TYPE_BOOL",
+ 9: "TYPE_STRING",
+ 10: "TYPE_GROUP",
+ 11: "TYPE_MESSAGE",
+ 12: "TYPE_BYTES",
+ 13: "TYPE_UINT32",
+ 14: "TYPE_ENUM",
+ 15: "TYPE_SFIXED32",
+ 16: "TYPE_SFIXED64",
+ 17: "TYPE_SINT32",
+ 18: "TYPE_SINT64",
+}
+var FieldDescriptorProto_Type_value = map[string]int32{
+ "TYPE_DOUBLE": 1,
+ "TYPE_FLOAT": 2,
+ "TYPE_INT64": 3,
+ "TYPE_UINT64": 4,
+ "TYPE_INT32": 5,
+ "TYPE_FIXED64": 6,
+ "TYPE_FIXED32": 7,
+ "TYPE_BOOL": 8,
+ "TYPE_STRING": 9,
+ "TYPE_GROUP": 10,
+ "TYPE_MESSAGE": 11,
+ "TYPE_BYTES": 12,
+ "TYPE_UINT32": 13,
+ "TYPE_ENUM": 14,
+ "TYPE_SFIXED32": 15,
+ "TYPE_SFIXED64": 16,
+ "TYPE_SINT32": 17,
+ "TYPE_SINT64": 18,
+}
+
+func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type {
+ p := new(FieldDescriptorProto_Type)
+ *p = x
+ return p
+}
+func (x FieldDescriptorProto_Type) String() string {
+ return proto.EnumName(FieldDescriptorProto_Type_name, int32(x))
+}
+func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Type_value, data, "FieldDescriptorProto_Type")
+ if err != nil {
+ return err
+ }
+ *x = FieldDescriptorProto_Type(value)
+ return nil
+}
+func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} }
+
+type FieldDescriptorProto_Label int32
+
+const (
+ // 0 is reserved for errors
+ FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1
+ FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2
+ FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3
+)
+
+var FieldDescriptorProto_Label_name = map[int32]string{
+ 1: "LABEL_OPTIONAL",
+ 2: "LABEL_REQUIRED",
+ 3: "LABEL_REPEATED",
+}
+var FieldDescriptorProto_Label_value = map[string]int32{
+ "LABEL_OPTIONAL": 1,
+ "LABEL_REQUIRED": 2,
+ "LABEL_REPEATED": 3,
+}
+
+func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label {
+ p := new(FieldDescriptorProto_Label)
+ *p = x
+ return p
+}
+func (x FieldDescriptorProto_Label) String() string {
+ return proto.EnumName(FieldDescriptorProto_Label_name, int32(x))
+}
+func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Label_value, data, "FieldDescriptorProto_Label")
+ if err != nil {
+ return err
+ }
+ *x = FieldDescriptorProto_Label(value)
+ return nil
+}
+func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{4, 1}
+}
+
+// Generated classes can be optimized for speed or code size.
+type FileOptions_OptimizeMode int32
+
+const (
+ FileOptions_SPEED FileOptions_OptimizeMode = 1
+ // etc.
+ FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2
+ FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3
+)
+
+var FileOptions_OptimizeMode_name = map[int32]string{
+ 1: "SPEED",
+ 2: "CODE_SIZE",
+ 3: "LITE_RUNTIME",
+}
+var FileOptions_OptimizeMode_value = map[string]int32{
+ "SPEED": 1,
+ "CODE_SIZE": 2,
+ "LITE_RUNTIME": 3,
+}
+
+func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode {
+ p := new(FileOptions_OptimizeMode)
+ *p = x
+ return p
+}
+func (x FileOptions_OptimizeMode) String() string {
+ return proto.EnumName(FileOptions_OptimizeMode_name, int32(x))
+}
+func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FileOptions_OptimizeMode_value, data, "FileOptions_OptimizeMode")
+ if err != nil {
+ return err
+ }
+ *x = FileOptions_OptimizeMode(value)
+ return nil
+}
+func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} }
+
+type FieldOptions_CType int32
+
+const (
+ // Default mode.
+ FieldOptions_STRING FieldOptions_CType = 0
+ FieldOptions_CORD FieldOptions_CType = 1
+ FieldOptions_STRING_PIECE FieldOptions_CType = 2
+)
+
+var FieldOptions_CType_name = map[int32]string{
+ 0: "STRING",
+ 1: "CORD",
+ 2: "STRING_PIECE",
+}
+var FieldOptions_CType_value = map[string]int32{
+ "STRING": 0,
+ "CORD": 1,
+ "STRING_PIECE": 2,
+}
+
+func (x FieldOptions_CType) Enum() *FieldOptions_CType {
+ p := new(FieldOptions_CType)
+ *p = x
+ return p
+}
+func (x FieldOptions_CType) String() string {
+ return proto.EnumName(FieldOptions_CType_name, int32(x))
+}
+func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldOptions_CType_value, data, "FieldOptions_CType")
+ if err != nil {
+ return err
+ }
+ *x = FieldOptions_CType(value)
+ return nil
+}
+func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 0} }
+
+type FieldOptions_JSType int32
+
+const (
+ // Use the default type.
+ FieldOptions_JS_NORMAL FieldOptions_JSType = 0
+ // Use JavaScript strings.
+ FieldOptions_JS_STRING FieldOptions_JSType = 1
+ // Use JavaScript numbers.
+ FieldOptions_JS_NUMBER FieldOptions_JSType = 2
+)
+
+var FieldOptions_JSType_name = map[int32]string{
+ 0: "JS_NORMAL",
+ 1: "JS_STRING",
+ 2: "JS_NUMBER",
+}
+var FieldOptions_JSType_value = map[string]int32{
+ "JS_NORMAL": 0,
+ "JS_STRING": 1,
+ "JS_NUMBER": 2,
+}
+
+func (x FieldOptions_JSType) Enum() *FieldOptions_JSType {
+ p := new(FieldOptions_JSType)
+ *p = x
+ return p
+}
+func (x FieldOptions_JSType) String() string {
+ return proto.EnumName(FieldOptions_JSType_name, int32(x))
+}
+func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FieldOptions_JSType_value, data, "FieldOptions_JSType")
+ if err != nil {
+ return err
+ }
+ *x = FieldOptions_JSType(value)
+ return nil
+}
+func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 1} }
+
+// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+// or neither? HTTP based RPC implementation may choose GET verb for safe
+// methods, and PUT verb for idempotent methods instead of the default POST.
+type MethodOptions_IdempotencyLevel int32
+
+const (
+ MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0
+ MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1
+ MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2
+)
+
+var MethodOptions_IdempotencyLevel_name = map[int32]string{
+ 0: "IDEMPOTENCY_UNKNOWN",
+ 1: "NO_SIDE_EFFECTS",
+ 2: "IDEMPOTENT",
+}
+var MethodOptions_IdempotencyLevel_value = map[string]int32{
+ "IDEMPOTENCY_UNKNOWN": 0,
+ "NO_SIDE_EFFECTS": 1,
+ "IDEMPOTENT": 2,
+}
+
+func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel {
+ p := new(MethodOptions_IdempotencyLevel)
+ *p = x
+ return p
+}
+func (x MethodOptions_IdempotencyLevel) String() string {
+ return proto.EnumName(MethodOptions_IdempotencyLevel_name, int32(x))
+}
+func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MethodOptions_IdempotencyLevel_value, data, "MethodOptions_IdempotencyLevel")
+ if err != nil {
+ return err
+ }
+ *x = MethodOptions_IdempotencyLevel(value)
+ return nil
+}
+func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{17, 0}
+}
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+type FileDescriptorSet struct {
+ File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} }
+func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) }
+func (*FileDescriptorSet) ProtoMessage() {}
+func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func (m *FileDescriptorSet) GetFile() []*FileDescriptorProto {
+ if m != nil {
+ return m.File
+ }
+ return nil
+}
+
+// Describes a complete .proto file.
+type FileDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"`
+ // Names of files imported by this file.
+ Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"`
+ // Indexes of the public imported files in the dependency list above.
+ PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"`
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"`
+ // All top-level definitions in this file.
+ MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
+ Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"`
+ Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"`
+ // This field contains optional information about the original source code.
+ // You may safely remove this entire field without harming runtime
+ // functionality of the descriptors -- the information is needed only by
+ // development tools.
+ SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"`
+ // The syntax of the proto file.
+ // The supported values are "proto2" and "proto3".
+ Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} }
+func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*FileDescriptorProto) ProtoMessage() {}
+func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+func (m *FileDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *FileDescriptorProto) GetPackage() string {
+ if m != nil && m.Package != nil {
+ return *m.Package
+ }
+ return ""
+}
+
+func (m *FileDescriptorProto) GetDependency() []string {
+ if m != nil {
+ return m.Dependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetPublicDependency() []int32 {
+ if m != nil {
+ return m.PublicDependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetWeakDependency() []int32 {
+ if m != nil {
+ return m.WeakDependency
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetMessageType() []*DescriptorProto {
+ if m != nil {
+ return m.MessageType
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto {
+ if m != nil {
+ return m.EnumType
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetService() []*ServiceDescriptorProto {
+ if m != nil {
+ return m.Service
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetExtension() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Extension
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetOptions() *FileOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo {
+ if m != nil {
+ return m.SourceCodeInfo
+ }
+ return nil
+}
+
+func (m *FileDescriptorProto) GetSyntax() string {
+ if m != nil && m.Syntax != nil {
+ return *m.Syntax
+ }
+ return ""
+}
+
+// Describes a message type.
+type DescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"`
+ Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"`
+ NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"`
+ EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"`
+ ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"`
+ OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"`
+ Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"`
+ ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"`
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto) Reset() { *m = DescriptorProto{} }
+func (m *DescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto) ProtoMessage() {}
+func (*DescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+func (m *DescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *DescriptorProto) GetField() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Field
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetExtension() []*FieldDescriptorProto {
+ if m != nil {
+ return m.Extension
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetNestedType() []*DescriptorProto {
+ if m != nil {
+ return m.NestedType
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetEnumType() []*EnumDescriptorProto {
+ if m != nil {
+ return m.EnumType
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange {
+ if m != nil {
+ return m.ExtensionRange
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto {
+ if m != nil {
+ return m.OneofDecl
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetOptions() *MessageOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange {
+ if m != nil {
+ return m.ReservedRange
+ }
+ return nil
+}
+
+func (m *DescriptorProto) GetReservedName() []string {
+ if m != nil {
+ return m.ReservedName
+ }
+ return nil
+}
+
+type DescriptorProto_ExtensionRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
+ Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} }
+func (m *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto_ExtensionRange) ProtoMessage() {}
+func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{2, 0}
+}
+
+func (m *DescriptorProto_ExtensionRange) GetStart() int32 {
+ if m != nil && m.Start != nil {
+ return *m.Start
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ExtensionRange) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Range of reserved tag numbers. Reserved tag numbers may not be used by
+// fields or extension ranges in the same message. Reserved ranges may
+// not overlap.
+type DescriptorProto_ReservedRange struct {
+ Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"`
+ End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DescriptorProto_ReservedRange) Reset() { *m = DescriptorProto_ReservedRange{} }
+func (m *DescriptorProto_ReservedRange) String() string { return proto.CompactTextString(m) }
+func (*DescriptorProto_ReservedRange) ProtoMessage() {}
+func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{2, 1}
+}
+
+func (m *DescriptorProto_ReservedRange) GetStart() int32 {
+ if m != nil && m.Start != nil {
+ return *m.Start
+ }
+ return 0
+}
+
+func (m *DescriptorProto_ReservedRange) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+type ExtensionRangeOptions struct {
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} }
+func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) }
+func (*ExtensionRangeOptions) ProtoMessage() {}
+func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+var extRange_ExtensionRangeOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*ExtensionRangeOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ExtensionRangeOptions
+}
+
+func (m *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+// Describes a field within a message.
+type FieldDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"`
+ Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"`
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+ Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"`
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"`
+ // For extensions, this is the name of the type being extended. It is
+ // resolved in the same manner as type_name.
+ Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"`
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"`
+ // If set, gives the index of a oneof in the containing type's oneof_decl
+ // list. This field is a member of that oneof.
+ OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"`
+ // JSON name of this field. The value is set by protocol compiler. If the
+ // user has set a "json_name" option on this field, that option's value
+ // will be used. Otherwise, it's deduced from the field's name by converting
+ // it to camelCase.
+ JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"`
+ Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} }
+func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*FieldDescriptorProto) ProtoMessage() {}
+func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *FieldDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetNumber() int32 {
+ if m != nil && m.Number != nil {
+ return *m.Number
+ }
+ return 0
+}
+
+func (m *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return FieldDescriptorProto_LABEL_OPTIONAL
+}
+
+func (m *FieldDescriptorProto) GetType() FieldDescriptorProto_Type {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return FieldDescriptorProto_TYPE_DOUBLE
+}
+
+func (m *FieldDescriptorProto) GetTypeName() string {
+ if m != nil && m.TypeName != nil {
+ return *m.TypeName
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetExtendee() string {
+ if m != nil && m.Extendee != nil {
+ return *m.Extendee
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetDefaultValue() string {
+ if m != nil && m.DefaultValue != nil {
+ return *m.DefaultValue
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetOneofIndex() int32 {
+ if m != nil && m.OneofIndex != nil {
+ return *m.OneofIndex
+ }
+ return 0
+}
+
+func (m *FieldDescriptorProto) GetJsonName() string {
+ if m != nil && m.JsonName != nil {
+ return *m.JsonName
+ }
+ return ""
+}
+
+func (m *FieldDescriptorProto) GetOptions() *FieldOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a oneof.
+type OneofDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} }
+func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*OneofDescriptorProto) ProtoMessage() {}
+func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+
+func (m *OneofDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *OneofDescriptorProto) GetOptions() *OneofOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes an enum type.
+type EnumDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"`
+ Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} }
+func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*EnumDescriptorProto) ProtoMessage() {}
+func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+
+func (m *EnumDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (m *EnumDescriptorProto) GetOptions() *EnumOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a value within an enum.
+type EnumValueDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"`
+ Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} }
+func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*EnumValueDescriptorProto) ProtoMessage() {}
+func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+
+func (m *EnumValueDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *EnumValueDescriptorProto) GetNumber() int32 {
+ if m != nil && m.Number != nil {
+ return *m.Number
+ }
+ return 0
+}
+
+func (m *EnumValueDescriptorProto) GetOptions() *EnumValueOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a service.
+type ServiceDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"`
+ Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} }
+func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*ServiceDescriptorProto) ProtoMessage() {}
+func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+
+func (m *ServiceDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto {
+ if m != nil {
+ return m.Method
+ }
+ return nil
+}
+
+func (m *ServiceDescriptorProto) GetOptions() *ServiceOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+// Describes a method of a service.
+type MethodDescriptorProto struct {
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // Input and output type names. These are resolved in the same way as
+ // FieldDescriptorProto.type_name, but must refer to a message type.
+ InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"`
+ OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"`
+ Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"`
+ // Identifies if client streams multiple client messages
+ ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"`
+ // Identifies if server streams multiple server messages
+ ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} }
+func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) }
+func (*MethodDescriptorProto) ProtoMessage() {}
+func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+
+const Default_MethodDescriptorProto_ClientStreaming bool = false
+const Default_MethodDescriptorProto_ServerStreaming bool = false
+
+func (m *MethodDescriptorProto) GetName() string {
+ if m != nil && m.Name != nil {
+ return *m.Name
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetInputType() string {
+ if m != nil && m.InputType != nil {
+ return *m.InputType
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetOutputType() string {
+ if m != nil && m.OutputType != nil {
+ return *m.OutputType
+ }
+ return ""
+}
+
+func (m *MethodDescriptorProto) GetOptions() *MethodOptions {
+ if m != nil {
+ return m.Options
+ }
+ return nil
+}
+
+func (m *MethodDescriptorProto) GetClientStreaming() bool {
+ if m != nil && m.ClientStreaming != nil {
+ return *m.ClientStreaming
+ }
+ return Default_MethodDescriptorProto_ClientStreaming
+}
+
+func (m *MethodDescriptorProto) GetServerStreaming() bool {
+ if m != nil && m.ServerStreaming != nil {
+ return *m.ServerStreaming
+ }
+ return Default_MethodDescriptorProto_ServerStreaming
+}
+
+type FileOptions struct {
+ // Sets the Java package where classes generated from this .proto will be
+ // placed. By default, the proto package is used, but this is often
+ // inappropriate because proto packages do not normally start with backwards
+ // domain names.
+ JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"`
+ // If set, all the classes from the .proto file are wrapped in a single
+ // outer class with the given name. This applies to both Proto1
+ // (equivalent to the old "--one_java_file" option) and Proto2 (where
+ // a .proto always translates to a single class, but you may want to
+ // explicitly choose the class name).
+ JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"`
+ // If set true, then the Java code generator will generate a separate .java
+ // file for each top-level message, enum, and service defined in the .proto
+ // file. Thus, these types will *not* be nested inside the outer class
+ // named by java_outer_classname. However, the outer class will still be
+ // generated to contain the file's getDescriptor() method as well as any
+ // top-level extensions defined in the file.
+ JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"`
+ // This option does nothing.
+ JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"`
+ // If set true, then the Java2 code generator will generate code that
+ // throws an exception whenever an attempt is made to assign a non-UTF-8
+ // byte sequence to a string field.
+ // Message reflection will do the same.
+ // However, an extension field still accepts non-UTF-8 byte sequences.
+ // This option has no effect on when used with the lite runtime.
+ JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"`
+ OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"`
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. If omitted, the Go package will be derived from the following:
+ // - The basename of the package import path, if provided.
+ // - Otherwise, the package statement in the .proto file, if present.
+ // - Otherwise, the basename of the .proto file, without extension.
+ GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"`
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of google.protobuf.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. Therefore,
+ // these default to false. Old code which depends on generic services should
+ // explicitly set them to true.
+ CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"`
+ JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"`
+ PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"`
+ PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"`
+ // Is this file deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for everything in the file, or it will be completely ignored; in the very
+ // least, this is a formalization for deprecating files.
+ Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // Enables the use of arenas for the proto messages in this file. This applies
+ // only to generated classes for C++.
+ CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=0" json:"cc_enable_arenas,omitempty"`
+ // Sets the objective c class prefix which is prepended to all objective c
+ // generated classes from this .proto. There is no default.
+ ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"`
+ // Namespace for generated classes; defaults to the package.
+ CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"`
+ // By default Swift generators will take the proto package and CamelCase it
+ // replacing '.' with underscore and use that to prefix the types/symbols
+ // defined. When this options is provided, they will use this value instead
+ // to prefix the types/symbols defined.
+ SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"`
+ // Sets the php class prefix which is prepended to all php generated classes
+ // from this .proto. Default is empty.
+ PhpClassPrefix *string `protobuf:"bytes,40,opt,name=php_class_prefix,json=phpClassPrefix" json:"php_class_prefix,omitempty"`
+ // Use this option to change the namespace of php generated classes. Default
+ // is empty. When this option is empty, the package name will be used for
+ // determining the namespace.
+ PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FileOptions) Reset() { *m = FileOptions{} }
+func (m *FileOptions) String() string { return proto.CompactTextString(m) }
+func (*FileOptions) ProtoMessage() {}
+func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
+
+var extRange_FileOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FileOptions
+}
+
+const Default_FileOptions_JavaMultipleFiles bool = false
+const Default_FileOptions_JavaStringCheckUtf8 bool = false
+const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED
+const Default_FileOptions_CcGenericServices bool = false
+const Default_FileOptions_JavaGenericServices bool = false
+const Default_FileOptions_PyGenericServices bool = false
+const Default_FileOptions_PhpGenericServices bool = false
+const Default_FileOptions_Deprecated bool = false
+const Default_FileOptions_CcEnableArenas bool = false
+
+func (m *FileOptions) GetJavaPackage() string {
+ if m != nil && m.JavaPackage != nil {
+ return *m.JavaPackage
+ }
+ return ""
+}
+
+func (m *FileOptions) GetJavaOuterClassname() string {
+ if m != nil && m.JavaOuterClassname != nil {
+ return *m.JavaOuterClassname
+ }
+ return ""
+}
+
+func (m *FileOptions) GetJavaMultipleFiles() bool {
+ if m != nil && m.JavaMultipleFiles != nil {
+ return *m.JavaMultipleFiles
+ }
+ return Default_FileOptions_JavaMultipleFiles
+}
+
+func (m *FileOptions) GetJavaGenerateEqualsAndHash() bool {
+ if m != nil && m.JavaGenerateEqualsAndHash != nil {
+ return *m.JavaGenerateEqualsAndHash
+ }
+ return false
+}
+
+func (m *FileOptions) GetJavaStringCheckUtf8() bool {
+ if m != nil && m.JavaStringCheckUtf8 != nil {
+ return *m.JavaStringCheckUtf8
+ }
+ return Default_FileOptions_JavaStringCheckUtf8
+}
+
+func (m *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode {
+ if m != nil && m.OptimizeFor != nil {
+ return *m.OptimizeFor
+ }
+ return Default_FileOptions_OptimizeFor
+}
+
+func (m *FileOptions) GetGoPackage() string {
+ if m != nil && m.GoPackage != nil {
+ return *m.GoPackage
+ }
+ return ""
+}
+
+func (m *FileOptions) GetCcGenericServices() bool {
+ if m != nil && m.CcGenericServices != nil {
+ return *m.CcGenericServices
+ }
+ return Default_FileOptions_CcGenericServices
+}
+
+func (m *FileOptions) GetJavaGenericServices() bool {
+ if m != nil && m.JavaGenericServices != nil {
+ return *m.JavaGenericServices
+ }
+ return Default_FileOptions_JavaGenericServices
+}
+
+func (m *FileOptions) GetPyGenericServices() bool {
+ if m != nil && m.PyGenericServices != nil {
+ return *m.PyGenericServices
+ }
+ return Default_FileOptions_PyGenericServices
+}
+
+func (m *FileOptions) GetPhpGenericServices() bool {
+ if m != nil && m.PhpGenericServices != nil {
+ return *m.PhpGenericServices
+ }
+ return Default_FileOptions_PhpGenericServices
+}
+
+func (m *FileOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_FileOptions_Deprecated
+}
+
+func (m *FileOptions) GetCcEnableArenas() bool {
+ if m != nil && m.CcEnableArenas != nil {
+ return *m.CcEnableArenas
+ }
+ return Default_FileOptions_CcEnableArenas
+}
+
+func (m *FileOptions) GetObjcClassPrefix() string {
+ if m != nil && m.ObjcClassPrefix != nil {
+ return *m.ObjcClassPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetCsharpNamespace() string {
+ if m != nil && m.CsharpNamespace != nil {
+ return *m.CsharpNamespace
+ }
+ return ""
+}
+
+func (m *FileOptions) GetSwiftPrefix() string {
+ if m != nil && m.SwiftPrefix != nil {
+ return *m.SwiftPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetPhpClassPrefix() string {
+ if m != nil && m.PhpClassPrefix != nil {
+ return *m.PhpClassPrefix
+ }
+ return ""
+}
+
+func (m *FileOptions) GetPhpNamespace() string {
+ if m != nil && m.PhpNamespace != nil {
+ return *m.PhpNamespace
+ }
+ return ""
+}
+
+func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type MessageOptions struct {
+ // Set true to use the old proto1 MessageSet wire format for extensions.
+ // This is provided for backwards-compatibility with the MessageSet wire
+ // format. You should not use this for any other reason: It's less
+ // efficient, has fewer features, and is more complicated.
+ //
+ // The message must be defined exactly as follows:
+ // message Foo {
+ // option message_set_wire_format = true;
+ // extensions 4 to max;
+ // }
+ // Note that the message cannot have any defined fields; MessageSets only
+ // have extensions.
+ //
+ // All extensions of your type must be singular messages; e.g. they cannot
+ // be int32s, enums, or repeated messages.
+ //
+ // Because this is an option, the above two restrictions are not enforced by
+ // the protocol compiler.
+ MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"`
+ // Disables the generation of the standard "descriptor()" accessor, which can
+ // conflict with a field of the same name. This is meant to make migration
+ // from proto1 easier; new code should avoid fields named "descriptor".
+ NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"`
+ // Is this message deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the message, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating messages.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // Whether the message is an automatically generated map entry type for the
+ // maps field.
+ //
+ // For maps fields:
+ // map map_field = 1;
+ // The parsed descriptor looks like:
+ // message MapFieldEntry {
+ // option map_entry = true;
+ // optional KeyType key = 1;
+ // optional ValueType value = 2;
+ // }
+ // repeated MapFieldEntry map_field = 1;
+ //
+ // Implementations may choose not to generate the map_entry=true message, but
+ // use a native map in the target language to hold the keys and values.
+ // The reflection APIs in such implementions still need to work as
+ // if the field is a repeated message field.
+ //
+ // NOTE: Do not set the option in .proto files. Always use the maps syntax
+ // instead. The option should only be implicitly set by the proto compiler
+ // parser.
+ MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MessageOptions) Reset() { *m = MessageOptions{} }
+func (m *MessageOptions) String() string { return proto.CompactTextString(m) }
+func (*MessageOptions) ProtoMessage() {}
+func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
+
+var extRange_MessageOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MessageOptions
+}
+
+const Default_MessageOptions_MessageSetWireFormat bool = false
+const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
+const Default_MessageOptions_Deprecated bool = false
+
+func (m *MessageOptions) GetMessageSetWireFormat() bool {
+ if m != nil && m.MessageSetWireFormat != nil {
+ return *m.MessageSetWireFormat
+ }
+ return Default_MessageOptions_MessageSetWireFormat
+}
+
+func (m *MessageOptions) GetNoStandardDescriptorAccessor() bool {
+ if m != nil && m.NoStandardDescriptorAccessor != nil {
+ return *m.NoStandardDescriptorAccessor
+ }
+ return Default_MessageOptions_NoStandardDescriptorAccessor
+}
+
+func (m *MessageOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_MessageOptions_Deprecated
+}
+
+func (m *MessageOptions) GetMapEntry() bool {
+ if m != nil && m.MapEntry != nil {
+ return *m.MapEntry
+ }
+ return false
+}
+
+func (m *MessageOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type FieldOptions struct {
+ // The ctype option instructs the C++ code generator to use a different
+ // representation of the field than it normally would. See the specific
+ // options below. This option is not yet implemented in the open source
+ // release -- sorry, we'll try to include it in a future version!
+ Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"`
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob. In proto3, only explicit setting it to
+ // false will avoid using packed encoding.
+ Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"`
+ // The jstype option determines the JavaScript type used for values of the
+ // field. The option is permitted only for 64 bit integral and fixed types
+ // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
+ // is represented as JavaScript string, which avoids loss of precision that
+ // can happen when a large value is converted to a floating point JavaScript.
+ // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+ // use the JavaScript "number" type. The behavior of the default option
+ // JS_NORMAL is implementation dependent.
+ //
+ // This option is an enum to permit additional types to be added, e.g.
+ // goog.math.Integer.
+ Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"`
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outer message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"`
+ // Is this field deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for accessors, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating fields.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // For Google-internal migration only. Do not use.
+ Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FieldOptions) Reset() { *m = FieldOptions{} }
+func (m *FieldOptions) String() string { return proto.CompactTextString(m) }
+func (*FieldOptions) ProtoMessage() {}
+func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
+
+var extRange_FieldOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_FieldOptions
+}
+
+const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
+const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL
+const Default_FieldOptions_Lazy bool = false
+const Default_FieldOptions_Deprecated bool = false
+const Default_FieldOptions_Weak bool = false
+
+func (m *FieldOptions) GetCtype() FieldOptions_CType {
+ if m != nil && m.Ctype != nil {
+ return *m.Ctype
+ }
+ return Default_FieldOptions_Ctype
+}
+
+func (m *FieldOptions) GetPacked() bool {
+ if m != nil && m.Packed != nil {
+ return *m.Packed
+ }
+ return false
+}
+
+func (m *FieldOptions) GetJstype() FieldOptions_JSType {
+ if m != nil && m.Jstype != nil {
+ return *m.Jstype
+ }
+ return Default_FieldOptions_Jstype
+}
+
+func (m *FieldOptions) GetLazy() bool {
+ if m != nil && m.Lazy != nil {
+ return *m.Lazy
+ }
+ return Default_FieldOptions_Lazy
+}
+
+func (m *FieldOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_FieldOptions_Deprecated
+}
+
+func (m *FieldOptions) GetWeak() bool {
+ if m != nil && m.Weak != nil {
+ return *m.Weak
+ }
+ return Default_FieldOptions_Weak
+}
+
+func (m *FieldOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type OneofOptions struct {
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *OneofOptions) Reset() { *m = OneofOptions{} }
+func (m *OneofOptions) String() string { return proto.CompactTextString(m) }
+func (*OneofOptions) ProtoMessage() {}
+func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
+
+var extRange_OneofOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*OneofOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_OneofOptions
+}
+
+func (m *OneofOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type EnumOptions struct {
+ // Set this option to true to allow mapping different tag names to the same
+ // value.
+ AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"`
+ // Is this enum deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating enums.
+ Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumOptions) Reset() { *m = EnumOptions{} }
+func (m *EnumOptions) String() string { return proto.CompactTextString(m) }
+func (*EnumOptions) ProtoMessage() {}
+func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
+
+var extRange_EnumOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumOptions
+}
+
+const Default_EnumOptions_Deprecated bool = false
+
+func (m *EnumOptions) GetAllowAlias() bool {
+ if m != nil && m.AllowAlias != nil {
+ return *m.AllowAlias
+ }
+ return false
+}
+
+func (m *EnumOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_EnumOptions_Deprecated
+}
+
+func (m *EnumOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type EnumValueOptions struct {
+ // Is this enum value deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum value, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating enum values.
+ Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
+func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) }
+func (*EnumValueOptions) ProtoMessage() {}
+func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
+
+var extRange_EnumValueOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_EnumValueOptions
+}
+
+const Default_EnumValueOptions_Deprecated bool = false
+
+func (m *EnumValueOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_EnumValueOptions_Deprecated
+}
+
+func (m *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type ServiceOptions struct {
+ // Is this service deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the service, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating services.
+ Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
+func (m *ServiceOptions) String() string { return proto.CompactTextString(m) }
+func (*ServiceOptions) ProtoMessage() {}
+func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
+
+var extRange_ServiceOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_ServiceOptions
+}
+
+const Default_ServiceOptions_Deprecated bool = false
+
+func (m *ServiceOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_ServiceOptions_Deprecated
+}
+
+func (m *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+type MethodOptions struct {
+ // Is this method deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the method, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating methods.
+ Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
+ IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"`
+ // The parser stores options it doesn't recognize here. See above.
+ UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
+ proto.XXX_InternalExtensions `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MethodOptions) Reset() { *m = MethodOptions{} }
+func (m *MethodOptions) String() string { return proto.CompactTextString(m) }
+func (*MethodOptions) ProtoMessage() {}
+func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
+
+var extRange_MethodOptions = []proto.ExtensionRange{
+ {1000, 536870911},
+}
+
+func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
+ return extRange_MethodOptions
+}
+
+const Default_MethodOptions_Deprecated bool = false
+const Default_MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN
+
+func (m *MethodOptions) GetDeprecated() bool {
+ if m != nil && m.Deprecated != nil {
+ return *m.Deprecated
+ }
+ return Default_MethodOptions_Deprecated
+}
+
+func (m *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel {
+ if m != nil && m.IdempotencyLevel != nil {
+ return *m.IdempotencyLevel
+ }
+ return Default_MethodOptions_IdempotencyLevel
+}
+
+func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption {
+ if m != nil {
+ return m.UninterpretedOption
+ }
+ return nil
+}
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+type UninterpretedOption struct {
+ Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"`
+ // The value of the uninterpreted option, in whatever type the tokenizer
+ // identified it as during parsing. Exactly one of these should be set.
+ IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"`
+ PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"`
+ NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"`
+ DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"`
+ StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"`
+ AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} }
+func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) }
+func (*UninterpretedOption) ProtoMessage() {}
+func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
+
+func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart {
+ if m != nil {
+ return m.Name
+ }
+ return nil
+}
+
+func (m *UninterpretedOption) GetIdentifierValue() string {
+ if m != nil && m.IdentifierValue != nil {
+ return *m.IdentifierValue
+ }
+ return ""
+}
+
+func (m *UninterpretedOption) GetPositiveIntValue() uint64 {
+ if m != nil && m.PositiveIntValue != nil {
+ return *m.PositiveIntValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetNegativeIntValue() int64 {
+ if m != nil && m.NegativeIntValue != nil {
+ return *m.NegativeIntValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetDoubleValue() float64 {
+ if m != nil && m.DoubleValue != nil {
+ return *m.DoubleValue
+ }
+ return 0
+}
+
+func (m *UninterpretedOption) GetStringValue() []byte {
+ if m != nil {
+ return m.StringValue
+ }
+ return nil
+}
+
+func (m *UninterpretedOption) GetAggregateValue() string {
+ if m != nil && m.AggregateValue != nil {
+ return *m.AggregateValue
+ }
+ return ""
+}
+
+// The name of the uninterpreted option. Each string represents a segment in
+// a dot-separated name. is_extension is true iff a segment represents an
+// extension (denoted with parentheses in options specs in .proto files).
+// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+// "foo.(bar.baz).qux".
+type UninterpretedOption_NamePart struct {
+ NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"`
+ IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOption_NamePart{} }
+func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) }
+func (*UninterpretedOption_NamePart) ProtoMessage() {}
+func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{18, 0}
+}
+
+func (m *UninterpretedOption_NamePart) GetNamePart() string {
+ if m != nil && m.NamePart != nil {
+ return *m.NamePart
+ }
+ return ""
+}
+
+func (m *UninterpretedOption_NamePart) GetIsExtension() bool {
+ if m != nil && m.IsExtension != nil {
+ return *m.IsExtension
+ }
+ return false
+}
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+type SourceCodeInfo struct {
+ // A Location identifies a piece of source code in a .proto file which
+ // corresponds to a particular definition. This information is intended
+ // to be useful to IDEs, code indexers, documentation generators, and similar
+ // tools.
+ //
+ // For example, say we have a file like:
+ // message Foo {
+ // optional string foo = 1;
+ // }
+ // Let's look at just the field definition:
+ // optional string foo = 1;
+ // ^ ^^ ^^ ^ ^^^
+ // a bc de f ghi
+ // We have the following locations:
+ // span path represents
+ // [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ //
+ // Notes:
+ // - A location may refer to a repeated field itself (i.e. not to any
+ // particular index within it). This is used whenever a set of elements are
+ // logically enclosed in a single code segment. For example, an entire
+ // extend block (possibly containing multiple extension definitions) will
+ // have an outer location whose path refers to the "extensions" repeated
+ // field without an index.
+ // - Multiple locations may have the same path. This happens when a single
+ // logical declaration is spread out across multiple places. The most
+ // obvious example is the "extend" block again -- there may be multiple
+ // extend blocks in the same scope, each of which will have the same path.
+ // - A location's span is not always a subset of its parent's span. For
+ // example, the "extendee" of an extension declaration appears at the
+ // beginning of the "extend" block and is shared by all extensions within
+ // the block.
+ // - Just because a location's span is a subset of some other location's span
+ // does not mean that it is a descendent. For example, a "group" defines
+ // both a type and a field in a single declaration. Thus, the locations
+ // corresponding to the type and field and their components will overlap.
+ // - Code which tries to interpret locations should probably be designed to
+ // ignore those that it doesn't understand, as more types of locations could
+ // be recorded in the future.
+ Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} }
+func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) }
+func (*SourceCodeInfo) ProtoMessage() {}
+func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
+
+func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location {
+ if m != nil {
+ return m.Location
+ }
+ return nil
+}
+
+type SourceCodeInfo_Location struct {
+ // Identifies which part of the FileDescriptorProto was defined at this
+ // location.
+ //
+ // Each element is a field number or an index. They form a path from
+ // the root FileDescriptorProto to the place where the definition. For
+ // example, this path:
+ // [ 4, 3, 2, 7, 1 ]
+ // refers to:
+ // file.message_type(3) // 4, 3
+ // .field(7) // 2, 7
+ // .name() // 1
+ // This is because FileDescriptorProto.message_type has field number 4:
+ // repeated DescriptorProto message_type = 4;
+ // and DescriptorProto.field has field number 2:
+ // repeated FieldDescriptorProto field = 2;
+ // and FieldDescriptorProto.name has field number 1:
+ // optional string name = 1;
+ //
+ // Thus, the above path gives the location of a field name. If we removed
+ // the last element:
+ // [ 4, 3, 2, 7 ]
+ // this path refers to the whole field declaration (from the beginning
+ // of the label to the terminating semicolon).
+ Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"`
+ // Always has exactly three or four elements: start line, start column,
+ // end line (optional, otherwise assumed same as start line), end column.
+ // These are packed into a single field for efficiency. Note that line
+ // and column numbers are zero-based -- typically you will want to add
+ // 1 to each before displaying to a user.
+ Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"`
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // leading_detached_comments will keep paragraphs of comments that appear
+ // before (but not connected to) the current element. Each paragraph,
+ // separated by empty lines, will be one comment element in the repeated
+ // field.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // // Detached comment for corge. This is not leading or trailing comments
+ // // to qux or corge because there are blank lines separating it from
+ // // both.
+ //
+ // // Detached comment for corge paragraph 2.
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ //
+ // // ignored detached comments.
+ LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"`
+ TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"`
+ LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} }
+func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) }
+func (*SourceCodeInfo_Location) ProtoMessage() {}
+func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} }
+
+func (m *SourceCodeInfo_Location) GetPath() []int32 {
+ if m != nil {
+ return m.Path
+ }
+ return nil
+}
+
+func (m *SourceCodeInfo_Location) GetSpan() []int32 {
+ if m != nil {
+ return m.Span
+ }
+ return nil
+}
+
+func (m *SourceCodeInfo_Location) GetLeadingComments() string {
+ if m != nil && m.LeadingComments != nil {
+ return *m.LeadingComments
+ }
+ return ""
+}
+
+func (m *SourceCodeInfo_Location) GetTrailingComments() string {
+ if m != nil && m.TrailingComments != nil {
+ return *m.TrailingComments
+ }
+ return ""
+}
+
+func (m *SourceCodeInfo_Location) GetLeadingDetachedComments() []string {
+ if m != nil {
+ return m.LeadingDetachedComments
+ }
+ return nil
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+type GeneratedCodeInfo struct {
+ // An Annotation connects some span of text in generated code to an element
+ // of its generating .proto file.
+ Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} }
+func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) }
+func (*GeneratedCodeInfo) ProtoMessage() {}
+func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
+
+func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation {
+ if m != nil {
+ return m.Annotation
+ }
+ return nil
+}
+
+type GeneratedCodeInfo_Annotation struct {
+ // Identifies the element in the original source .proto file. This field
+ // is formatted the same as SourceCodeInfo.Location.path.
+ Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"`
+ // Identifies the filesystem path to the original source .proto.
+ SourceFile *string `protobuf:"bytes,2,opt,name=source_file,json=sourceFile" json:"source_file,omitempty"`
+ // Identifies the starting offset in bytes in the generated code
+ // that relates to the identified object.
+ Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"`
+ // Identifies the ending offset in bytes in the generated code that
+ // relates to the identified offset. The end offset should be one past
+ // the last relevant byte (so the length of the text = end - begin).
+ End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_Annotation{} }
+func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) }
+func (*GeneratedCodeInfo_Annotation) ProtoMessage() {}
+func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) {
+ return fileDescriptor0, []int{20, 0}
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 {
+ if m != nil {
+ return m.Path
+ }
+ return nil
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetSourceFile() string {
+ if m != nil && m.SourceFile != nil {
+ return *m.SourceFile
+ }
+ return ""
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetBegin() int32 {
+ if m != nil && m.Begin != nil {
+ return *m.Begin
+ }
+ return 0
+}
+
+func (m *GeneratedCodeInfo_Annotation) GetEnd() int32 {
+ if m != nil && m.End != nil {
+ return *m.End
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*FileDescriptorSet)(nil), "google.protobuf.FileDescriptorSet")
+ proto.RegisterType((*FileDescriptorProto)(nil), "google.protobuf.FileDescriptorProto")
+ proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto")
+ proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
+ proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
+ proto.RegisterType((*ExtensionRangeOptions)(nil), "google.protobuf.ExtensionRangeOptions")
+ proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
+ proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
+ proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
+ proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto")
+ proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto")
+ proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto")
+ proto.RegisterType((*FileOptions)(nil), "google.protobuf.FileOptions")
+ proto.RegisterType((*MessageOptions)(nil), "google.protobuf.MessageOptions")
+ proto.RegisterType((*FieldOptions)(nil), "google.protobuf.FieldOptions")
+ proto.RegisterType((*OneofOptions)(nil), "google.protobuf.OneofOptions")
+ proto.RegisterType((*EnumOptions)(nil), "google.protobuf.EnumOptions")
+ proto.RegisterType((*EnumValueOptions)(nil), "google.protobuf.EnumValueOptions")
+ proto.RegisterType((*ServiceOptions)(nil), "google.protobuf.ServiceOptions")
+ proto.RegisterType((*MethodOptions)(nil), "google.protobuf.MethodOptions")
+ proto.RegisterType((*UninterpretedOption)(nil), "google.protobuf.UninterpretedOption")
+ proto.RegisterType((*UninterpretedOption_NamePart)(nil), "google.protobuf.UninterpretedOption.NamePart")
+ proto.RegisterType((*SourceCodeInfo)(nil), "google.protobuf.SourceCodeInfo")
+ proto.RegisterType((*SourceCodeInfo_Location)(nil), "google.protobuf.SourceCodeInfo.Location")
+ proto.RegisterType((*GeneratedCodeInfo)(nil), "google.protobuf.GeneratedCodeInfo")
+ proto.RegisterType((*GeneratedCodeInfo_Annotation)(nil), "google.protobuf.GeneratedCodeInfo.Annotation")
+ proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value)
+ proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value)
+ proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value)
+ proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value)
+ proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value)
+ proto.RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", MethodOptions_IdempotencyLevel_name, MethodOptions_IdempotencyLevel_value)
+}
+
+func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 2519 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6e, 0x1b, 0xc7,
+ 0x15, 0x0e, 0x7f, 0x45, 0x1e, 0x52, 0xd4, 0x68, 0xa4, 0xd8, 0x6b, 0xe5, 0xc7, 0x32, 0xf3, 0x63,
+ 0xd9, 0x69, 0xa8, 0x40, 0xb1, 0x1d, 0x47, 0x29, 0xd2, 0x52, 0xe4, 0x5a, 0xa1, 0x4a, 0x91, 0xec,
+ 0x92, 0x6a, 0x7e, 0x6e, 0x16, 0xa3, 0xdd, 0x21, 0xb9, 0xf6, 0x72, 0x77, 0xb3, 0xbb, 0xb4, 0xad,
+ 0xa0, 0x17, 0x06, 0x7a, 0x55, 0xa0, 0x0f, 0x50, 0x14, 0x45, 0x2f, 0x72, 0x13, 0xa0, 0x0f, 0x50,
+ 0x20, 0x77, 0x7d, 0x82, 0x02, 0x79, 0x83, 0xa2, 0x28, 0xd0, 0x3e, 0x46, 0x31, 0x33, 0xbb, 0xcb,
+ 0x5d, 0xfe, 0xc4, 0x6a, 0x80, 0x38, 0x57, 0xe4, 0x7c, 0xe7, 0x3b, 0x67, 0xce, 0x9c, 0x39, 0x33,
+ 0x73, 0x66, 0x16, 0x76, 0x47, 0xb6, 0x3d, 0x32, 0xe9, 0xbe, 0xe3, 0xda, 0xbe, 0x7d, 0x3e, 0x1d,
+ 0xee, 0xeb, 0xd4, 0xd3, 0x5c, 0xc3, 0xf1, 0x6d, 0xb7, 0xc6, 0x31, 0xbc, 0x21, 0x18, 0xb5, 0x90,
+ 0x51, 0x3d, 0x85, 0xcd, 0x07, 0x86, 0x49, 0x9b, 0x11, 0xb1, 0x4f, 0x7d, 0x7c, 0x1f, 0xb2, 0x43,
+ 0xc3, 0xa4, 0x52, 0x6a, 0x37, 0xb3, 0x57, 0x3a, 0x78, 0xb3, 0x36, 0xa7, 0x54, 0x4b, 0x6a, 0xf4,
+ 0x18, 0xac, 0x70, 0x8d, 0xea, 0xbf, 0xb3, 0xb0, 0xb5, 0x44, 0x8a, 0x31, 0x64, 0x2d, 0x32, 0x61,
+ 0x16, 0x53, 0x7b, 0x45, 0x85, 0xff, 0xc7, 0x12, 0xac, 0x39, 0x44, 0x7b, 0x44, 0x46, 0x54, 0x4a,
+ 0x73, 0x38, 0x6c, 0xe2, 0xd7, 0x01, 0x74, 0xea, 0x50, 0x4b, 0xa7, 0x96, 0x76, 0x21, 0x65, 0x76,
+ 0x33, 0x7b, 0x45, 0x25, 0x86, 0xe0, 0x77, 0x60, 0xd3, 0x99, 0x9e, 0x9b, 0x86, 0xa6, 0xc6, 0x68,
+ 0xb0, 0x9b, 0xd9, 0xcb, 0x29, 0x48, 0x08, 0x9a, 0x33, 0xf2, 0x4d, 0xd8, 0x78, 0x42, 0xc9, 0xa3,
+ 0x38, 0xb5, 0xc4, 0xa9, 0x15, 0x06, 0xc7, 0x88, 0x0d, 0x28, 0x4f, 0xa8, 0xe7, 0x91, 0x11, 0x55,
+ 0xfd, 0x0b, 0x87, 0x4a, 0x59, 0x3e, 0xfa, 0xdd, 0x85, 0xd1, 0xcf, 0x8f, 0xbc, 0x14, 0x68, 0x0d,
+ 0x2e, 0x1c, 0x8a, 0xeb, 0x50, 0xa4, 0xd6, 0x74, 0x22, 0x2c, 0xe4, 0x56, 0xc4, 0x4f, 0xb6, 0xa6,
+ 0x93, 0x79, 0x2b, 0x05, 0xa6, 0x16, 0x98, 0x58, 0xf3, 0xa8, 0xfb, 0xd8, 0xd0, 0xa8, 0x94, 0xe7,
+ 0x06, 0x6e, 0x2e, 0x18, 0xe8, 0x0b, 0xf9, 0xbc, 0x8d, 0x50, 0x0f, 0x37, 0xa0, 0x48, 0x9f, 0xfa,
+ 0xd4, 0xf2, 0x0c, 0xdb, 0x92, 0xd6, 0xb8, 0x91, 0xb7, 0x96, 0xcc, 0x22, 0x35, 0xf5, 0x79, 0x13,
+ 0x33, 0x3d, 0x7c, 0x0f, 0xd6, 0x6c, 0xc7, 0x37, 0x6c, 0xcb, 0x93, 0x0a, 0xbb, 0xa9, 0xbd, 0xd2,
+ 0xc1, 0xab, 0x4b, 0x13, 0xa1, 0x2b, 0x38, 0x4a, 0x48, 0xc6, 0x2d, 0x40, 0x9e, 0x3d, 0x75, 0x35,
+ 0xaa, 0x6a, 0xb6, 0x4e, 0x55, 0xc3, 0x1a, 0xda, 0x52, 0x91, 0x1b, 0xb8, 0xbe, 0x38, 0x10, 0x4e,
+ 0x6c, 0xd8, 0x3a, 0x6d, 0x59, 0x43, 0x5b, 0xa9, 0x78, 0x89, 0x36, 0xbe, 0x02, 0x79, 0xef, 0xc2,
+ 0xf2, 0xc9, 0x53, 0xa9, 0xcc, 0x33, 0x24, 0x68, 0x55, 0xbf, 0xcd, 0xc3, 0xc6, 0x65, 0x52, 0xec,
+ 0x23, 0xc8, 0x0d, 0xd9, 0x28, 0xa5, 0xf4, 0xff, 0x13, 0x03, 0xa1, 0x93, 0x0c, 0x62, 0xfe, 0x07,
+ 0x06, 0xb1, 0x0e, 0x25, 0x8b, 0x7a, 0x3e, 0xd5, 0x45, 0x46, 0x64, 0x2e, 0x99, 0x53, 0x20, 0x94,
+ 0x16, 0x53, 0x2a, 0xfb, 0x83, 0x52, 0xea, 0x33, 0xd8, 0x88, 0x5c, 0x52, 0x5d, 0x62, 0x8d, 0xc2,
+ 0xdc, 0xdc, 0x7f, 0x9e, 0x27, 0x35, 0x39, 0xd4, 0x53, 0x98, 0x9a, 0x52, 0xa1, 0x89, 0x36, 0x6e,
+ 0x02, 0xd8, 0x16, 0xb5, 0x87, 0xaa, 0x4e, 0x35, 0x53, 0x2a, 0xac, 0x88, 0x52, 0x97, 0x51, 0x16,
+ 0xa2, 0x64, 0x0b, 0x54, 0x33, 0xf1, 0x87, 0xb3, 0x54, 0x5b, 0x5b, 0x91, 0x29, 0xa7, 0x62, 0x91,
+ 0x2d, 0x64, 0xdb, 0x19, 0x54, 0x5c, 0xca, 0xf2, 0x9e, 0xea, 0xc1, 0xc8, 0x8a, 0xdc, 0x89, 0xda,
+ 0x73, 0x47, 0xa6, 0x04, 0x6a, 0x62, 0x60, 0xeb, 0x6e, 0xbc, 0x89, 0xdf, 0x80, 0x08, 0x50, 0x79,
+ 0x5a, 0x01, 0xdf, 0x85, 0xca, 0x21, 0xd8, 0x21, 0x13, 0xba, 0xf3, 0x15, 0x54, 0x92, 0xe1, 0xc1,
+ 0xdb, 0x90, 0xf3, 0x7c, 0xe2, 0xfa, 0x3c, 0x0b, 0x73, 0x8a, 0x68, 0x60, 0x04, 0x19, 0x6a, 0xe9,
+ 0x7c, 0x97, 0xcb, 0x29, 0xec, 0x2f, 0xfe, 0xe5, 0x6c, 0xc0, 0x19, 0x3e, 0xe0, 0xb7, 0x17, 0x67,
+ 0x34, 0x61, 0x79, 0x7e, 0xdc, 0x3b, 0x1f, 0xc0, 0x7a, 0x62, 0x00, 0x97, 0xed, 0xba, 0xfa, 0x5b,
+ 0x78, 0x79, 0xa9, 0x69, 0xfc, 0x19, 0x6c, 0x4f, 0x2d, 0xc3, 0xf2, 0xa9, 0xeb, 0xb8, 0x94, 0x65,
+ 0xac, 0xe8, 0x4a, 0xfa, 0xcf, 0xda, 0x8a, 0x9c, 0x3b, 0x8b, 0xb3, 0x85, 0x15, 0x65, 0x6b, 0xba,
+ 0x08, 0xde, 0x2e, 0x16, 0xfe, 0xbb, 0x86, 0x9e, 0x3d, 0x7b, 0xf6, 0x2c, 0x5d, 0xfd, 0x63, 0x1e,
+ 0xb6, 0x97, 0xad, 0x99, 0xa5, 0xcb, 0xf7, 0x0a, 0xe4, 0xad, 0xe9, 0xe4, 0x9c, 0xba, 0x3c, 0x48,
+ 0x39, 0x25, 0x68, 0xe1, 0x3a, 0xe4, 0x4c, 0x72, 0x4e, 0x4d, 0x29, 0xbb, 0x9b, 0xda, 0xab, 0x1c,
+ 0xbc, 0x73, 0xa9, 0x55, 0x59, 0x6b, 0x33, 0x15, 0x45, 0x68, 0xe2, 0x8f, 0x21, 0x1b, 0x6c, 0xd1,
+ 0xcc, 0xc2, 0xed, 0xcb, 0x59, 0x60, 0x6b, 0x49, 0xe1, 0x7a, 0xf8, 0x15, 0x28, 0xb2, 0x5f, 0x91,
+ 0x1b, 0x79, 0xee, 0x73, 0x81, 0x01, 0x2c, 0x2f, 0xf0, 0x0e, 0x14, 0xf8, 0x32, 0xd1, 0x69, 0x78,
+ 0xb4, 0x45, 0x6d, 0x96, 0x58, 0x3a, 0x1d, 0x92, 0xa9, 0xe9, 0xab, 0x8f, 0x89, 0x39, 0xa5, 0x3c,
+ 0xe1, 0x8b, 0x4a, 0x39, 0x00, 0x7f, 0xc3, 0x30, 0x7c, 0x1d, 0x4a, 0x62, 0x55, 0x19, 0x96, 0x4e,
+ 0x9f, 0xf2, 0xdd, 0x33, 0xa7, 0x88, 0x85, 0xd6, 0x62, 0x08, 0xeb, 0xfe, 0xa1, 0x67, 0x5b, 0x61,
+ 0x6a, 0xf2, 0x2e, 0x18, 0xc0, 0xbb, 0xff, 0x60, 0x7e, 0xe3, 0x7e, 0x6d, 0xf9, 0xf0, 0xe6, 0x73,
+ 0xaa, 0xfa, 0xb7, 0x34, 0x64, 0xf9, 0x7e, 0xb1, 0x01, 0xa5, 0xc1, 0xe7, 0x3d, 0x59, 0x6d, 0x76,
+ 0xcf, 0x8e, 0xda, 0x32, 0x4a, 0xe1, 0x0a, 0x00, 0x07, 0x1e, 0xb4, 0xbb, 0xf5, 0x01, 0x4a, 0x47,
+ 0xed, 0x56, 0x67, 0x70, 0xef, 0x0e, 0xca, 0x44, 0x0a, 0x67, 0x02, 0xc8, 0xc6, 0x09, 0xef, 0x1f,
+ 0xa0, 0x1c, 0x46, 0x50, 0x16, 0x06, 0x5a, 0x9f, 0xc9, 0xcd, 0x7b, 0x77, 0x50, 0x3e, 0x89, 0xbc,
+ 0x7f, 0x80, 0xd6, 0xf0, 0x3a, 0x14, 0x39, 0x72, 0xd4, 0xed, 0xb6, 0x51, 0x21, 0xb2, 0xd9, 0x1f,
+ 0x28, 0xad, 0xce, 0x31, 0x2a, 0x46, 0x36, 0x8f, 0x95, 0xee, 0x59, 0x0f, 0x41, 0x64, 0xe1, 0x54,
+ 0xee, 0xf7, 0xeb, 0xc7, 0x32, 0x2a, 0x45, 0x8c, 0xa3, 0xcf, 0x07, 0x72, 0x1f, 0x95, 0x13, 0x6e,
+ 0xbd, 0x7f, 0x80, 0xd6, 0xa3, 0x2e, 0xe4, 0xce, 0xd9, 0x29, 0xaa, 0xe0, 0x4d, 0x58, 0x17, 0x5d,
+ 0x84, 0x4e, 0x6c, 0xcc, 0x41, 0xf7, 0xee, 0x20, 0x34, 0x73, 0x44, 0x58, 0xd9, 0x4c, 0x00, 0xf7,
+ 0xee, 0x20, 0x5c, 0x6d, 0x40, 0x8e, 0x67, 0x17, 0xc6, 0x50, 0x69, 0xd7, 0x8f, 0xe4, 0xb6, 0xda,
+ 0xed, 0x0d, 0x5a, 0xdd, 0x4e, 0xbd, 0x8d, 0x52, 0x33, 0x4c, 0x91, 0x7f, 0x7d, 0xd6, 0x52, 0xe4,
+ 0x26, 0x4a, 0xc7, 0xb1, 0x9e, 0x5c, 0x1f, 0xc8, 0x4d, 0x94, 0xa9, 0x6a, 0xb0, 0xbd, 0x6c, 0x9f,
+ 0x5c, 0xba, 0x32, 0x62, 0x53, 0x9c, 0x5e, 0x31, 0xc5, 0xdc, 0xd6, 0xc2, 0x14, 0x7f, 0x9d, 0x82,
+ 0xad, 0x25, 0x67, 0xc5, 0xd2, 0x4e, 0x7e, 0x01, 0x39, 0x91, 0xa2, 0xe2, 0xf4, 0xbc, 0xb5, 0xf4,
+ 0xd0, 0xe1, 0x09, 0xbb, 0x70, 0x82, 0x72, 0xbd, 0x78, 0x05, 0x91, 0x59, 0x51, 0x41, 0x30, 0x13,
+ 0x0b, 0x4e, 0xfe, 0x2e, 0x05, 0xd2, 0x2a, 0xdb, 0xcf, 0xd9, 0x28, 0xd2, 0x89, 0x8d, 0xe2, 0xa3,
+ 0x79, 0x07, 0x6e, 0xac, 0x1e, 0xc3, 0x82, 0x17, 0xdf, 0xa4, 0xe0, 0xca, 0xf2, 0x42, 0x6b, 0xa9,
+ 0x0f, 0x1f, 0x43, 0x7e, 0x42, 0xfd, 0xb1, 0x1d, 0x16, 0x1b, 0x6f, 0x2f, 0x39, 0xc2, 0x98, 0x78,
+ 0x3e, 0x56, 0x81, 0x56, 0xfc, 0x0c, 0xcc, 0xac, 0xaa, 0x96, 0x84, 0x37, 0x0b, 0x9e, 0xfe, 0x3e,
+ 0x0d, 0x2f, 0x2f, 0x35, 0xbe, 0xd4, 0xd1, 0xd7, 0x00, 0x0c, 0xcb, 0x99, 0xfa, 0xa2, 0xa0, 0x10,
+ 0xfb, 0x53, 0x91, 0x23, 0x7c, 0xed, 0xb3, 0xbd, 0x67, 0xea, 0x47, 0xf2, 0x0c, 0x97, 0x83, 0x80,
+ 0x38, 0xe1, 0xfe, 0xcc, 0xd1, 0x2c, 0x77, 0xf4, 0xf5, 0x15, 0x23, 0x5d, 0x38, 0xab, 0xdf, 0x03,
+ 0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x26, 0x86, 0x35, 0xe2, 0x1b, 0x70, 0xe1,
+ 0x30, 0x37, 0x24, 0xa6, 0x47, 0x95, 0x0d, 0x21, 0xee, 0x87, 0x52, 0xa6, 0xc1, 0xcf, 0x38, 0x37,
+ 0xa6, 0x91, 0x4f, 0x68, 0x08, 0x71, 0xa4, 0x51, 0xfd, 0xb6, 0x00, 0xa5, 0x58, 0x59, 0x8a, 0x6f,
+ 0x40, 0xf9, 0x21, 0x79, 0x4c, 0xd4, 0xf0, 0xaa, 0x21, 0x22, 0x51, 0x62, 0x58, 0x2f, 0xb8, 0x6e,
+ 0xbc, 0x07, 0xdb, 0x9c, 0x62, 0x4f, 0x7d, 0xea, 0xaa, 0x9a, 0x49, 0x3c, 0x8f, 0x07, 0xad, 0xc0,
+ 0xa9, 0x98, 0xc9, 0xba, 0x4c, 0xd4, 0x08, 0x25, 0xf8, 0x2e, 0x6c, 0x71, 0x8d, 0xc9, 0xd4, 0xf4,
+ 0x0d, 0xc7, 0xa4, 0x2a, 0xbb, 0xfc, 0x78, 0x7c, 0x23, 0x8e, 0x3c, 0xdb, 0x64, 0x8c, 0xd3, 0x80,
+ 0xc0, 0x3c, 0xf2, 0x70, 0x13, 0x5e, 0xe3, 0x6a, 0x23, 0x6a, 0x51, 0x97, 0xf8, 0x54, 0xa5, 0x5f,
+ 0x4e, 0x89, 0xe9, 0xa9, 0xc4, 0xd2, 0xd5, 0x31, 0xf1, 0xc6, 0xd2, 0x36, 0x33, 0x70, 0x94, 0x96,
+ 0x52, 0xca, 0x35, 0x46, 0x3c, 0x0e, 0x78, 0x32, 0xa7, 0xd5, 0x2d, 0xfd, 0x13, 0xe2, 0x8d, 0xf1,
+ 0x21, 0x5c, 0xe1, 0x56, 0x3c, 0xdf, 0x35, 0xac, 0x91, 0xaa, 0x8d, 0xa9, 0xf6, 0x48, 0x9d, 0xfa,
+ 0xc3, 0xfb, 0xd2, 0x2b, 0xf1, 0xfe, 0xb9, 0x87, 0x7d, 0xce, 0x69, 0x30, 0xca, 0x99, 0x3f, 0xbc,
+ 0x8f, 0xfb, 0x50, 0x66, 0x93, 0x31, 0x31, 0xbe, 0xa2, 0xea, 0xd0, 0x76, 0xf9, 0xc9, 0x52, 0x59,
+ 0xb2, 0xb2, 0x63, 0x11, 0xac, 0x75, 0x03, 0x85, 0x53, 0x5b, 0xa7, 0x87, 0xb9, 0x7e, 0x4f, 0x96,
+ 0x9b, 0x4a, 0x29, 0xb4, 0xf2, 0xc0, 0x76, 0x59, 0x42, 0x8d, 0xec, 0x28, 0xc0, 0x25, 0x91, 0x50,
+ 0x23, 0x3b, 0x0c, 0xef, 0x5d, 0xd8, 0xd2, 0x34, 0x31, 0x66, 0x43, 0x53, 0x83, 0x2b, 0x8a, 0x27,
+ 0xa1, 0x44, 0xb0, 0x34, 0xed, 0x58, 0x10, 0x82, 0x1c, 0xf7, 0xf0, 0x87, 0xf0, 0xf2, 0x2c, 0x58,
+ 0x71, 0xc5, 0xcd, 0x85, 0x51, 0xce, 0xab, 0xde, 0x85, 0x2d, 0xe7, 0x62, 0x51, 0x11, 0x27, 0x7a,
+ 0x74, 0x2e, 0xe6, 0xd5, 0x3e, 0x80, 0x6d, 0x67, 0xec, 0x2c, 0xea, 0xdd, 0x8e, 0xeb, 0x61, 0x67,
+ 0xec, 0xcc, 0x2b, 0xbe, 0xc5, 0xef, 0xab, 0x2e, 0xd5, 0x88, 0x4f, 0x75, 0xe9, 0x6a, 0x9c, 0x1e,
+ 0x13, 0xe0, 0x7d, 0x40, 0x9a, 0xa6, 0x52, 0x8b, 0x9c, 0x9b, 0x54, 0x25, 0x2e, 0xb5, 0x88, 0x27,
+ 0x5d, 0x8f, 0x93, 0x2b, 0x9a, 0x26, 0x73, 0x69, 0x9d, 0x0b, 0xf1, 0x6d, 0xd8, 0xb4, 0xcf, 0x1f,
+ 0x6a, 0x22, 0x25, 0x55, 0xc7, 0xa5, 0x43, 0xe3, 0xa9, 0xf4, 0x26, 0x8f, 0xef, 0x06, 0x13, 0xf0,
+ 0x84, 0xec, 0x71, 0x18, 0xdf, 0x02, 0xa4, 0x79, 0x63, 0xe2, 0x3a, 0xbc, 0x26, 0xf0, 0x1c, 0xa2,
+ 0x51, 0xe9, 0x2d, 0x41, 0x15, 0x78, 0x27, 0x84, 0xd9, 0x92, 0xf0, 0x9e, 0x18, 0x43, 0x3f, 0xb4,
+ 0x78, 0x53, 0x2c, 0x09, 0x8e, 0x05, 0xd6, 0xf6, 0x00, 0xb1, 0x50, 0x24, 0x3a, 0xde, 0xe3, 0xb4,
+ 0x8a, 0x33, 0x76, 0xe2, 0xfd, 0xbe, 0x01, 0xeb, 0x8c, 0x39, 0xeb, 0xf4, 0x96, 0xa8, 0x67, 0x9c,
+ 0x71, 0xac, 0xc7, 0x1f, 0xad, 0xb4, 0xac, 0x1e, 0x42, 0x39, 0x9e, 0x9f, 0xb8, 0x08, 0x22, 0x43,
+ 0x51, 0x8a, 0x9d, 0xf5, 0x8d, 0x6e, 0x93, 0x9d, 0xd2, 0x5f, 0xc8, 0x28, 0xcd, 0xaa, 0x85, 0x76,
+ 0x6b, 0x20, 0xab, 0xca, 0x59, 0x67, 0xd0, 0x3a, 0x95, 0x51, 0x26, 0x56, 0x96, 0x9e, 0x64, 0x0b,
+ 0x6f, 0xa3, 0x9b, 0xd5, 0xef, 0xd2, 0x50, 0x49, 0xde, 0x33, 0xf0, 0xcf, 0xe1, 0x6a, 0xf8, 0x28,
+ 0xe0, 0x51, 0x5f, 0x7d, 0x62, 0xb8, 0x7c, 0xe1, 0x4c, 0x88, 0xa8, 0xb3, 0xa3, 0xa9, 0xdb, 0x0e,
+ 0x58, 0x7d, 0xea, 0x7f, 0x6a, 0xb8, 0x6c, 0x59, 0x4c, 0x88, 0x8f, 0xdb, 0x70, 0xdd, 0xb2, 0x55,
+ 0xcf, 0x27, 0x96, 0x4e, 0x5c, 0x5d, 0x9d, 0x3d, 0xc7, 0xa8, 0x44, 0xd3, 0xa8, 0xe7, 0xd9, 0xe2,
+ 0xc0, 0x8a, 0xac, 0xbc, 0x6a, 0xd9, 0xfd, 0x80, 0x3c, 0xdb, 0xc9, 0xeb, 0x01, 0x75, 0x2e, 0xcd,
+ 0x32, 0xab, 0xd2, 0xec, 0x15, 0x28, 0x4e, 0x88, 0xa3, 0x52, 0xcb, 0x77, 0x2f, 0x78, 0x75, 0x59,
+ 0x50, 0x0a, 0x13, 0xe2, 0xc8, 0xac, 0xfd, 0x42, 0x8a, 0xfc, 0x93, 0x6c, 0xa1, 0x80, 0x8a, 0x27,
+ 0xd9, 0x42, 0x11, 0x41, 0xf5, 0x5f, 0x19, 0x28, 0xc7, 0xab, 0x4d, 0x56, 0xbc, 0x6b, 0xfc, 0x64,
+ 0x49, 0xf1, 0xbd, 0xe7, 0x8d, 0xef, 0xad, 0x4d, 0x6b, 0x0d, 0x76, 0xe4, 0x1c, 0xe6, 0x45, 0x0d,
+ 0xa8, 0x08, 0x4d, 0x76, 0xdc, 0xb3, 0xdd, 0x86, 0x8a, 0x7b, 0x4d, 0x41, 0x09, 0x5a, 0xf8, 0x18,
+ 0xf2, 0x0f, 0x3d, 0x6e, 0x3b, 0xcf, 0x6d, 0xbf, 0xf9, 0xfd, 0xb6, 0x4f, 0xfa, 0xdc, 0x78, 0xf1,
+ 0xa4, 0xaf, 0x76, 0xba, 0xca, 0x69, 0xbd, 0xad, 0x04, 0xea, 0xf8, 0x1a, 0x64, 0x4d, 0xf2, 0xd5,
+ 0x45, 0xf2, 0x70, 0xe2, 0xd0, 0x65, 0x27, 0xe1, 0x1a, 0x64, 0x9f, 0x50, 0xf2, 0x28, 0x79, 0x24,
+ 0x70, 0xe8, 0x47, 0x5c, 0x0c, 0xfb, 0x90, 0xe3, 0xf1, 0xc2, 0x00, 0x41, 0xc4, 0xd0, 0x4b, 0xb8,
+ 0x00, 0xd9, 0x46, 0x57, 0x61, 0x0b, 0x02, 0x41, 0x59, 0xa0, 0x6a, 0xaf, 0x25, 0x37, 0x64, 0x94,
+ 0xae, 0xde, 0x85, 0xbc, 0x08, 0x02, 0x5b, 0x2c, 0x51, 0x18, 0xd0, 0x4b, 0x41, 0x33, 0xb0, 0x91,
+ 0x0a, 0xa5, 0x67, 0xa7, 0x47, 0xb2, 0x82, 0xd2, 0xc9, 0xa9, 0xce, 0xa2, 0x5c, 0xd5, 0x83, 0x72,
+ 0xbc, 0xdc, 0x7c, 0x31, 0x57, 0xc9, 0xbf, 0xa7, 0xa0, 0x14, 0x2b, 0x1f, 0x59, 0xe1, 0x42, 0x4c,
+ 0xd3, 0x7e, 0xa2, 0x12, 0xd3, 0x20, 0x5e, 0x90, 0x1a, 0xc0, 0xa1, 0x3a, 0x43, 0x2e, 0x3b, 0x75,
+ 0x2f, 0x68, 0x89, 0xe4, 0x50, 0xbe, 0xfa, 0x97, 0x14, 0xa0, 0xf9, 0x02, 0x74, 0xce, 0xcd, 0xd4,
+ 0x4f, 0xe9, 0x66, 0xf5, 0xcf, 0x29, 0xa8, 0x24, 0xab, 0xce, 0x39, 0xf7, 0x6e, 0xfc, 0xa4, 0xee,
+ 0xfd, 0x33, 0x0d, 0xeb, 0x89, 0x5a, 0xf3, 0xb2, 0xde, 0x7d, 0x09, 0x9b, 0x86, 0x4e, 0x27, 0x8e,
+ 0xed, 0x53, 0x4b, 0xbb, 0x50, 0x4d, 0xfa, 0x98, 0x9a, 0x52, 0x95, 0x6f, 0x1a, 0xfb, 0xdf, 0x5f,
+ 0xcd, 0xd6, 0x5a, 0x33, 0xbd, 0x36, 0x53, 0x3b, 0xdc, 0x6a, 0x35, 0xe5, 0xd3, 0x5e, 0x77, 0x20,
+ 0x77, 0x1a, 0x9f, 0xab, 0x67, 0x9d, 0x5f, 0x75, 0xba, 0x9f, 0x76, 0x14, 0x64, 0xcc, 0xd1, 0x7e,
+ 0xc4, 0x65, 0xdf, 0x03, 0x34, 0xef, 0x14, 0xbe, 0x0a, 0xcb, 0xdc, 0x42, 0x2f, 0xe1, 0x2d, 0xd8,
+ 0xe8, 0x74, 0xd5, 0x7e, 0xab, 0x29, 0xab, 0xf2, 0x83, 0x07, 0x72, 0x63, 0xd0, 0x17, 0xd7, 0xfb,
+ 0x88, 0x3d, 0x48, 0x2c, 0xf0, 0xea, 0x9f, 0x32, 0xb0, 0xb5, 0xc4, 0x13, 0x5c, 0x0f, 0x6e, 0x16,
+ 0xe2, 0xb2, 0xf3, 0xee, 0x65, 0xbc, 0xaf, 0xb1, 0x82, 0xa0, 0x47, 0x5c, 0x3f, 0xb8, 0x88, 0xdc,
+ 0x02, 0x16, 0x25, 0xcb, 0x37, 0x86, 0x06, 0x75, 0x83, 0xd7, 0x10, 0x71, 0xdd, 0xd8, 0x98, 0xe1,
+ 0xe2, 0x41, 0xe4, 0x67, 0x80, 0x1d, 0xdb, 0x33, 0x7c, 0xe3, 0x31, 0x55, 0x0d, 0x2b, 0x7c, 0x3a,
+ 0x61, 0xd7, 0x8f, 0xac, 0x82, 0x42, 0x49, 0xcb, 0xf2, 0x23, 0xb6, 0x45, 0x47, 0x64, 0x8e, 0xcd,
+ 0x36, 0xf3, 0x8c, 0x82, 0x42, 0x49, 0xc4, 0xbe, 0x01, 0x65, 0xdd, 0x9e, 0xb2, 0x9a, 0x4c, 0xf0,
+ 0xd8, 0xd9, 0x91, 0x52, 0x4a, 0x02, 0x8b, 0x28, 0x41, 0xb5, 0x3d, 0x7b, 0xb3, 0x29, 0x2b, 0x25,
+ 0x81, 0x09, 0xca, 0x4d, 0xd8, 0x20, 0xa3, 0x91, 0xcb, 0x8c, 0x87, 0x86, 0xc4, 0xfd, 0xa1, 0x12,
+ 0xc1, 0x9c, 0xb8, 0x73, 0x02, 0x85, 0x30, 0x0e, 0xec, 0xa8, 0x66, 0x91, 0x50, 0x1d, 0xf1, 0x6e,
+ 0x97, 0xde, 0x2b, 0x2a, 0x05, 0x2b, 0x14, 0xde, 0x80, 0xb2, 0xe1, 0xa9, 0xb3, 0x27, 0xe8, 0xf4,
+ 0x6e, 0x7a, 0xaf, 0xa0, 0x94, 0x0c, 0x2f, 0x7a, 0xbe, 0xab, 0x7e, 0x93, 0x86, 0x4a, 0xf2, 0x09,
+ 0x1d, 0x37, 0xa1, 0x60, 0xda, 0x1a, 0xe1, 0xa9, 0x25, 0xbe, 0xdf, 0xec, 0x3d, 0xe7, 0xd5, 0xbd,
+ 0xd6, 0x0e, 0xf8, 0x4a, 0xa4, 0xb9, 0xf3, 0x8f, 0x14, 0x14, 0x42, 0x18, 0x5f, 0x81, 0xac, 0x43,
+ 0xfc, 0x31, 0x37, 0x97, 0x3b, 0x4a, 0xa3, 0x94, 0xc2, 0xdb, 0x0c, 0xf7, 0x1c, 0x62, 0xf1, 0x14,
+ 0x08, 0x70, 0xd6, 0x66, 0xf3, 0x6a, 0x52, 0xa2, 0xf3, 0xcb, 0x89, 0x3d, 0x99, 0x50, 0xcb, 0xf7,
+ 0xc2, 0x79, 0x0d, 0xf0, 0x46, 0x00, 0xe3, 0x77, 0x60, 0xd3, 0x77, 0x89, 0x61, 0x26, 0xb8, 0x59,
+ 0xce, 0x45, 0xa1, 0x20, 0x22, 0x1f, 0xc2, 0xb5, 0xd0, 0xae, 0x4e, 0x7d, 0xa2, 0x8d, 0xa9, 0x3e,
+ 0x53, 0xca, 0xf3, 0xf7, 0xd9, 0xab, 0x01, 0xa1, 0x19, 0xc8, 0x43, 0xdd, 0xea, 0x77, 0x29, 0xd8,
+ 0x0c, 0xaf, 0x53, 0x7a, 0x14, 0xac, 0x53, 0x00, 0x62, 0x59, 0xb6, 0x1f, 0x0f, 0xd7, 0x62, 0x2a,
+ 0x2f, 0xe8, 0xd5, 0xea, 0x91, 0x92, 0x12, 0x33, 0xb0, 0x33, 0x01, 0x98, 0x49, 0x56, 0x86, 0xed,
+ 0x3a, 0x94, 0x82, 0xef, 0x23, 0xfc, 0x23, 0x9b, 0xb8, 0x80, 0x83, 0x80, 0xd8, 0xbd, 0x0b, 0x6f,
+ 0x43, 0xee, 0x9c, 0x8e, 0x0c, 0x2b, 0x78, 0xf5, 0x14, 0x8d, 0xf0, 0x25, 0x37, 0x1b, 0xbd, 0xe4,
+ 0x1e, 0xfd, 0x21, 0x05, 0x5b, 0x9a, 0x3d, 0x99, 0xf7, 0xf7, 0x08, 0xcd, 0xbd, 0x02, 0x78, 0x9f,
+ 0xa4, 0xbe, 0xf8, 0x78, 0x64, 0xf8, 0xe3, 0xe9, 0x79, 0x4d, 0xb3, 0x27, 0xfb, 0x23, 0xdb, 0x24,
+ 0xd6, 0x68, 0xf6, 0x95, 0x90, 0xff, 0xd1, 0xde, 0x1d, 0x51, 0xeb, 0xdd, 0x91, 0x1d, 0xfb, 0x66,
+ 0xf8, 0xd1, 0xec, 0xef, 0xd7, 0xe9, 0xcc, 0x71, 0xef, 0xe8, 0xaf, 0xe9, 0x9d, 0x63, 0xd1, 0x57,
+ 0x2f, 0x8c, 0x8d, 0x42, 0x87, 0x26, 0xd5, 0xd8, 0x78, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x0c,
+ 0xab, 0xb6, 0x37, 0x7e, 0x1c, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto
new file mode 100644
index 0000000..4d4fb37
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto
@@ -0,0 +1,849 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// The messages in this file describe the definitions found in .proto files.
+// A valid .proto file can be translated directly to a FileDescriptorProto
+// without any other information (e.g. without reading its imports).
+
+
+syntax = "proto2";
+
+package google.protobuf;
+option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DescriptorProtos";
+option csharp_namespace = "Google.Protobuf.Reflection";
+option objc_class_prefix = "GPB";
+
+// descriptor.proto must be optimized for speed because reflection-based
+// algorithms don't work during bootstrapping.
+option optimize_for = SPEED;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+ repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+ optional string name = 1; // file name, relative to root of source tree
+ optional string package = 2; // e.g. "foo", "foo.bar", etc.
+
+ // Names of files imported by this file.
+ repeated string dependency = 3;
+ // Indexes of the public imported files in the dependency list above.
+ repeated int32 public_dependency = 10;
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ repeated int32 weak_dependency = 11;
+
+ // All top-level definitions in this file.
+ repeated DescriptorProto message_type = 4;
+ repeated EnumDescriptorProto enum_type = 5;
+ repeated ServiceDescriptorProto service = 6;
+ repeated FieldDescriptorProto extension = 7;
+
+ optional FileOptions options = 8;
+
+ // This field contains optional information about the original source code.
+ // You may safely remove this entire field without harming runtime
+ // functionality of the descriptors -- the information is needed only by
+ // development tools.
+ optional SourceCodeInfo source_code_info = 9;
+
+ // The syntax of the proto file.
+ // The supported values are "proto2" and "proto3".
+ optional string syntax = 12;
+}
+
+// Describes a message type.
+message DescriptorProto {
+ optional string name = 1;
+
+ repeated FieldDescriptorProto field = 2;
+ repeated FieldDescriptorProto extension = 6;
+
+ repeated DescriptorProto nested_type = 3;
+ repeated EnumDescriptorProto enum_type = 4;
+
+ message ExtensionRange {
+ optional int32 start = 1;
+ optional int32 end = 2;
+
+ optional ExtensionRangeOptions options = 3;
+ }
+ repeated ExtensionRange extension_range = 5;
+
+ repeated OneofDescriptorProto oneof_decl = 8;
+
+ optional MessageOptions options = 7;
+
+ // Range of reserved tag numbers. Reserved tag numbers may not be used by
+ // fields or extension ranges in the same message. Reserved ranges may
+ // not overlap.
+ message ReservedRange {
+ optional int32 start = 1; // Inclusive.
+ optional int32 end = 2; // Exclusive.
+ }
+ repeated ReservedRange reserved_range = 9;
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ repeated string reserved_name = 10;
+}
+
+message ExtensionRangeOptions {
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+ enum Type {
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ TYPE_DOUBLE = 1;
+ TYPE_FLOAT = 2;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ TYPE_INT64 = 3;
+ TYPE_UINT64 = 4;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ TYPE_INT32 = 5;
+ TYPE_FIXED64 = 6;
+ TYPE_FIXED32 = 7;
+ TYPE_BOOL = 8;
+ TYPE_STRING = 9;
+ // Tag-delimited aggregate.
+ // Group type is deprecated and not supported in proto3. However, Proto3
+ // implementations should still be able to parse the group wire format and
+ // treat group fields as unknown fields.
+ TYPE_GROUP = 10;
+ TYPE_MESSAGE = 11; // Length-delimited aggregate.
+
+ // New in version 2.
+ TYPE_BYTES = 12;
+ TYPE_UINT32 = 13;
+ TYPE_ENUM = 14;
+ TYPE_SFIXED32 = 15;
+ TYPE_SFIXED64 = 16;
+ TYPE_SINT32 = 17; // Uses ZigZag encoding.
+ TYPE_SINT64 = 18; // Uses ZigZag encoding.
+ };
+
+ enum Label {
+ // 0 is reserved for errors
+ LABEL_OPTIONAL = 1;
+ LABEL_REQUIRED = 2;
+ LABEL_REPEATED = 3;
+ };
+
+ optional string name = 1;
+ optional int32 number = 3;
+ optional Label label = 4;
+
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+ optional Type type = 5;
+
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ optional string type_name = 6;
+
+ // For extensions, this is the name of the type being extended. It is
+ // resolved in the same manner as type_name.
+ optional string extendee = 2;
+
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ optional string default_value = 7;
+
+ // If set, gives the index of a oneof in the containing type's oneof_decl
+ // list. This field is a member of that oneof.
+ optional int32 oneof_index = 9;
+
+ // JSON name of this field. The value is set by protocol compiler. If the
+ // user has set a "json_name" option on this field, that option's value
+ // will be used. Otherwise, it's deduced from the field's name by converting
+ // it to camelCase.
+ optional string json_name = 10;
+
+ optional FieldOptions options = 8;
+}
+
+// Describes a oneof.
+message OneofDescriptorProto {
+ optional string name = 1;
+ optional OneofOptions options = 2;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+ optional string name = 1;
+
+ repeated EnumValueDescriptorProto value = 2;
+
+ optional EnumOptions options = 3;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+ optional string name = 1;
+ optional int32 number = 2;
+
+ optional EnumValueOptions options = 3;
+}
+
+// Describes a service.
+message ServiceDescriptorProto {
+ optional string name = 1;
+ repeated MethodDescriptorProto method = 2;
+
+ optional ServiceOptions options = 3;
+}
+
+// Describes a method of a service.
+message MethodDescriptorProto {
+ optional string name = 1;
+
+ // Input and output type names. These are resolved in the same way as
+ // FieldDescriptorProto.type_name, but must refer to a message type.
+ optional string input_type = 2;
+ optional string output_type = 3;
+
+ optional MethodOptions options = 4;
+
+ // Identifies if client streams multiple client messages
+ optional bool client_streaming = 5 [default=false];
+ // Identifies if server streams multiple server messages
+ optional bool server_streaming = 6 [default=false];
+}
+
+
+// ===================================================================
+// Options
+
+// Each of the definitions above may have "options" attached. These are
+// just annotations which may cause code to be generated slightly differently
+// or may contain hints for code that manipulates protocol messages.
+//
+// Clients may define custom options as extensions of the *Options messages.
+// These extensions may not yet be known at parsing time, so the parser cannot
+// store the values in them. Instead it stores them in a field in the *Options
+// message called uninterpreted_option. This field must have the same name
+// across all *Options messages. We then use this field to populate the
+// extensions when we build a descriptor, at which point all protos have been
+// parsed and so all extensions are known.
+//
+// Extension numbers for custom options may be chosen as follows:
+// * For options which will only be used within a single application or
+// organization, or for experimental options, use field numbers 50000
+// through 99999. It is up to you to ensure that you do not use the
+// same number for multiple options.
+// * For options which will be published and used publicly by multiple
+// independent entities, e-mail protobuf-global-extension-registry@google.com
+// to reserve extension numbers. Simply provide your project name (e.g.
+// Objective-C plugin) and your project website (if available) -- there's no
+// need to explain how you intend to use them. Usually you only need one
+// extension number. You can declare multiple options with only one extension
+// number by putting them in a sub-message. See the Custom Options section of
+// the docs for examples:
+// https://developers.google.com/protocol-buffers/docs/proto#options
+// If this turns out to be popular, a web service will be set up
+// to automatically assign option numbers.
+
+
+message FileOptions {
+
+ // Sets the Java package where classes generated from this .proto will be
+ // placed. By default, the proto package is used, but this is often
+ // inappropriate because proto packages do not normally start with backwards
+ // domain names.
+ optional string java_package = 1;
+
+
+ // If set, all the classes from the .proto file are wrapped in a single
+ // outer class with the given name. This applies to both Proto1
+ // (equivalent to the old "--one_java_file" option) and Proto2 (where
+ // a .proto always translates to a single class, but you may want to
+ // explicitly choose the class name).
+ optional string java_outer_classname = 8;
+
+ // If set true, then the Java code generator will generate a separate .java
+ // file for each top-level message, enum, and service defined in the .proto
+ // file. Thus, these types will *not* be nested inside the outer class
+ // named by java_outer_classname. However, the outer class will still be
+ // generated to contain the file's getDescriptor() method as well as any
+ // top-level extensions defined in the file.
+ optional bool java_multiple_files = 10 [default=false];
+
+ // This option does nothing.
+ optional bool java_generate_equals_and_hash = 20 [deprecated=true];
+
+ // If set true, then the Java2 code generator will generate code that
+ // throws an exception whenever an attempt is made to assign a non-UTF-8
+ // byte sequence to a string field.
+ // Message reflection will do the same.
+ // However, an extension field still accepts non-UTF-8 byte sequences.
+ // This option has no effect on when used with the lite runtime.
+ optional bool java_string_check_utf8 = 27 [default=false];
+
+
+ // Generated classes can be optimized for speed or code size.
+ enum OptimizeMode {
+ SPEED = 1; // Generate complete code for parsing, serialization,
+ // etc.
+ CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
+ LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+ }
+ optional OptimizeMode optimize_for = 9 [default=SPEED];
+
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. If omitted, the Go package will be derived from the following:
+ // - The basename of the package import path, if provided.
+ // - Otherwise, the package statement in the .proto file, if present.
+ // - Otherwise, the basename of the .proto file, without extension.
+ optional string go_package = 11;
+
+
+
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of google.protobuf.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. Therefore,
+ // these default to false. Old code which depends on generic services should
+ // explicitly set them to true.
+ optional bool cc_generic_services = 16 [default=false];
+ optional bool java_generic_services = 17 [default=false];
+ optional bool py_generic_services = 18 [default=false];
+ optional bool php_generic_services = 42 [default=false];
+
+ // Is this file deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for everything in the file, or it will be completely ignored; in the very
+ // least, this is a formalization for deprecating files.
+ optional bool deprecated = 23 [default=false];
+
+ // Enables the use of arenas for the proto messages in this file. This applies
+ // only to generated classes for C++.
+ optional bool cc_enable_arenas = 31 [default=false];
+
+
+ // Sets the objective c class prefix which is prepended to all objective c
+ // generated classes from this .proto. There is no default.
+ optional string objc_class_prefix = 36;
+
+ // Namespace for generated classes; defaults to the package.
+ optional string csharp_namespace = 37;
+
+ // By default Swift generators will take the proto package and CamelCase it
+ // replacing '.' with underscore and use that to prefix the types/symbols
+ // defined. When this options is provided, they will use this value instead
+ // to prefix the types/symbols defined.
+ optional string swift_prefix = 39;
+
+ // Sets the php class prefix which is prepended to all php generated classes
+ // from this .proto. Default is empty.
+ optional string php_class_prefix = 40;
+
+ // Use this option to change the namespace of php generated classes. Default
+ // is empty. When this option is empty, the package name will be used for
+ // determining the namespace.
+ optional string php_namespace = 41;
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+
+ reserved 38;
+}
+
+message MessageOptions {
+ // Set true to use the old proto1 MessageSet wire format for extensions.
+ // This is provided for backwards-compatibility with the MessageSet wire
+ // format. You should not use this for any other reason: It's less
+ // efficient, has fewer features, and is more complicated.
+ //
+ // The message must be defined exactly as follows:
+ // message Foo {
+ // option message_set_wire_format = true;
+ // extensions 4 to max;
+ // }
+ // Note that the message cannot have any defined fields; MessageSets only
+ // have extensions.
+ //
+ // All extensions of your type must be singular messages; e.g. they cannot
+ // be int32s, enums, or repeated messages.
+ //
+ // Because this is an option, the above two restrictions are not enforced by
+ // the protocol compiler.
+ optional bool message_set_wire_format = 1 [default=false];
+
+ // Disables the generation of the standard "descriptor()" accessor, which can
+ // conflict with a field of the same name. This is meant to make migration
+ // from proto1 easier; new code should avoid fields named "descriptor".
+ optional bool no_standard_descriptor_accessor = 2 [default=false];
+
+ // Is this message deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the message, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating messages.
+ optional bool deprecated = 3 [default=false];
+
+ // Whether the message is an automatically generated map entry type for the
+ // maps field.
+ //
+ // For maps fields:
+ // map map_field = 1;
+ // The parsed descriptor looks like:
+ // message MapFieldEntry {
+ // option map_entry = true;
+ // optional KeyType key = 1;
+ // optional ValueType value = 2;
+ // }
+ // repeated MapFieldEntry map_field = 1;
+ //
+ // Implementations may choose not to generate the map_entry=true message, but
+ // use a native map in the target language to hold the keys and values.
+ // The reflection APIs in such implementions still need to work as
+ // if the field is a repeated message field.
+ //
+ // NOTE: Do not set the option in .proto files. Always use the maps syntax
+ // instead. The option should only be implicitly set by the proto compiler
+ // parser.
+ optional bool map_entry = 7;
+
+ reserved 8; // javalite_serializable
+ reserved 9; // javanano_as_lite
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message FieldOptions {
+ // The ctype option instructs the C++ code generator to use a different
+ // representation of the field than it normally would. See the specific
+ // options below. This option is not yet implemented in the open source
+ // release -- sorry, we'll try to include it in a future version!
+ optional CType ctype = 1 [default = STRING];
+ enum CType {
+ // Default mode.
+ STRING = 0;
+
+ CORD = 1;
+
+ STRING_PIECE = 2;
+ }
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob. In proto3, only explicit setting it to
+ // false will avoid using packed encoding.
+ optional bool packed = 2;
+
+ // The jstype option determines the JavaScript type used for values of the
+ // field. The option is permitted only for 64 bit integral and fixed types
+ // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
+ // is represented as JavaScript string, which avoids loss of precision that
+ // can happen when a large value is converted to a floating point JavaScript.
+ // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+ // use the JavaScript "number" type. The behavior of the default option
+ // JS_NORMAL is implementation dependent.
+ //
+ // This option is an enum to permit additional types to be added, e.g.
+ // goog.math.Integer.
+ optional JSType jstype = 6 [default = JS_NORMAL];
+ enum JSType {
+ // Use the default type.
+ JS_NORMAL = 0;
+
+ // Use JavaScript strings.
+ JS_STRING = 1;
+
+ // Use JavaScript numbers.
+ JS_NUMBER = 2;
+ }
+
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outer message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ optional bool lazy = 5 [default=false];
+
+ // Is this field deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for accessors, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating fields.
+ optional bool deprecated = 3 [default=false];
+
+ // For Google-internal migration only. Do not use.
+ optional bool weak = 10 [default=false];
+
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+
+ reserved 4; // removed jtype
+}
+
+message OneofOptions {
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumOptions {
+
+ // Set this option to true to allow mapping different tag names to the same
+ // value.
+ optional bool allow_alias = 2;
+
+ // Is this enum deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating enums.
+ optional bool deprecated = 3 [default=false];
+
+ reserved 5; // javanano_as_lite
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumValueOptions {
+ // Is this enum value deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the enum value, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating enum values.
+ optional bool deprecated = 1 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message ServiceOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // Is this service deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the service, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating services.
+ optional bool deprecated = 33 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message MethodOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // Is this method deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for the method, or it will be completely ignored; in the very least,
+ // this is a formalization for deprecating methods.
+ optional bool deprecated = 33 [default=false];
+
+ // Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+ // or neither? HTTP based RPC implementation may choose GET verb for safe
+ // methods, and PUT verb for idempotent methods instead of the default POST.
+ enum IdempotencyLevel {
+ IDEMPOTENCY_UNKNOWN = 0;
+ NO_SIDE_EFFECTS = 1; // implies idempotent
+ IDEMPOTENT = 2; // idempotent, but may have side effects
+ }
+ optional IdempotencyLevel idempotency_level =
+ 34 [default=IDEMPOTENCY_UNKNOWN];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+message UninterpretedOption {
+ // The name of the uninterpreted option. Each string represents a segment in
+ // a dot-separated name. is_extension is true iff a segment represents an
+ // extension (denoted with parentheses in options specs in .proto files).
+ // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+ // "foo.(bar.baz).qux".
+ message NamePart {
+ required string name_part = 1;
+ required bool is_extension = 2;
+ }
+ repeated NamePart name = 2;
+
+ // The value of the uninterpreted option, in whatever type the tokenizer
+ // identified it as during parsing. Exactly one of these should be set.
+ optional string identifier_value = 3;
+ optional uint64 positive_int_value = 4;
+ optional int64 negative_int_value = 5;
+ optional double double_value = 6;
+ optional bytes string_value = 7;
+ optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+ // A Location identifies a piece of source code in a .proto file which
+ // corresponds to a particular definition. This information is intended
+ // to be useful to IDEs, code indexers, documentation generators, and similar
+ // tools.
+ //
+ // For example, say we have a file like:
+ // message Foo {
+ // optional string foo = 1;
+ // }
+ // Let's look at just the field definition:
+ // optional string foo = 1;
+ // ^ ^^ ^^ ^ ^^^
+ // a bc de f ghi
+ // We have the following locations:
+ // span path represents
+ // [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ //
+ // Notes:
+ // - A location may refer to a repeated field itself (i.e. not to any
+ // particular index within it). This is used whenever a set of elements are
+ // logically enclosed in a single code segment. For example, an entire
+ // extend block (possibly containing multiple extension definitions) will
+ // have an outer location whose path refers to the "extensions" repeated
+ // field without an index.
+ // - Multiple locations may have the same path. This happens when a single
+ // logical declaration is spread out across multiple places. The most
+ // obvious example is the "extend" block again -- there may be multiple
+ // extend blocks in the same scope, each of which will have the same path.
+ // - A location's span is not always a subset of its parent's span. For
+ // example, the "extendee" of an extension declaration appears at the
+ // beginning of the "extend" block and is shared by all extensions within
+ // the block.
+ // - Just because a location's span is a subset of some other location's span
+ // does not mean that it is a descendent. For example, a "group" defines
+ // both a type and a field in a single declaration. Thus, the locations
+ // corresponding to the type and field and their components will overlap.
+ // - Code which tries to interpret locations should probably be designed to
+ // ignore those that it doesn't understand, as more types of locations could
+ // be recorded in the future.
+ repeated Location location = 1;
+ message Location {
+ // Identifies which part of the FileDescriptorProto was defined at this
+ // location.
+ //
+ // Each element is a field number or an index. They form a path from
+ // the root FileDescriptorProto to the place where the definition. For
+ // example, this path:
+ // [ 4, 3, 2, 7, 1 ]
+ // refers to:
+ // file.message_type(3) // 4, 3
+ // .field(7) // 2, 7
+ // .name() // 1
+ // This is because FileDescriptorProto.message_type has field number 4:
+ // repeated DescriptorProto message_type = 4;
+ // and DescriptorProto.field has field number 2:
+ // repeated FieldDescriptorProto field = 2;
+ // and FieldDescriptorProto.name has field number 1:
+ // optional string name = 1;
+ //
+ // Thus, the above path gives the location of a field name. If we removed
+ // the last element:
+ // [ 4, 3, 2, 7 ]
+ // this path refers to the whole field declaration (from the beginning
+ // of the label to the terminating semicolon).
+ repeated int32 path = 1 [packed=true];
+
+ // Always has exactly three or four elements: start line, start column,
+ // end line (optional, otherwise assumed same as start line), end column.
+ // These are packed into a single field for efficiency. Note that line
+ // and column numbers are zero-based -- typically you will want to add
+ // 1 to each before displaying to a user.
+ repeated int32 span = 2 [packed=true];
+
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // leading_detached_comments will keep paragraphs of comments that appear
+ // before (but not connected to) the current element. Each paragraph,
+ // separated by empty lines, will be one comment element in the repeated
+ // field.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // // Detached comment for corge. This is not leading or trailing comments
+ // // to qux or corge because there are blank lines separating it from
+ // // both.
+ //
+ // // Detached comment for corge paragraph 2.
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ //
+ // // ignored detached comments.
+ optional string leading_comments = 3;
+ optional string trailing_comments = 4;
+ repeated string leading_detached_comments = 6;
+ }
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+message GeneratedCodeInfo {
+ // An Annotation connects some span of text in generated code to an element
+ // of its generating .proto file.
+ repeated Annotation annotation = 1;
+ message Annotation {
+ // Identifies the element in the original source .proto file. This field
+ // is formatted the same as SourceCodeInfo.Location.path.
+ repeated int32 path = 1 [packed=true];
+
+ // Identifies the filesystem path to the original source .proto.
+ optional string source_file = 2;
+
+ // Identifies the starting offset in bytes in the generated code
+ // that relates to the identified object.
+ optional int32 begin = 3;
+
+ // Identifies the ending offset in bytes in the generated code that
+ // relates to the identified offset. The end offset should be one past
+ // the last relevant byte (so the length of the text = end - begin).
+ optional int32 end = 4;
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/any.go b/vendor/github.com/golang/protobuf/ptypes/any.go
new file mode 100644
index 0000000..b2af97f
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/any.go
@@ -0,0 +1,139 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package ptypes
+
+// This file implements functions to marshal proto.Message to/from
+// google.protobuf.Any message.
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes/any"
+)
+
+const googleApis = "type.googleapis.com/"
+
+// AnyMessageName returns the name of the message contained in a google.protobuf.Any message.
+//
+// Note that regular type assertions should be done using the Is
+// function. AnyMessageName is provided for less common use cases like filtering a
+// sequence of Any messages based on a set of allowed message type names.
+func AnyMessageName(any *any.Any) (string, error) {
+ if any == nil {
+ return "", fmt.Errorf("message is nil")
+ }
+ slash := strings.LastIndex(any.TypeUrl, "/")
+ if slash < 0 {
+ return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
+ }
+ return any.TypeUrl[slash+1:], nil
+}
+
+// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any.
+func MarshalAny(pb proto.Message) (*any.Any, error) {
+ value, err := proto.Marshal(pb)
+ if err != nil {
+ return nil, err
+ }
+ return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil
+}
+
+// DynamicAny is a value that can be passed to UnmarshalAny to automatically
+// allocate a proto.Message for the type specified in a google.protobuf.Any
+// message. The allocated message is stored in the embedded proto.Message.
+//
+// Example:
+//
+// var x ptypes.DynamicAny
+// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
+// fmt.Printf("unmarshaled message: %v", x.Message)
+type DynamicAny struct {
+ proto.Message
+}
+
+// Empty returns a new proto.Message of the type specified in a
+// google.protobuf.Any message. It returns an error if corresponding message
+// type isn't linked in.
+func Empty(any *any.Any) (proto.Message, error) {
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return nil, err
+ }
+
+ t := proto.MessageType(aname)
+ if t == nil {
+ return nil, fmt.Errorf("any: message type %q isn't linked in", aname)
+ }
+ return reflect.New(t.Elem()).Interface().(proto.Message), nil
+}
+
+// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any
+// message and places the decoded result in pb. It returns an error if type of
+// contents of Any message does not match type of pb message.
+//
+// pb can be a proto.Message, or a *DynamicAny.
+func UnmarshalAny(any *any.Any, pb proto.Message) error {
+ if d, ok := pb.(*DynamicAny); ok {
+ if d.Message == nil {
+ var err error
+ d.Message, err = Empty(any)
+ if err != nil {
+ return err
+ }
+ }
+ return UnmarshalAny(any, d.Message)
+ }
+
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return err
+ }
+
+ mname := proto.MessageName(pb)
+ if aname != mname {
+ return fmt.Errorf("mismatched message type: got %q want %q", aname, mname)
+ }
+ return proto.Unmarshal(any.Value, pb)
+}
+
+// Is returns true if any value contains a given message type.
+func Is(any *any.Any, pb proto.Message) bool {
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return false
+ }
+
+ return aname == proto.MessageName(pb)
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
new file mode 100644
index 0000000..f346017
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
@@ -0,0 +1,178 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/any.proto
+
+/*
+Package any is a generated protocol buffer package.
+
+It is generated from these files:
+ google/protobuf/any.proto
+
+It has these top-level messages:
+ Any
+*/
+package any
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// Example 3: Pack and unpack a message in Python.
+//
+// foo = Foo(...)
+// any = Any()
+// any.Pack(foo)
+// ...
+// if any.Is(Foo.DESCRIPTOR):
+// any.Unpack(foo)
+// ...
+//
+// Example 4: Pack and unpack a message in Go
+//
+// foo := &pb.Foo{...}
+// any, err := ptypes.MarshalAny(foo)
+// ...
+// foo := &pb.Foo{}
+// if err := ptypes.UnmarshalAny(any, foo); err != nil {
+// ...
+// }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": ,
+// "lastName":
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+type Any struct {
+ // A URL/resource name whose content describes the type of the
+ // serialized protocol buffer message.
+ //
+ // For URLs which use the scheme `http`, `https`, or no scheme, the
+ // following restrictions and interpretations apply:
+ //
+ // * If no scheme is provided, `https` is assumed.
+ // * The last segment of the URL's path must represent the fully
+ // qualified name of the type (as in `path/google.protobuf.Duration`).
+ // The name should be in a canonical form (e.g., leading "." is
+ // not accepted).
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Schemes other than `http`, `https` (or the empty scheme) might be
+ // used with implementation specific semantics.
+ //
+ TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"`
+ // Must be a valid serialized protocol buffer of the above specified type.
+ Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+}
+
+func (m *Any) Reset() { *m = Any{} }
+func (m *Any) String() string { return proto.CompactTextString(m) }
+func (*Any) ProtoMessage() {}
+func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+func (*Any) XXX_WellKnownType() string { return "Any" }
+
+func (m *Any) GetTypeUrl() string {
+ if m != nil {
+ return m.TypeUrl
+ }
+ return ""
+}
+
+func (m *Any) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Any)(nil), "google.protobuf.Any")
+}
+
+func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 185 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
+ 0x03, 0x73, 0x84, 0xf8, 0x21, 0x52, 0x7a, 0x30, 0x29, 0x25, 0x33, 0x2e, 0x66, 0xc7, 0xbc, 0x4a,
+ 0x21, 0x49, 0x2e, 0x8e, 0x92, 0xca, 0x82, 0xd4, 0xf8, 0xd2, 0xa2, 0x1c, 0x09, 0x46, 0x05, 0x46,
+ 0x0d, 0xce, 0x20, 0x76, 0x10, 0x3f, 0xb4, 0x28, 0x47, 0x48, 0x84, 0x8b, 0xb5, 0x2c, 0x31, 0xa7,
+ 0x34, 0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xc2, 0x71, 0xca, 0xe7, 0x12, 0x4e, 0xce,
+ 0xcf, 0xd5, 0x43, 0x33, 0xce, 0x89, 0xc3, 0x31, 0xaf, 0x32, 0x00, 0xc4, 0x09, 0x60, 0x8c, 0x52,
+ 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc,
+ 0x4b, 0x47, 0xb8, 0xa8, 0x00, 0x64, 0x7a, 0x31, 0xc8, 0x61, 0x8b, 0x98, 0x98, 0xdd, 0x03, 0x9c,
+ 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x8c, 0x0a, 0x80, 0x2a, 0xd1, 0x0b, 0x4f, 0xcd, 0xc9, 0xf1, 0xce,
+ 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0x29, 0x4d, 0x62, 0x03, 0xeb, 0x35, 0x06, 0x04, 0x00, 0x00, 0xff,
+ 0xff, 0x13, 0xf8, 0xe8, 0x42, 0xdd, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.proto b/vendor/github.com/golang/protobuf/ptypes/any/any.proto
new file mode 100644
index 0000000..c748667
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/any/any.proto
@@ -0,0 +1,149 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/any";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "AnyProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// Example 3: Pack and unpack a message in Python.
+//
+// foo = Foo(...)
+// any = Any()
+// any.Pack(foo)
+// ...
+// if any.Is(Foo.DESCRIPTOR):
+// any.Unpack(foo)
+// ...
+//
+// Example 4: Pack and unpack a message in Go
+//
+// foo := &pb.Foo{...}
+// any, err := ptypes.MarshalAny(foo)
+// ...
+// foo := &pb.Foo{}
+// if err := ptypes.UnmarshalAny(any, foo); err != nil {
+// ...
+// }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": ,
+// "lastName":
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+message Any {
+ // A URL/resource name whose content describes the type of the
+ // serialized protocol buffer message.
+ //
+ // For URLs which use the scheme `http`, `https`, or no scheme, the
+ // following restrictions and interpretations apply:
+ //
+ // * If no scheme is provided, `https` is assumed.
+ // * The last segment of the URL's path must represent the fully
+ // qualified name of the type (as in `path/google.protobuf.Duration`).
+ // The name should be in a canonical form (e.g., leading "." is
+ // not accepted).
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Schemes other than `http`, `https` (or the empty scheme) might be
+ // used with implementation specific semantics.
+ //
+ string type_url = 1;
+
+ // Must be a valid serialized protocol buffer of the above specified type.
+ bytes value = 2;
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/doc.go b/vendor/github.com/golang/protobuf/ptypes/doc.go
new file mode 100644
index 0000000..c0d595d
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/doc.go
@@ -0,0 +1,35 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package ptypes contains code for interacting with well-known types.
+*/
+package ptypes
diff --git a/vendor/github.com/golang/protobuf/ptypes/duration.go b/vendor/github.com/golang/protobuf/ptypes/duration.go
new file mode 100644
index 0000000..65cb0f8
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/duration.go
@@ -0,0 +1,102 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package ptypes
+
+// This file implements conversions between google.protobuf.Duration
+// and time.Duration.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ durpb "github.com/golang/protobuf/ptypes/duration"
+)
+
+const (
+ // Range of a durpb.Duration in seconds, as specified in
+ // google/protobuf/duration.proto. This is about 10,000 years in seconds.
+ maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
+ minSeconds = -maxSeconds
+)
+
+// validateDuration determines whether the durpb.Duration is valid according to the
+// definition in google/protobuf/duration.proto. A valid durpb.Duration
+// may still be too large to fit into a time.Duration (the range of durpb.Duration
+// is about 10,000 years, and the range of time.Duration is about 290).
+func validateDuration(d *durpb.Duration) error {
+ if d == nil {
+ return errors.New("duration: nil Duration")
+ }
+ if d.Seconds < minSeconds || d.Seconds > maxSeconds {
+ return fmt.Errorf("duration: %v: seconds out of range", d)
+ }
+ if d.Nanos <= -1e9 || d.Nanos >= 1e9 {
+ return fmt.Errorf("duration: %v: nanos out of range", d)
+ }
+ // Seconds and Nanos must have the same sign, unless d.Nanos is zero.
+ if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) {
+ return fmt.Errorf("duration: %v: seconds and nanos have different signs", d)
+ }
+ return nil
+}
+
+// Duration converts a durpb.Duration to a time.Duration. Duration
+// returns an error if the durpb.Duration is invalid or is too large to be
+// represented in a time.Duration.
+func Duration(p *durpb.Duration) (time.Duration, error) {
+ if err := validateDuration(p); err != nil {
+ return 0, err
+ }
+ d := time.Duration(p.Seconds) * time.Second
+ if int64(d/time.Second) != p.Seconds {
+ return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
+ }
+ if p.Nanos != 0 {
+ d += time.Duration(p.Nanos)
+ if (d < 0) != (p.Nanos < 0) {
+ return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
+ }
+ }
+ return d, nil
+}
+
+// DurationProto converts a time.Duration to a durpb.Duration.
+func DurationProto(d time.Duration) *durpb.Duration {
+ nanos := d.Nanoseconds()
+ secs := nanos / 1e9
+ nanos -= secs * 1e9
+ return &durpb.Duration{
+ Seconds: secs,
+ Nanos: int32(nanos),
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
new file mode 100644
index 0000000..b2410a0
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
@@ -0,0 +1,144 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/duration.proto
+
+/*
+Package duration is a generated protocol buffer package.
+
+It is generated from these files:
+ google/protobuf/duration.proto
+
+It has these top-level messages:
+ Duration
+*/
+package duration
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// # Examples
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+// Example 3: Compute Duration from datetime.timedelta in Python.
+//
+// td = datetime.timedelta(days=3, minutes=10)
+// duration = Duration()
+// duration.FromTimedelta(td)
+//
+// # JSON Mapping
+//
+// In JSON format, the Duration type is encoded as a string rather than an
+// object, where the string ends in the suffix "s" (indicating seconds) and
+// is preceded by the number of seconds, with nanoseconds expressed as
+// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
+// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
+// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
+// microsecond should be expressed in JSON format as "3.000001s".
+//
+//
+type Duration struct {
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive. Note: these bounds are computed from:
+ // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
+}
+
+func (m *Duration) Reset() { *m = Duration{} }
+func (m *Duration) String() string { return proto.CompactTextString(m) }
+func (*Duration) ProtoMessage() {}
+func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+func (*Duration) XXX_WellKnownType() string { return "Duration" }
+
+func (m *Duration) GetSeconds() int64 {
+ if m != nil {
+ return m.Seconds
+ }
+ return 0
+}
+
+func (m *Duration) GetNanos() int32 {
+ if m != nil {
+ return m.Nanos
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
+}
+
+func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 190 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
+ 0x2c, 0xc9, 0xcc, 0xcf, 0xd3, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0x56,
+ 0x5c, 0x1c, 0x2e, 0x50, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0xc9, 0xf9, 0x79, 0x29, 0xc5,
+ 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, 0x5e, 0x62, 0x5e,
+ 0x7e, 0xb1, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0x84, 0xe3, 0x54, 0xc3, 0x25, 0x9c, 0x9c,
+ 0x9f, 0xab, 0x87, 0x66, 0xa4, 0x13, 0x2f, 0xcc, 0xc0, 0x00, 0x90, 0x48, 0x00, 0x63, 0x94, 0x56,
+ 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62, 0x5e,
+ 0x3a, 0xc2, 0x7d, 0x05, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x70, 0x67, 0xfe, 0x60, 0x64, 0x5c, 0xc4,
+ 0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0x62, 0x6e, 0x00, 0x54, 0xa9, 0x5e, 0x78,
+ 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x4b, 0x12, 0x1b, 0xd8, 0x0c, 0x63,
+ 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x84, 0x30, 0xff, 0xf3, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
new file mode 100644
index 0000000..975fce4
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
@@ -0,0 +1,117 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/duration";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DurationProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// # Examples
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+// Example 3: Compute Duration from datetime.timedelta in Python.
+//
+// td = datetime.timedelta(days=3, minutes=10)
+// duration = Duration()
+// duration.FromTimedelta(td)
+//
+// # JSON Mapping
+//
+// In JSON format, the Duration type is encoded as a string rather than an
+// object, where the string ends in the suffix "s" (indicating seconds) and
+// is preceded by the number of seconds, with nanoseconds expressed as
+// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
+// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
+// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
+// microsecond should be expressed in JSON format as "3.000001s".
+//
+//
+message Duration {
+
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive. Note: these bounds are computed from:
+ // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+ int64 seconds = 1;
+
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ int32 nanos = 2;
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/regen.sh b/vendor/github.com/golang/protobuf/ptypes/regen.sh
new file mode 100755
index 0000000..b50a941
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/regen.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -e
+#
+# This script fetches and rebuilds the "well-known types" protocol buffers.
+# To run this you will need protoc and goprotobuf installed;
+# see https://github.com/golang/protobuf for instructions.
+# You also need Go and Git installed.
+
+PKG=github.com/golang/protobuf/ptypes
+UPSTREAM=https://github.com/google/protobuf
+UPSTREAM_SUBDIR=src/google/protobuf
+PROTO_FILES=(any duration empty struct timestamp wrappers)
+
+function die() {
+ echo 1>&2 $*
+ exit 1
+}
+
+# Sanity check that the right tools are accessible.
+for tool in go git protoc protoc-gen-go; do
+ q=$(which $tool) || die "didn't find $tool"
+ echo 1>&2 "$tool: $q"
+done
+
+tmpdir=$(mktemp -d -t regen-wkt.XXXXXX)
+trap 'rm -rf $tmpdir' EXIT
+
+echo -n 1>&2 "finding package dir... "
+pkgdir=$(go list -f '{{.Dir}}' $PKG)
+echo 1>&2 $pkgdir
+base=$(echo $pkgdir | sed "s,/$PKG\$,,")
+echo 1>&2 "base: $base"
+cd "$base"
+
+echo 1>&2 "fetching latest protos... "
+git clone -q $UPSTREAM $tmpdir
+
+for file in ${PROTO_FILES[@]}; do
+ echo 1>&2 "* $file"
+ protoc --go_out=. -I$tmpdir/src $tmpdir/src/google/protobuf/$file.proto || die
+ cp $tmpdir/src/google/protobuf/$file.proto $PKG/$file
+done
+
+echo 1>&2 "All OK"
diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp.go b/vendor/github.com/golang/protobuf/ptypes/timestamp.go
new file mode 100644
index 0000000..47f10db
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/timestamp.go
@@ -0,0 +1,134 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package ptypes
+
+// This file implements operations on google.protobuf.Timestamp.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ tspb "github.com/golang/protobuf/ptypes/timestamp"
+)
+
+const (
+ // Seconds field of the earliest valid Timestamp.
+ // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ minValidSeconds = -62135596800
+ // Seconds field just after the latest valid Timestamp.
+ // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ maxValidSeconds = 253402300800
+)
+
+// validateTimestamp determines whether a Timestamp is valid.
+// A valid timestamp represents a time in the range
+// [0001-01-01, 10000-01-01) and has a Nanos field
+// in the range [0, 1e9).
+//
+// If the Timestamp is valid, validateTimestamp returns nil.
+// Otherwise, it returns an error that describes
+// the problem.
+//
+// Every valid Timestamp can be represented by a time.Time, but the converse is not true.
+func validateTimestamp(ts *tspb.Timestamp) error {
+ if ts == nil {
+ return errors.New("timestamp: nil Timestamp")
+ }
+ if ts.Seconds < minValidSeconds {
+ return fmt.Errorf("timestamp: %v before 0001-01-01", ts)
+ }
+ if ts.Seconds >= maxValidSeconds {
+ return fmt.Errorf("timestamp: %v after 10000-01-01", ts)
+ }
+ if ts.Nanos < 0 || ts.Nanos >= 1e9 {
+ return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts)
+ }
+ return nil
+}
+
+// Timestamp converts a google.protobuf.Timestamp proto to a time.Time.
+// It returns an error if the argument is invalid.
+//
+// Unlike most Go functions, if Timestamp returns an error, the first return value
+// is not the zero time.Time. Instead, it is the value obtained from the
+// time.Unix function when passed the contents of the Timestamp, in the UTC
+// locale. This may or may not be a meaningful time; many invalid Timestamps
+// do map to valid time.Times.
+//
+// A nil Timestamp returns an error. The first return value in that case is
+// undefined.
+func Timestamp(ts *tspb.Timestamp) (time.Time, error) {
+ // Don't return the zero value on error, because corresponds to a valid
+ // timestamp. Instead return whatever time.Unix gives us.
+ var t time.Time
+ if ts == nil {
+ t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
+ } else {
+ t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
+ }
+ return t, validateTimestamp(ts)
+}
+
+// TimestampNow returns a google.protobuf.Timestamp for the current time.
+func TimestampNow() *tspb.Timestamp {
+ ts, err := TimestampProto(time.Now())
+ if err != nil {
+ panic("ptypes: time.Now() out of Timestamp range")
+ }
+ return ts
+}
+
+// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
+// It returns an error if the resulting Timestamp is invalid.
+func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
+ seconds := t.Unix()
+ nanos := int32(t.Sub(time.Unix(seconds, 0)))
+ ts := &tspb.Timestamp{
+ Seconds: seconds,
+ Nanos: nanos,
+ }
+ if err := validateTimestamp(ts); err != nil {
+ return nil, err
+ }
+ return ts, nil
+}
+
+// TimestampString returns the RFC 3339 string for valid Timestamps. For invalid
+// Timestamps, it returns an error message in parentheses.
+func TimestampString(ts *tspb.Timestamp) string {
+ t, err := Timestamp(ts)
+ if err != nil {
+ return fmt.Sprintf("(%v)", err)
+ }
+ return t.Format(time.RFC3339Nano)
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
new file mode 100644
index 0000000..e23e4a2
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
@@ -0,0 +1,160 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/timestamp.proto
+
+/*
+Package timestamp is a generated protocol buffer package.
+
+It is generated from these files:
+ google/protobuf/timestamp.proto
+
+It has these top-level messages:
+ Timestamp
+*/
+package timestamp
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// # Examples
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+//
+// Example 5: Compute Timestamp from current time in Python.
+//
+// timestamp = Timestamp()
+// timestamp.GetCurrentTime()
+//
+// # JSON Mapping
+//
+// In JSON format, the Timestamp type is encoded as a string in the
+// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+// where {year} is always expressed using four digits while {month}, {day},
+// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+// is required, though only UTC (as indicated by "Z") is presently supported.
+//
+// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+// 01:30 UTC on January 15, 2017.
+//
+// In JavaScript, one can convert a Date object to this format using the
+// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
+// method. In Python, a standard `datetime.datetime` object can be converted
+// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
+// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
+// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
+// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
+// to obtain a formatter capable of generating timestamps in this format.
+//
+//
+type Timestamp struct {
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
+}
+
+func (m *Timestamp) Reset() { *m = Timestamp{} }
+func (m *Timestamp) String() string { return proto.CompactTextString(m) }
+func (*Timestamp) ProtoMessage() {}
+func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
+
+func (m *Timestamp) GetSeconds() int64 {
+ if m != nil {
+ return m.Seconds
+ }
+ return 0
+}
+
+func (m *Timestamp) GetNanos() int32 {
+ if m != nil {
+ return m.Nanos
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
+}
+
+func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 191 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
+ 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0xd0, 0x03, 0x0b, 0x09, 0xf1, 0x43, 0x14, 0xe8, 0xc1, 0x14, 0x28,
+ 0x59, 0x73, 0x71, 0x86, 0xc0, 0xd4, 0x08, 0x49, 0x70, 0xb1, 0x17, 0xa7, 0x26, 0xe7, 0xe7, 0xa5,
+ 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0xc1, 0xb8, 0x42, 0x22, 0x5c, 0xac, 0x79, 0x89,
+ 0x79, 0xf9, 0xc5, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xac, 0x41, 0x10, 0x8e, 0x53, 0x1d, 0x97, 0x70,
+ 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0x99, 0x4e, 0x7c, 0x70, 0x13, 0x03, 0x40, 0x42, 0x01, 0x8c, 0x51,
+ 0xda, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xe9, 0xf9, 0x39, 0x89,
+ 0x79, 0xe9, 0x08, 0x27, 0x16, 0x94, 0x54, 0x16, 0xa4, 0x16, 0x23, 0x5c, 0xfa, 0x83, 0x91, 0x71,
+ 0x11, 0x13, 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xc9, 0x01, 0x50, 0xb5, 0x7a,
+ 0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x3d, 0x49, 0x6c, 0x60, 0x43,
+ 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x77, 0x4a, 0x07, 0xf7, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
new file mode 100644
index 0000000..b7cbd17
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
@@ -0,0 +1,133 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/timestamp";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TimestampProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// # Examples
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+//
+// Example 5: Compute Timestamp from current time in Python.
+//
+// timestamp = Timestamp()
+// timestamp.GetCurrentTime()
+//
+// # JSON Mapping
+//
+// In JSON format, the Timestamp type is encoded as a string in the
+// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+// where {year} is always expressed using four digits while {month}, {day},
+// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+// is required, though only UTC (as indicated by "Z") is presently supported.
+//
+// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+// 01:30 UTC on January 15, 2017.
+//
+// In JavaScript, one can convert a Date object to this format using the
+// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
+// method. In Python, a standard `datetime.datetime` object can be converted
+// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
+// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
+// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
+// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
+// to obtain a formatter capable of generating timestamps in this format.
+//
+//
+message Timestamp {
+
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ int64 seconds = 1;
+
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ int32 nanos = 2;
+}
diff --git a/vendor/github.com/googleapis/gax-go/CONTRIBUTING.md b/vendor/github.com/googleapis/gax-go/CONTRIBUTING.md
new file mode 100644
index 0000000..2827b7d
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/CONTRIBUTING.md
@@ -0,0 +1,27 @@
+Want to contribute? Great! First, read this page (including the small print at the end).
+
+### Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement]
+(https://cla.developers.google.com/about/google-individual)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first through the issue tracker with your idea so that we can help out and
+possibly guide you. Coordinating up front makes it much easier to avoid
+frustration later on.
+
+### Code reviews
+All submissions, including submissions by project members, require review. We
+use Github pull requests for this purpose.
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the
+[Software Grant and Corporate Contributor License Agreement]
+(https://cla.developers.google.com/about/google-corporate).
diff --git a/vendor/github.com/googleapis/gax-go/LICENSE b/vendor/github.com/googleapis/gax-go/LICENSE
new file mode 100644
index 0000000..6d16b65
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2016, Google Inc.
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/googleapis/gax-go/README.md b/vendor/github.com/googleapis/gax-go/README.md
new file mode 100644
index 0000000..3cedd5b
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/README.md
@@ -0,0 +1,24 @@
+Google API Extensions for Go
+============================
+
+[![Build Status](https://travis-ci.org/googleapis/gax-go.svg?branch=master)](https://travis-ci.org/googleapis/gax-go)
+[![Code Coverage](https://img.shields.io/codecov/c/github/googleapis/gax-go.svg)](https://codecov.io/github/googleapis/gax-go)
+
+Google API Extensions for Go (gax-go) is a set of modules which aids the
+development of APIs for clients and servers based on `gRPC` and Google API
+conventions.
+
+Application code will rarely need to use this library directly,
+but the code generated automatically from API definition files can use it
+to simplify code generation and to provide more convenient and idiomatic API surface.
+
+**This project is currently experimental and not supported.**
+
+Go Versions
+===========
+This library requires Go 1.6 or above.
+
+License
+=======
+BSD - please see [LICENSE](https://github.com/googleapis/gax-go/blob/master/LICENSE)
+for more information.
diff --git a/vendor/github.com/googleapis/gax-go/call_option.go b/vendor/github.com/googleapis/gax-go/call_option.go
new file mode 100644
index 0000000..7b62164
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/call_option.go
@@ -0,0 +1,157 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import (
+ "math/rand"
+ "time"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+// CallOption is an option used by Invoke to control behaviors of RPC calls.
+// CallOption works by modifying relevant fields of CallSettings.
+type CallOption interface {
+ // Resolve applies the option by modifying cs.
+ Resolve(cs *CallSettings)
+}
+
+// Retryer is used by Invoke to determine retry behavior.
+type Retryer interface {
+ // Retry reports whether a request should be retriedand how long to pause before retrying
+ // if the previous attempt returned with err. Invoke never calls Retry with nil error.
+ Retry(err error) (pause time.Duration, shouldRetry bool)
+}
+
+type retryerOption func() Retryer
+
+func (o retryerOption) Resolve(s *CallSettings) {
+ s.Retry = o
+}
+
+// WithRetry sets CallSettings.Retry to fn.
+func WithRetry(fn func() Retryer) CallOption {
+ return retryerOption(fn)
+}
+
+// OnCodes returns a Retryer that retries if and only if
+// the previous attempt returns a GRPC error whose error code is stored in cc.
+// Pause times between retries are specified by bo.
+//
+// bo is only used for its parameters; each Retryer has its own copy.
+func OnCodes(cc []codes.Code, bo Backoff) Retryer {
+ return &boRetryer{
+ backoff: bo,
+ codes: append([]codes.Code(nil), cc...),
+ }
+}
+
+type boRetryer struct {
+ backoff Backoff
+ codes []codes.Code
+}
+
+func (r *boRetryer) Retry(err error) (time.Duration, bool) {
+ st, ok := status.FromError(err)
+ if !ok {
+ return 0, false
+ }
+ c := st.Code()
+ for _, rc := range r.codes {
+ if c == rc {
+ return r.backoff.Pause(), true
+ }
+ }
+ return 0, false
+}
+
+// Backoff implements exponential backoff.
+// The wait time between retries is a random value between 0 and the "retry envelope".
+// The envelope starts at Initial and increases by the factor of Multiplier every retry,
+// but is capped at Max.
+type Backoff struct {
+ // Initial is the initial value of the retry envelope, defaults to 1 second.
+ Initial time.Duration
+
+ // Max is the maximum value of the retry envelope, defaults to 30 seconds.
+ Max time.Duration
+
+ // Multiplier is the factor by which the retry envelope increases.
+ // It should be greater than 1 and defaults to 2.
+ Multiplier float64
+
+ // cur is the current retry envelope
+ cur time.Duration
+}
+
+func (bo *Backoff) Pause() time.Duration {
+ if bo.Initial == 0 {
+ bo.Initial = time.Second
+ }
+ if bo.cur == 0 {
+ bo.cur = bo.Initial
+ }
+ if bo.Max == 0 {
+ bo.Max = 30 * time.Second
+ }
+ if bo.Multiplier < 1 {
+ bo.Multiplier = 2
+ }
+ // Select a duration between zero and the current max. It might seem counterintuitive to
+ // have so much jitter, but https://www.awsarchitectureblog.com/2015/03/backoff.html
+ // argues that that is the best strategy.
+ d := time.Duration(rand.Int63n(int64(bo.cur)))
+ bo.cur = time.Duration(float64(bo.cur) * bo.Multiplier)
+ if bo.cur > bo.Max {
+ bo.cur = bo.Max
+ }
+ return d
+}
+
+type grpcOpt []grpc.CallOption
+
+func (o grpcOpt) Resolve(s *CallSettings) {
+ s.GRPC = o
+}
+
+func WithGRPCOptions(opt ...grpc.CallOption) CallOption {
+ return grpcOpt(append([]grpc.CallOption(nil), opt...))
+}
+
+type CallSettings struct {
+ // Retry returns a Retryer to be used to control retry logic of a method call.
+ // If Retry is nil or the returned Retryer is nil, the call will not be retried.
+ Retry func() Retryer
+
+ // CallOptions to be forwarded to GRPC.
+ GRPC []grpc.CallOption
+}
diff --git a/vendor/github.com/googleapis/gax-go/gax.go b/vendor/github.com/googleapis/gax-go/gax.go
new file mode 100644
index 0000000..5ebedff
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/gax.go
@@ -0,0 +1,40 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Package gax contains a set of modules which aid the development of APIs
+// for clients and servers based on gRPC and Google API conventions.
+//
+// Application code will rarely need to use this library directly.
+// However, code generated automatically from API definition files can use it
+// to simplify code generation and to provide more convenient and idiomatic API surfaces.
+//
+// This project is currently experimental and not supported.
+package gax
+
+const Version = "0.1.0"
diff --git a/vendor/github.com/googleapis/gax-go/header.go b/vendor/github.com/googleapis/gax-go/header.go
new file mode 100644
index 0000000..d81455e
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/header.go
@@ -0,0 +1,24 @@
+package gax
+
+import "bytes"
+
+// XGoogHeader is for use by the Google Cloud Libraries only.
+//
+// XGoogHeader formats key-value pairs.
+// The resulting string is suitable for x-goog-api-client header.
+func XGoogHeader(keyval ...string) string {
+ if len(keyval) == 0 {
+ return ""
+ }
+ if len(keyval)%2 != 0 {
+ panic("gax.Header: odd argument count")
+ }
+ var buf bytes.Buffer
+ for i := 0; i < len(keyval); i += 2 {
+ buf.WriteByte(' ')
+ buf.WriteString(keyval[i])
+ buf.WriteByte('/')
+ buf.WriteString(keyval[i+1])
+ }
+ return buf.String()[1:]
+}
diff --git a/vendor/github.com/googleapis/gax-go/invoke.go b/vendor/github.com/googleapis/gax-go/invoke.go
new file mode 100644
index 0000000..86049d8
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/invoke.go
@@ -0,0 +1,90 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import (
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// A user defined call stub.
+type APICall func(context.Context, CallSettings) error
+
+// Invoke calls the given APICall,
+// performing retries as specified by opts, if any.
+func Invoke(ctx context.Context, call APICall, opts ...CallOption) error {
+ var settings CallSettings
+ for _, opt := range opts {
+ opt.Resolve(&settings)
+ }
+ return invoke(ctx, call, settings, Sleep)
+}
+
+// Sleep is similar to time.Sleep, but it can be interrupted by ctx.Done() closing.
+// If interrupted, Sleep returns ctx.Err().
+func Sleep(ctx context.Context, d time.Duration) error {
+ t := time.NewTimer(d)
+ select {
+ case <-ctx.Done():
+ t.Stop()
+ return ctx.Err()
+ case <-t.C:
+ return nil
+ }
+}
+
+type sleeper func(ctx context.Context, d time.Duration) error
+
+// invoke implements Invoke, taking an additional sleeper argument for testing.
+func invoke(ctx context.Context, call APICall, settings CallSettings, sp sleeper) error {
+ var retryer Retryer
+ for {
+ err := call(ctx, settings)
+ if err == nil {
+ return nil
+ }
+ if settings.Retry == nil {
+ return err
+ }
+ if retryer == nil {
+ if r := settings.Retry(); r != nil {
+ retryer = r
+ } else {
+ return err
+ }
+ }
+ if d, ok := retryer.Retry(err); !ok {
+ return err
+ } else if err = sp(ctx, d); err != nil {
+ return err
+ }
+ }
+}
diff --git a/vendor/github.com/sethgrid/pester/LICENSE.md b/vendor/github.com/sethgrid/pester/LICENSE.md
new file mode 100644
index 0000000..4b49dda
--- /dev/null
+++ b/vendor/github.com/sethgrid/pester/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) SendGrid 2016
+
+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.
diff --git a/vendor/github.com/sethgrid/pester/README.md b/vendor/github.com/sethgrid/pester/README.md
new file mode 100644
index 0000000..ac1d6d9
--- /dev/null
+++ b/vendor/github.com/sethgrid/pester/README.md
@@ -0,0 +1,126 @@
+# pester
+
+`pester` wraps Go's standard lib http client to provide several options to increase resiliency in your request. If you experience poor network conditions or requests could experience varied delays, you can now pester the endpoint for data.
+- Send out multiple requests and get the first back (only used for GET calls)
+- Retry on errors
+- Backoff
+
+### Simple Example
+Use `pester` where you would use the http client calls. By default, pester will use a concurrency of 1, and retry the endpoint 3 times with the `DefaultBackoff` strategy of waiting 1 second between retries.
+```go
+/* swap in replacement, just switch
+ http.{Get|Post|PostForm|Head|Do} to
+ pester.{Get|Post|PostForm|Head|Do}
+*/
+resp, err := pester.Get("http://sethammons.com")
+```
+
+### Backoff Strategy
+Provide your own backoff strategy, or use one of the provided built in strategies:
+- `DefaultBackoff`: 1 second
+- `LinearBackoff`: n seconds where n is the retry number
+- `LinearJitterBackoff`: n seconds where n is the retry number, +/- 0-33%
+- `ExponentialBackoff`: n seconds where n is 2^(retry number)
+- `ExponentialJitterBackoff`: n seconds where n is 2^(retry number), +/- 0-33%
+
+```go
+client := pester.New()
+client.Backoff = func(retry int) time.Duration {
+ // set up something dynamic or use a look up table
+ return time.Duration(retry) * time.Minute
+}
+```
+
+### Complete example
+For a complete and working example, see the sample directory.
+`pester` allows you to use a constructor to control:
+- backoff strategy
+- retries
+- concurrency
+- keeping a log for debugging
+```go
+package main
+
+import (
+ "log"
+ "net/http"
+ "strings"
+
+ "github.com/sethgrid/pester"
+)
+
+func main() {
+ log.Println("Starting...")
+
+ { // drop in replacement for http.Get and other client methods
+ resp, err := pester.Get("http://example.com")
+ if err != nil {
+ log.Println("error GETing example.com", err)
+ }
+ defer resp.Body.Close()
+ log.Printf("example.com %s", resp.Status)
+ }
+
+ { // control the resiliency
+ client := pester.New()
+ client.Concurrency = 3
+ client.MaxRetries = 5
+ client.Backoff = pester.ExponentialBackoff
+ client.KeepLog = true
+
+ resp, err := client.Get("http://example.com")
+ if err != nil {
+ log.Println("error GETing example.com", client.LogString())
+ }
+ defer resp.Body.Close()
+ log.Printf("example.com %s", resp.Status)
+ }
+
+ { // use the pester version of http.Client.Do
+ req, err := http.NewRequest("POST", "http://example.com", strings.NewReader("data"))
+ if err != nil {
+ log.Fatal("Unable to create a new http request", err)
+ }
+ resp, err := pester.Do(req)
+ if err != nil {
+ log.Println("error POSTing example.com", err)
+ }
+ defer resp.Body.Close()
+ log.Printf("example.com %s", resp.Status)
+ }
+}
+
+```
+
+### Example Log
+`pester` also allows you to control the resiliency and can optionally log the errors.
+```go
+c := pester.New()
+c.KeepLog = true
+
+nonExistantURL := "http://localhost:9000/foo"
+_, _ = c.Get(nonExistantURL)
+
+fmt.Println(c.LogString())
+/*
+Output:
+
+1432402837 Get [GET] http://localhost:9000/foo request-0 retry-0 error: Get http://localhost:9000/foo: dial tcp 127.0.0.1:9000: connection refused
+1432402838 Get [GET] http://localhost:9000/foo request-0 retry-1 error: Get http://localhost:9000/foo: dial tcp 127.0.0.1:9000: connection refused
+1432402839 Get [GET] http://localhost:9000/foo request-0 retry-2 error: Get http://localhost:9000/foo: dial tcp 127.0.0.1:9000: connection refused
+*/
+```
+
+### Tests
+
+You can run tests in the root directory with `$ go test`. There is a benchmark-like test available with `$ cd benchmarks; go test`.
+You can see `pester` in action with `$ cd sample; go run main.go`.
+
+For watching open file descriptors, you can run `watch "lsof -i -P | grep main"` if you started the app with `go run main.go`.
+I did this for watching for FD leaks. My method was to alter `sample/main.go` to only run one case (`pester.Get with set backoff stategy, concurrency and retries increased`)
+and adding a sleep after the result came back. This let me verify if FDs were getting left open when they should have closed. If you know a better way, let me know!
+I was able to see that FDs are now closing when they should :)
+
+![Are we there yet?](http://butchbellah.com/wp-content/uploads/2012/06/Are-We-There-Yet.jpg)
+
+Are we there yet? Are we there yet? Are we there yet? Are we there yet? ...
diff --git a/vendor/github.com/sethgrid/pester/main.go b/vendor/github.com/sethgrid/pester/main.go
new file mode 100644
index 0000000..55db6fa
--- /dev/null
+++ b/vendor/github.com/sethgrid/pester/main.go
@@ -0,0 +1,445 @@
+// Package pester provides additional resiliency over the standard http client methods by
+// allowing you to control concurrency, retries, and a backoff strategy.
+package pester
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "net/http"
+ "net/url"
+ "sync"
+ "time"
+)
+
+//ErrUnexpectedMethod occurs when an http.Client method is unable to be mapped from a calling method in the pester client
+var ErrUnexpectedMethod = errors.New("unexpected client method, must be one of Do, Get, Head, Post, or PostFrom")
+
+// ErrReadingBody happens when we cannot read the body bytes
+var ErrReadingBody = errors.New("error reading body")
+
+// ErrReadingRequestBody happens when we cannot read the request body bytes
+var ErrReadingRequestBody = errors.New("error reading request body")
+
+// Client wraps the http client and exposes all the functionality of the http.Client.
+// Additionally, Client provides pester specific values for handling resiliency.
+type Client struct {
+ // wrap it to provide access to http built ins
+ hc *http.Client
+
+ Transport http.RoundTripper
+ CheckRedirect func(req *http.Request, via []*http.Request) error
+ Jar http.CookieJar
+ Timeout time.Duration
+
+ // pester specific
+ Concurrency int
+ MaxRetries int
+ Backoff BackoffStrategy
+ KeepLog bool
+ LogHook LogHook
+
+ SuccessReqNum int
+ SuccessRetryNum int
+
+ wg *sync.WaitGroup
+
+ sync.Mutex
+ ErrLog []ErrEntry
+}
+
+// ErrEntry is used to provide the LogString() data and is populated
+// each time an error happens if KeepLog is set.
+// ErrEntry.Retry is deprecated in favor of ErrEntry.Attempt
+type ErrEntry struct {
+ Time time.Time
+ Method string
+ URL string
+ Verb string
+ Request int
+ Retry int
+ Attempt int
+ Err error
+}
+
+// result simplifies the channel communication for concurrent request handling
+type result struct {
+ resp *http.Response
+ err error
+ req int
+ retry int
+}
+
+// params represents all the params needed to run http client calls and pester errors
+type params struct {
+ method string
+ verb string
+ req *http.Request
+ url string
+ bodyType string
+ body io.Reader
+ data url.Values
+}
+
+var random *rand.Rand
+
+func init() {
+ random = rand.New(rand.NewSource(time.Now().UnixNano()))
+}
+
+// New constructs a new DefaultClient with sensible default values
+func New() *Client {
+ return &Client{
+ Concurrency: DefaultClient.Concurrency,
+ MaxRetries: DefaultClient.MaxRetries,
+ Backoff: DefaultClient.Backoff,
+ ErrLog: DefaultClient.ErrLog,
+ wg: &sync.WaitGroup{},
+ }
+}
+
+// NewExtendedClient allows you to pass in an http.Client that is previously set up
+// and extends it to have Pester's features of concurrency and retries.
+func NewExtendedClient(hc *http.Client) *Client {
+ c := New()
+ c.hc = hc
+ return c
+}
+
+// LogHook is used to log attempts as they happen. This function is never called,
+// however, if KeepLog is set to true.
+type LogHook func(e ErrEntry)
+
+// BackoffStrategy is used to determine how long a retry request should wait until attempted
+type BackoffStrategy func(retry int) time.Duration
+
+// DefaultClient provides sensible defaults
+var DefaultClient = &Client{Concurrency: 1, MaxRetries: 3, Backoff: DefaultBackoff, ErrLog: []ErrEntry{}}
+
+// DefaultBackoff always returns 1 second
+func DefaultBackoff(_ int) time.Duration {
+ return 1 * time.Second
+}
+
+// ExponentialBackoff returns ever increasing backoffs by a power of 2
+func ExponentialBackoff(i int) time.Duration {
+ return time.Duration(1< 0 {
+ p.req.Body = ioutil.NopCloser(bytes.NewBuffer(originalRequestBody))
+ }
+ if len(originalBody) > 0 {
+ p.body = bytes.NewBuffer(originalBody)
+ }
+
+ var resp *http.Response
+ // route the calls
+ switch p.method {
+ case "Do":
+ resp, err = httpClient.Do(p.req)
+ case "Get":
+ resp, err = httpClient.Get(p.url)
+ case "Head":
+ resp, err = httpClient.Head(p.url)
+ case "Post":
+ resp, err = httpClient.Post(p.url, p.bodyType, p.body)
+ case "PostForm":
+ resp, err = httpClient.PostForm(p.url, p.data)
+ default:
+ err = ErrUnexpectedMethod
+ }
+
+ // Early return if we have a valid result
+ // Only retry (ie, continue the loop) on 5xx status codes
+ if err == nil && resp.StatusCode < 500 {
+ multiplexCh <- result{resp: resp, err: err, req: n, retry: i}
+ return
+ }
+
+ c.log(ErrEntry{
+ Time: time.Now(),
+ Method: p.method,
+ Verb: p.verb,
+ URL: p.url,
+ Request: n,
+ Retry: i + 1, // would remove, but would break backward compatibility
+ Attempt: i,
+ Err: err,
+ })
+
+ // if it is the last iteration, grab the result (which is an error at this point)
+ if i == AttemptLimit {
+ multiplexCh <- result{resp: resp, err: err}
+ return
+ }
+
+ // if we are retrying, we should close this response body to free the fd
+ if resp != nil {
+ resp.Body.Close()
+ }
+
+ // prevent a 0 from causing the tick to block, pass additional microsecond
+ <-time.After(c.Backoff(i) + 1*time.Microsecond)
+ }
+ }(req, p)
+ }
+
+ // spin off the go routine so it can continually listen in on late results and close the response bodies
+ go func() {
+ gotFirstResult := false
+ for {
+ select {
+ case res := <-multiplexCh:
+ if !gotFirstResult {
+ gotFirstResult = true
+ close(finishCh)
+ resultCh <- res
+ } else if res.resp != nil {
+ // we only return one result to the caller; close all other response bodies that come back
+ // drain the body before close as to not prevent keepalive. see https://gist.github.com/mholt/eba0f2cc96658be0f717
+ io.Copy(ioutil.Discard, res.resp.Body)
+ res.resp.Body.Close()
+ }
+ case <-allRequestsBackCh:
+ // don't leave this goroutine running
+ return
+ }
+ }
+ }()
+
+ res := <-resultCh
+ c.Lock()
+ defer c.Unlock()
+ c.SuccessReqNum = res.req
+ c.SuccessRetryNum = res.retry
+ return res.resp, res.err
+
+}
+
+// LogString provides a string representation of the errors the client has seen
+func (c *Client) LogString() string {
+ c.Lock()
+ defer c.Unlock()
+ var res string
+ for _, e := range c.ErrLog {
+ res += c.FormatError(e)
+ }
+ return res
+}
+
+// Format the Error to human readable string
+func (c *Client) FormatError(e ErrEntry) string {
+ return fmt.Sprintf("%d %s [%s] %s request-%d retry-%d error: %s\n",
+ e.Time.Unix(), e.Method, e.Verb, e.URL, e.Request, e.Retry, e.Err)
+}
+
+// LogErrCount is a helper method used primarily for test validation
+func (c *Client) LogErrCount() int {
+ c.Lock()
+ defer c.Unlock()
+ return len(c.ErrLog)
+}
+
+// EmbedHTTPClient allows you to extend an existing Pester client with an
+// underlying http.Client, such as https://godoc.org/golang.org/x/oauth2/google#DefaultClient
+func (c *Client) EmbedHTTPClient(hc *http.Client) {
+ c.hc = hc
+}
+
+func (c *Client) log(e ErrEntry) {
+ if c.KeepLog {
+ c.Lock()
+ defer c.Unlock()
+ c.ErrLog = append(c.ErrLog, e)
+ } else if c.LogHook != nil {
+ // NOTE: There is a possibility that Log Printing hook slows it down.
+ // but the consumer can always do the Job in a go-routine.
+ c.LogHook(e)
+ }
+}
+
+// Do provides the same functionality as http.Client.Do
+func (c *Client) Do(req *http.Request) (resp *http.Response, err error) {
+ return c.pester(params{method: "Do", req: req, verb: req.Method, url: req.URL.String()})
+}
+
+// Get provides the same functionality as http.Client.Get
+func (c *Client) Get(url string) (resp *http.Response, err error) {
+ return c.pester(params{method: "Get", url: url, verb: "GET"})
+}
+
+// Head provides the same functionality as http.Client.Head
+func (c *Client) Head(url string) (resp *http.Response, err error) {
+ return c.pester(params{method: "Head", url: url, verb: "HEAD"})
+}
+
+// Post provides the same functionality as http.Client.Post
+func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error) {
+ return c.pester(params{method: "Post", url: url, bodyType: bodyType, body: body, verb: "POST"})
+}
+
+// PostForm provides the same functionality as http.Client.PostForm
+func (c *Client) PostForm(url string, data url.Values) (resp *http.Response, err error) {
+ return c.pester(params{method: "PostForm", url: url, data: data, verb: "POST"})
+}
+
+////////////////////////////////////////
+// Provide self-constructing variants //
+////////////////////////////////////////
+
+// Do provides the same functionality as http.Client.Do and creates its own constructor
+func Do(req *http.Request) (resp *http.Response, err error) {
+ c := New()
+ return c.Do(req)
+}
+
+// Get provides the same functionality as http.Client.Get and creates its own constructor
+func Get(url string) (resp *http.Response, err error) {
+ c := New()
+ return c.Get(url)
+}
+
+// Head provides the same functionality as http.Client.Head and creates its own constructor
+func Head(url string) (resp *http.Response, err error) {
+ c := New()
+ return c.Head(url)
+}
+
+// Post provides the same functionality as http.Client.Post and creates its own constructor
+func Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error) {
+ c := New()
+ return c.Post(url, bodyType, body)
+}
+
+// PostForm provides the same functionality as http.Client.PostForm and creates its own constructor
+func PostForm(url string, data url.Values) (resp *http.Response, err error) {
+ c := New()
+ return c.PostForm(url, data)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
new file mode 100644
index 0000000..23838c4
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -0,0 +1,379 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Conditionf uses a Comparison to assert a complex condition.
+func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
+ return Condition(t, comp, append([]interface{}{msg}, args...)...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
+// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
+// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Emptyf(t, obj, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return Empty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// assert.Equalf(t, 123, 123, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
+ return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
+//
+// Returns whether the assertion was successful (true) or not (false).
+func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Errorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ return Error(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// Exactlyf asserts that two objects are equal is value and type.
+//
+// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Failf reports a failure through
+func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// FailNowf fails test
+func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// assert.Falsef(t, myBool, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ return False(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyContains(t, handler, method, url, values, str)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyNotContains(t, handler, method, url, values, str)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// 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).
+func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPError(t, handler, method, url, values)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// 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).
+func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPRedirect(t, handler, method, url, values)
+}
+
+// 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")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPSuccess(t, handler, method, url, values)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
+func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
+ return Len(t, object, length, append([]interface{}{msg}, args...)...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// assert.Nilf(t, err, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return Nil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoErrorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ return NoError(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// assert.NotNilf(t, err, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return NotNil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return NotPanics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// 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, "^start", "it's not starting", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// NotZerof asserts that i is not the zero value for its type and returns the truth.
+func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ return NotZero(t, i, append([]interface{}{msg}, args...)...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return Panics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
+}
+
+// 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, "start...$", "it's not starting", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// assert.Truef(t, myBool, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ return True(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// Zerof asserts that i is the zero value for its type and returns the truth.
+func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ return Zero(t, i, append([]interface{}{msg}, args...)...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
new file mode 100644
index 0000000..c5cc66f
--- /dev/null
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
@@ -0,0 +1,4 @@
+{{.CommentFormat}}
+func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
+ return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
index e6a7960..fcccbd0 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -1,387 +1,746 @@
/*
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
-*/
+ */
package assert
import (
-
http "net/http"
url "net/url"
time "time"
)
-
// Condition uses a Comparison to assert a complex condition.
func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
return Condition(a.t, comp, msgAndArgs...)
}
+// Conditionf uses a Comparison to assert a complex condition.
+func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
+ return Conditionf(a.t, comp, msg, args...)
+}
// Contains asserts that the specified string, list(array, slice...) or map contains the
// specified substring or element.
-//
-// a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
-// a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
-// a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
-//
+//
+// a.Contains("Hello World", "World")
+// a.Contains(["Hello", "World"], "World")
+// a.Contains({"Hello": "World"}, "Hello")
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
return Contains(a.t, s, contains, msgAndArgs...)
}
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Containsf("Hello World", "World", "error message %s", "formatted")
+// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
+// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return Containsf(a.t, s, contains, msg, args...)
+}
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
// a slice or a channel with len == 0.
-//
+//
// a.Empty(obj)
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
return Empty(a.t, object, msgAndArgs...)
}
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Emptyf(obj, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
+ return Emptyf(a.t, object, msg, args...)
+}
// Equal asserts that two objects are equal.
-//
-// a.Equal(123, 123, "123 and 123 should be equal")
-//
+//
+// a.Equal(123, 123)
+//
// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
return Equal(a.t, expected, actual, msgAndArgs...)
}
-
// EqualError asserts that a function returned an error (i.e. not `nil`)
// and that it is equal to the provided error.
-//
+//
// actualObj, err := SomeFunction()
-// if assert.Error(t, err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
-// }
-//
+// a.EqualError(err, expectedErrorString)
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
return EqualError(a.t, theError, errString, msgAndArgs...)
}
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
+ return EqualErrorf(a.t, theError, errString, msg, args...)
+}
// EqualValues asserts that two objects are equal or convertable to the same types
// and equal.
-//
-// a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
-//
+//
+// a.EqualValues(uint32(123), int32(123))
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
return EqualValues(a.t, expected, actual, msgAndArgs...)
}
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return EqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// a.Equalf(123, 123, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Equalf(a.t, expected, actual, msg, args...)
+}
// Error asserts that a function returned an error (i.e. not `nil`).
-//
+//
// actualObj, err := SomeFunction()
-// if a.Error(err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
+// if a.Error(err) {
+// assert.Equal(t, expectedError, err)
// }
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
return Error(a.t, err, msgAndArgs...)
}
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Errorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
+ return Errorf(a.t, err, msg, args...)
+}
// Exactly asserts that two objects are equal is value and type.
-//
-// a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
-//
+//
+// a.Exactly(int32(123), int64(123))
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
return Exactly(a.t, expected, actual, msgAndArgs...)
}
+// Exactlyf asserts that two objects are equal is value and type.
+//
+// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Exactlyf(a.t, expected, actual, msg, args...)
+}
// Fail reports a failure through
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
return Fail(a.t, failureMessage, msgAndArgs...)
}
-
// FailNow fails test
func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
return FailNow(a.t, failureMessage, msgAndArgs...)
}
+// FailNowf fails test
+func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
+ return FailNowf(a.t, failureMessage, msg, args...)
+}
+
+// Failf reports a failure through
+func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
+ return Failf(a.t, failureMessage, msg, args...)
+}
// False asserts that the specified value is false.
-//
-// a.False(myBool, "myBool should be false")
-//
+//
+// a.False(myBool)
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
return False(a.t, value, msgAndArgs...)
}
+// Falsef asserts that the specified value is false.
+//
+// a.Falsef(myBool, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
+ return Falsef(a.t, value, msg, args...)
+}
// HTTPBodyContains asserts that a specified handler returns a
// body that contains a string.
-//
+//
// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
return HTTPBodyContains(a.t, handler, method, url, values, str)
}
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyContainsf(a.t, handler, method, url, values, str)
+}
// HTTPBodyNotContains asserts that a specified handler returns a
// body that does not contain a string.
-//
+//
// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
return HTTPBodyNotContains(a.t, handler, method, url, values, str)
}
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyNotContainsf(a.t, handler, method, url, values, str)
+}
// HTTPError asserts that a specified handler returns an error status code.
-//
+//
// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values) bool {
return HTTPError(a.t, handler, method, url, values)
}
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// 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).
+func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPErrorf(a.t, handler, method, url, values)
+}
// HTTPRedirect asserts that a specified handler returns a redirect status code.
-//
+//
// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values) bool {
return HTTPRedirect(a.t, handler, method, url, values)
}
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// 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).
+func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPRedirectf(a.t, handler, method, url, values)
+}
// HTTPSuccess asserts that a specified handler returns a success status code.
-//
+//
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values) bool {
return HTTPSuccess(a.t, handler, method, url, values)
}
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values) bool {
+ return HTTPSuccessf(a.t, handler, method, url, values)
+}
// Implements asserts that an object is implemented by the specified interface.
-//
-// a.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
+//
+// a.Implements((*MyInterface)(nil), new(MyObject))
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
return Implements(a.t, interfaceObject, object, msgAndArgs...)
}
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
+func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return Implementsf(a.t, interfaceObject, object, msg, args...)
+}
// InDelta asserts that the two numerals are within delta of each other.
-//
+//
// a.InDelta(math.Pi, (22 / 7.0), 0.01)
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
return InDelta(a.t, expected, actual, delta, msgAndArgs...)
}
-
// InDeltaSlice is the same as InDelta, except it compares two slices.
func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
}
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaf(a.t, expected, actual, delta, msg, args...)
+}
// InEpsilon asserts that expected and actual have a relative error less than epsilon
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
}
-
-// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
-func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
- return InEpsilonSlice(a.t, expected, actual, delta, msgAndArgs...)
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
}
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
+}
// IsType asserts that the specified objects are of the same type.
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
return IsType(a.t, expectedType, object, msgAndArgs...)
}
+// IsTypef asserts that the specified objects are of the same type.
+func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return IsTypef(a.t, expectedType, object, msg, args...)
+}
// JSONEq asserts that two JSON strings are equivalent.
-//
+//
// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
return JSONEq(a.t, expected, actual, msgAndArgs...)
}
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ return JSONEqf(a.t, expected, actual, msg, args...)
+}
// Len asserts that the specified object has specific length.
// Len also fails if the object has a type that len() not accept.
-//
-// a.Len(mySlice, 3, "The size of slice is not 3")
-//
+//
+// a.Len(mySlice, 3)
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
return Len(a.t, object, length, msgAndArgs...)
}
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// a.Lenf(mySlice, 3, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
+ return Lenf(a.t, object, length, msg, args...)
+}
// Nil asserts that the specified object is nil.
-//
-// a.Nil(err, "err should be nothing")
-//
+//
+// a.Nil(err)
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
return Nil(a.t, object, msgAndArgs...)
}
+// Nilf asserts that the specified object is nil.
+//
+// a.Nilf(err, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
+ return Nilf(a.t, object, msg, args...)
+}
// NoError asserts that a function returned no error (i.e. `nil`).
-//
+//
// actualObj, err := SomeFunction()
// if a.NoError(err) {
-// assert.Equal(t, actualObj, expectedObj)
+// assert.Equal(t, expectedObj, actualObj)
// }
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
return NoError(a.t, err, msgAndArgs...)
}
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoErrorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
+ return NoErrorf(a.t, err, msg, args...)
+}
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
-//
-// a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
-// a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
-// a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
-//
+//
+// a.NotContains("Hello World", "Earth")
+// a.NotContains(["Hello", "World"], "Earth")
+// a.NotContains({"Hello": "World"}, "Earth")
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
return NotContains(a.t, s, contains, msgAndArgs...)
}
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
+// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
+// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return NotContainsf(a.t, s, contains, msg, args...)
+}
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
// a slice or a channel with len == 0.
-//
+//
// if a.NotEmpty(obj) {
// assert.Equal(t, "two", obj[1])
// }
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
return NotEmpty(a.t, object, msgAndArgs...)
}
+// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if a.NotEmptyf(obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
+ return NotEmptyf(a.t, object, msg, args...)
+}
// NotEqual asserts that the specified values are NOT equal.
-//
-// a.NotEqual(obj1, obj2, "two objects shouldn't be equal")
-//
+//
+// a.NotEqual(obj1, obj2)
+//
// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
return NotEqual(a.t, expected, actual, msgAndArgs...)
}
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return NotEqualf(a.t, expected, actual, msg, args...)
+}
// NotNil asserts that the specified object is not nil.
-//
-// a.NotNil(err, "err should be something")
-//
+//
+// a.NotNil(err)
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
return NotNil(a.t, object, msgAndArgs...)
}
+// NotNilf asserts that the specified object is not nil.
+//
+// a.NotNilf(err, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
+ return NotNilf(a.t, object, msg, args...)
+}
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
-//
-// a.NotPanics(func(){
-// RemainCalm()
-// }, "Calling RemainCalm() should NOT panic")
-//
+//
+// a.NotPanics(func(){ RemainCalm() })
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
return NotPanics(a.t, f, msgAndArgs...)
}
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ return NotPanicsf(a.t, f, msg, args...)
+}
// NotRegexp asserts that a specified regexp does not match a string.
-//
+//
// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
// a.NotRegexp("^start", "it's not starting")
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
return NotRegexp(a.t, rx, str, msgAndArgs...)
}
+// 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("^start", "it's not starting", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return NotRegexpf(a.t, rx, str, msg, args...)
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ return NotSubset(a.t, list, subset, msgAndArgs...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return NotSubsetf(a.t, list, subset, msg, args...)
+}
// NotZero asserts that i is not the zero value for its type and returns the truth.
func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
return NotZero(a.t, i, msgAndArgs...)
}
+// NotZerof asserts that i is not the zero value for its type and returns the truth.
+func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
+ return NotZerof(a.t, i, msg, args...)
+}
// Panics asserts that the code inside the specified PanicTestFunc panics.
-//
-// a.Panics(func(){
-// GoCrazy()
-// }, "Calling GoCrazy() should panic")
-//
+//
+// a.Panics(func(){ GoCrazy() })
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
return Panics(a.t, f, msgAndArgs...)
}
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return PanicsWithValue(a.t, expected, f, msgAndArgs...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return PanicsWithValuef(a.t, expected, f, msg, args...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ return Panicsf(a.t, f, msg, args...)
+}
// Regexp asserts that a specified regexp matches a string.
-//
+//
// a.Regexp(regexp.MustCompile("start"), "it's starting")
// a.Regexp("start...$", "it's not starting")
-//
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
return Regexp(a.t, rx, str, msgAndArgs...)
}
+// Regexpf asserts that a specified regexp matches a string.
+//
+// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
+// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return Regexpf(a.t, rx, str, msg, args...)
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ return Subset(a.t, list, subset, msgAndArgs...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return Subsetf(a.t, list, subset, msg, args...)
+}
// True asserts that the specified value is true.
-//
-// a.True(myBool, "myBool should be true")
-//
+//
+// a.True(myBool)
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
return True(a.t, value, msgAndArgs...)
}
+// Truef asserts that the specified value is true.
+//
+// a.Truef(myBool, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
+ return Truef(a.t, value, msg, args...)
+}
// WithinDuration asserts that the two times are within duration delta of each other.
-//
-// a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
-//
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
+//
// Returns whether the assertion was successful (true) or not (false).
func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
}
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ return WithinDurationf(a.t, expected, actual, delta, msg, args...)
+}
// Zero asserts that i is the zero value for its type and returns the truth.
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
return Zero(a.t, i, msgAndArgs...)
}
+
+// Zerof asserts that i is the zero value for its type and returns the truth.
+func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
+ return Zerof(a.t, i, msg, args...)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
index 348d5f1..8259050 100644
--- a/vendor/github.com/stretchr/testify/assert/assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -4,6 +4,7 @@ import (
"bufio"
"bytes"
"encoding/json"
+ "errors"
"fmt"
"math"
"reflect"
@@ -18,6 +19,8 @@ import (
"github.com/pmezard/go-difflib/difflib"
)
+//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
+
// TestingT is an interface wrapper around *testing.T
type TestingT interface {
Errorf(format string, args ...interface{})
@@ -38,7 +41,15 @@ func ObjectsAreEqual(expected, actual interface{}) bool {
if expected == nil || actual == nil {
return expected == actual
}
-
+ if exp, ok := expected.([]byte); ok {
+ act, ok := actual.([]byte)
+ if !ok {
+ return false
+ } else if exp == nil || act == nil {
+ return exp == nil && act == nil
+ }
+ return bytes.Equal(exp, act)
+ }
return reflect.DeepEqual(expected, actual)
}
@@ -65,7 +76,7 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool {
/* CallerInfo is necessary because the assert functions use the testing object
internally, causing it to print the file:line of the assert method, rather than where
-the problem actually occured in calling code.*/
+the problem actually occurred in calling code.*/
// CallerInfo returns an array of strings containing the file and line number
// of each stack frame leading from the current test to the assert call that
@@ -82,7 +93,9 @@ func CallerInfo() []string {
for i := 0; ; i++ {
pc, file, line, ok = runtime.Caller(i)
if !ok {
- return nil
+ // The breaks below failed to terminate the loop, and we ran off the
+ // end of the call stack.
+ break
}
// This is a huge edge case, but it will panic if this is the case, see #180
@@ -90,18 +103,30 @@ func CallerInfo() []string {
break
}
- parts := strings.Split(file, "/")
- dir := parts[len(parts)-2]
- file = parts[len(parts)-1]
- if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
- callers = append(callers, fmt.Sprintf("%s:%d", file, line))
- }
-
f := runtime.FuncForPC(pc)
if f == nil {
break
}
name = f.Name()
+
+ // testing.tRunner is the standard library function that calls
+ // tests. Subtests are called directly by tRunner, without going through
+ // the Test/Benchmark/Example function that contains the t.Run calls, so
+ // with subtests we should break when we hit tRunner, without adding it
+ // to the list of callers.
+ if name == "testing.tRunner" {
+ break
+ }
+
+ parts := strings.Split(file, "/")
+ file = parts[len(parts)-1]
+ if len(parts) > 1 {
+ dir := parts[len(parts)-2]
+ if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
+ callers = append(callers, fmt.Sprintf("%s:%d", file, line))
+ }
+ }
+
// Drop the package
segments := strings.Split(name, ".")
name = segments[len(segments)-1]
@@ -141,7 +166,7 @@ func getWhitespaceString() string {
parts := strings.Split(file, "/")
file = parts[len(parts)-1]
- return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
+ return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
}
@@ -158,22 +183,18 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
return ""
}
-// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's
-// test printing (see inner comment for specifics)
-func indentMessageLines(message string, tabs int) string {
+// Aligns the provided message so that all lines after the first line start at the same location as the first line.
+// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
+// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the
+// basis on which the alignment occurs).
+func indentMessageLines(message string, longestLabelLen int) string {
outBuf := new(bytes.Buffer)
for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
+ // no need to align first line because it starts at the correct location (after the label)
if i != 0 {
- outBuf.WriteRune('\n')
- }
- for ii := 0; ii < tabs; ii++ {
- outBuf.WriteRune('\t')
- // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter
- // by 1 prematurely.
- if ii == 0 && i > 0 {
- ii++
- }
+ // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
+ outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
}
outBuf.WriteString(scanner.Text())
}
@@ -205,32 +226,52 @@ func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
// Fail reports a failure through
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+ content := []labeledContent{
+ {"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")},
+ {"Error", failureMessage},
+ }
message := messageFromMsgAndArgs(msgAndArgs...)
-
- errorTrace := strings.Join(CallerInfo(), "\n\r\t\t\t")
if len(message) > 0 {
- t.Errorf("\r%s\r\tError Trace:\t%s\n"+
- "\r\tError:%s\n"+
- "\r\tMessages:\t%s\n\r",
- getWhitespaceString(),
- errorTrace,
- indentMessageLines(failureMessage, 2),
- message)
- } else {
- t.Errorf("\r%s\r\tError Trace:\t%s\n"+
- "\r\tError:%s\n\r",
- getWhitespaceString(),
- errorTrace,
- indentMessageLines(failureMessage, 2))
+ content = append(content, labeledContent{"Messages", message})
}
+ t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...))
+
return false
}
+type labeledContent struct {
+ label string
+ content string
+}
+
+// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
+//
+// \r\t{{label}}:{{align_spaces}}\t{{content}}\n
+//
+// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
+// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
+// alignment is achieved, "\t{{content}}\n" is added for the output.
+//
+// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line.
+func labeledOutput(content ...labeledContent) string {
+ longestLabel := 0
+ for _, v := range content {
+ if len(v.label) > longestLabel {
+ longestLabel = len(v.label)
+ }
+ }
+ var output string
+ for _, v := range content {
+ output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
+ }
+ return output
+}
+
// Implements asserts that an object is implemented by the specified interface.
//
-// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
interfaceType := reflect.TypeOf(interfaceObject).Elem()
@@ -255,32 +296,61 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs
// Equal asserts that two objects are equal.
//
-// assert.Equal(t, 123, 123, "123 and 123 should be equal")
+// assert.Equal(t, 123, 123)
//
// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
if !ObjectsAreEqual(expected, actual) {
diff := diff(expected, actual)
- return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
- " != %#v (actual)%s", expected, actual, diff), msgAndArgs...)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual: %s%s", expected, actual, diff), msgAndArgs...)
}
return true
}
+// formatUnequalValues takes two values of arbitrary types and returns string
+// representations appropriate to be presented to the user.
+//
+// If the values are not of like type, the returned strings will be prefixed
+// with the type name, and the value will be enclosed in parenthesis similar
+// to a type conversion in the Go grammar.
+func formatUnequalValues(expected, actual interface{}) (e string, a string) {
+ if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
+ return fmt.Sprintf("%T(%#v)", expected, expected),
+ fmt.Sprintf("%T(%#v)", actual, actual)
+ }
+
+ return fmt.Sprintf("%#v", expected),
+ fmt.Sprintf("%#v", actual)
+}
+
// EqualValues asserts that two objects are equal or convertable to the same types
// and equal.
//
-// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal")
+// assert.EqualValues(t, uint32(123), int32(123))
//
// Returns whether the assertion was successful (true) or not (false).
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
if !ObjectsAreEqualValues(expected, actual) {
- return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
- " != %#v (actual)", expected, actual), msgAndArgs...)
+ diff := diff(expected, actual)
+ expected, actual = formatUnequalValues(expected, actual)
+ return Fail(t, fmt.Sprintf("Not equal: \n"+
+ "expected: %s\n"+
+ "actual: %s%s", expected, actual, diff), msgAndArgs...)
}
return true
@@ -289,7 +359,7 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa
// Exactly asserts that two objects are equal is value and type.
//
-// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
+// assert.Exactly(t, int32(123), int64(123))
//
// Returns whether the assertion was successful (true) or not (false).
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
@@ -307,7 +377,7 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
// NotNil asserts that the specified object is not nil.
//
-// assert.NotNil(t, err, "err should be something")
+// assert.NotNil(t, err)
//
// Returns whether the assertion was successful (true) or not (false).
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
@@ -334,7 +404,7 @@ func isNil(object interface{}) bool {
// Nil asserts that the specified object is nil.
//
-// assert.Nil(t, err, "err should be nothing")
+// assert.Nil(t, err)
//
// Returns whether the assertion was successful (true) or not (false).
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
@@ -379,9 +449,7 @@ func isEmpty(object interface{}) bool {
objValue := reflect.ValueOf(object)
switch objValue.Kind() {
- case reflect.Map:
- fallthrough
- case reflect.Slice, reflect.Chan:
+ case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
{
return (objValue.Len() == 0)
}
@@ -457,7 +525,7 @@ func getLen(x interface{}) (ok bool, length int) {
// Len asserts that the specified object has specific length.
// Len also fails if the object has a type that len() not accept.
//
-// assert.Len(t, mySlice, 3, "The size of slice is not 3")
+// assert.Len(t, mySlice, 3)
//
// Returns whether the assertion was successful (true) or not (false).
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
@@ -474,7 +542,7 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
// True asserts that the specified value is true.
//
-// assert.True(t, myBool, "myBool should be true")
+// assert.True(t, myBool)
//
// Returns whether the assertion was successful (true) or not (false).
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
@@ -489,7 +557,7 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
// False asserts that the specified value is false.
//
-// assert.False(t, myBool, "myBool should be false")
+// assert.False(t, myBool)
//
// Returns whether the assertion was successful (true) or not (false).
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
@@ -504,10 +572,17 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
// NotEqual asserts that the specified values are NOT equal.
//
-// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
+// assert.NotEqual(t, obj1, obj2)
//
// Returns whether the assertion was successful (true) or not (false).
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if err := validateEqualArgs(expected, actual); err != nil {
+ return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
+ expected, actual, err), msgAndArgs...)
+ }
if ObjectsAreEqual(expected, actual) {
return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
@@ -558,9 +633,9 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
// Contains asserts that the specified string, list(array, slice...) or map contains the
// specified substring or element.
//
-// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
-// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
-// assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
+// assert.Contains(t, "Hello World", "World")
+// assert.Contains(t, ["Hello", "World"], "World")
+// assert.Contains(t, {"Hello": "World"}, "Hello")
//
// Returns whether the assertion was successful (true) or not (false).
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
@@ -580,9 +655,9 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
-// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
-// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
-// assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
+// assert.NotContains(t, "Hello World", "Earth")
+// assert.NotContains(t, ["Hello", "World"], "Earth")
+// assert.NotContains(t, {"Hello": "World"}, "Earth")
//
// Returns whether the assertion was successful (true) or not (false).
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
@@ -599,6 +674,92 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
}
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if subset == nil {
+ return true // we consider nil to be equal to the nil set
+ }
+
+ subsetValue := reflect.ValueOf(subset)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+
+ listKind := reflect.TypeOf(list).Kind()
+ subsetKind := reflect.TypeOf(subset).Kind()
+
+ if listKind != reflect.Array && listKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ for i := 0; i < subsetValue.Len(); i++ {
+ element := subsetValue.Index(i).Interface()
+ ok, found := includeElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...)
+ }
+ }
+
+ return true
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
+ if subset == nil {
+ return false // we consider nil to be equal to the nil set
+ }
+
+ subsetValue := reflect.ValueOf(subset)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+
+ listKind := reflect.TypeOf(list).Kind()
+ subsetKind := reflect.TypeOf(subset).Kind()
+
+ if listKind != reflect.Array && listKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
+ }
+
+ if subsetKind != reflect.Array && subsetKind != reflect.Slice {
+ return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
+ }
+
+ for i := 0; i < subsetValue.Len(); i++ {
+ element := subsetValue.Index(i).Interface()
+ ok, found := includeElement(list, element)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
+ }
+ if !found {
+ return true
+ }
+ }
+
+ return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
+}
+
// Condition uses a Comparison to assert a complex condition.
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
result := comp()
@@ -636,9 +797,7 @@ func didPanic(f PanicTestFunc) (bool, interface{}) {
// Panics asserts that the code inside the specified PanicTestFunc panics.
//
-// assert.Panics(t, func(){
-// GoCrazy()
-// }, "Calling GoCrazy() should panic")
+// assert.Panics(t, func(){ GoCrazy() })
//
// Returns whether the assertion was successful (true) or not (false).
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
@@ -650,11 +809,28 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
return true
}
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
+//
+// Returns whether the assertion was successful (true) or not (false).
+func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+
+ funcDidPanic, panicValue := didPanic(f)
+ if !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
+ }
+ if panicValue != expected {
+ return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
//
-// assert.NotPanics(t, func(){
-// RemainCalm()
-// }, "Calling RemainCalm() should NOT panic")
+// assert.NotPanics(t, func(){ RemainCalm() })
//
// Returns whether the assertion was successful (true) or not (false).
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
@@ -668,7 +844,7 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
// WithinDuration asserts that the two times are within duration delta of each other.
//
-// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
//
// Returns whether the assertion was successful (true) or not (false).
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
@@ -708,6 +884,8 @@ func toFloat(x interface{}) (float64, bool) {
xf = float64(xn)
case float64:
xf = float64(xn)
+ case time.Duration:
+ xf = float64(xn)
default:
xok = false
}
@@ -730,7 +908,7 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs
}
if math.IsNaN(af) {
- return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...)
}
if math.IsNaN(bf) {
@@ -757,7 +935,7 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn
expectedSlice := reflect.ValueOf(expected)
for i := 0; i < actualSlice.Len(); i++ {
- result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
+ result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...)
if !result {
return result
}
@@ -776,7 +954,7 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
}
bf, bok := toFloat(actual)
if !bok {
- return 0, fmt.Errorf("expected value %q cannot be converted to float", actual)
+ return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
}
return math.Abs(af-bf) / math.Abs(af), nil
@@ -792,7 +970,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
}
if actualEpsilon > epsilon {
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
- " < %#v (actual)", actualEpsilon, epsilon), msgAndArgs...)
+ " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
}
return true
@@ -827,13 +1005,13 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
//
// actualObj, err := SomeFunction()
// if assert.NoError(t, err) {
-// assert.Equal(t, actualObj, expectedObj)
+// assert.Equal(t, expectedObj, actualObj)
// }
//
// Returns whether the assertion was successful (true) or not (false).
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
if err != nil {
- return Fail(t, fmt.Sprintf("Received unexpected error %q", err), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
}
return true
@@ -842,16 +1020,15 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
// Error asserts that a function returned an error (i.e. not `nil`).
//
// actualObj, err := SomeFunction()
-// if assert.Error(t, err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
+// if assert.Error(t, err) {
+// assert.Equal(t, expectedError, err)
// }
//
// Returns whether the assertion was successful (true) or not (false).
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
- message := messageFromMsgAndArgs(msgAndArgs...)
if err == nil {
- return Fail(t, "An error is expected but got nil. %s", message)
+ return Fail(t, "An error is expected but got nil.", msgAndArgs...)
}
return true
@@ -861,20 +1038,22 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
// and that it is equal to the provided error.
//
// actualObj, err := SomeFunction()
-// if assert.Error(t, err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
-// }
+// assert.EqualError(t, err, expectedErrorString)
//
// Returns whether the assertion was successful (true) or not (false).
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
-
- message := messageFromMsgAndArgs(msgAndArgs...)
- if !NotNil(t, theError, "An error is expected but got nil. %s", message) {
+ if !Error(t, theError, msgAndArgs...) {
return false
}
- s := "An error with value \"%s\" is expected but got \"%s\". %s"
- return Equal(t, errString, theError.Error(),
- s, errString, theError.Error(), message)
+ expected := errString
+ actual := theError.Error()
+ // don't need to use deep equals here, we know they are both strings
+ if expected != actual {
+ return Fail(t, fmt.Sprintf("Error message not equal:\n"+
+ "expected: %q\n"+
+ "actual: %q", expected, actual), msgAndArgs...)
+ }
+ return true
}
// matchRegexp return true if a specified regexp matches a string.
@@ -989,9 +1168,8 @@ func diff(expected interface{}, actual interface{}) string {
return ""
}
- spew.Config.SortKeys = true
- e := spew.Sdump(expected)
- a := spew.Sdump(actual)
+ e := spewConfig.Sdump(expected)
+ a := spewConfig.Sdump(actual)
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
A: difflib.SplitLines(e),
@@ -1005,3 +1183,26 @@ func diff(expected interface{}, actual interface{}) string {
return "\n\nDiff:\n" + diff
}
+
+// validateEqualArgs checks whether provided arguments can be safely used in the
+// Equal/NotEqual functions.
+func validateEqualArgs(expected, actual interface{}) error {
+ if isFunction(expected) || isFunction(actual) {
+ return errors.New("cannot take func type as argument")
+ }
+ return nil
+}
+
+func isFunction(arg interface{}) bool {
+ if arg == nil {
+ return false
+ }
+ return reflect.TypeOf(arg).Kind() == reflect.Func
+}
+
+var spewConfig = spew.ConfigState{
+ Indent: " ",
+ DisablePointerAddresses: true,
+ DisableCapacities: true,
+ SortKeys: true,
+}
diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
index b867e95..9ad5685 100644
--- a/vendor/github.com/stretchr/testify/assert/forward_assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
@@ -13,4 +13,4 @@ func New(t TestingT) *Assertions {
}
}
-//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl
+//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs
diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go
index e1b9442..ba811c0 100644
--- a/vendor/github.com/stretchr/testify/assert/http_assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go
@@ -8,16 +8,16 @@ import (
"strings"
)
-// httpCode is a helper that returns HTTP code of the response. It returns -1
-// if building a new request fails.
-func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
+// httpCode is a helper that returns HTTP code of the response. It returns -1 and
+// an error if building a new request fails.
+func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
w := httptest.NewRecorder()
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
if err != nil {
- return -1
+ return -1, err
}
handler(w, req)
- return w.Code
+ return w.Code, nil
}
// HTTPSuccess asserts that a specified handler returns a success status code.
@@ -26,11 +26,18 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) i
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
return false
}
- return code >= http.StatusOK && code <= http.StatusPartialContent
+
+ isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
+ if !isSuccessCode {
+ Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isSuccessCode
}
// HTTPRedirect asserts that a specified handler returns a redirect status code.
@@ -39,11 +46,18 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
return false
}
- return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
+
+ isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
+ if !isRedirectCode {
+ Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isRedirectCode
}
// HTTPError asserts that a specified handler returns an error status code.
@@ -52,11 +66,18 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
//
// Returns whether the assertion was successful (true) or not (false).
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
+ code, err := httpCode(handler, method, url, values)
+ if err != nil {
+ Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
return false
}
- return code >= http.StatusBadRequest
+
+ isErrorCode := code >= http.StatusBadRequest
+ if !isErrorCode {
+ Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code))
+ }
+
+ return isErrorCode
}
// HTTPBody is a helper that returns HTTP body of the response. It returns
@@ -99,7 +120,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin
contains := strings.Contains(body, fmt.Sprint(str))
if contains {
- Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
}
return !contains
diff --git a/vendor/github.com/vimeo/go-util/LICENSE b/vendor/github.com/vimeo/go-util/LICENSE
new file mode 100644
index 0000000..22e45cd
--- /dev/null
+++ b/vendor/github.com/vimeo/go-util/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2014, Vimeo, LLC.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of Vimeo, LLC.
diff --git a/vendor/github.com/vimeo/go-util/crc32combine/LICENSE b/vendor/github.com/vimeo/go-util/crc32combine/LICENSE
new file mode 100644
index 0000000..48c40a4
--- /dev/null
+++ b/vendor/github.com/vimeo/go-util/crc32combine/LICENSE
@@ -0,0 +1,20 @@
+Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Jean-loup Gailly Mark Adler
+jloup@gzip.org madler@alumni.caltech.edu
diff --git a/vendor/github.com/vimeo/go-util/crc32combine/crc32combine.go b/vendor/github.com/vimeo/go-util/crc32combine/crc32combine.go
new file mode 100644
index 0000000..2e62d23
--- /dev/null
+++ b/vendor/github.com/vimeo/go-util/crc32combine/crc32combine.go
@@ -0,0 +1,86 @@
+// Package crc32combine provides functionality to calculate the combined
+// CRC-32 hash of two given CRC-32 hash values.
+package crc32combine
+
+// Ported from C to Go in 2016 by Justin Ruggles, with minimal alteration.
+// Used uint for unsigned long. Used uint32 for input arguments in order to match
+// the Go hash/crc32 package. zlib CRC32 combine (https://github.com/madler/zlib)
+
+func gf2MatrixTimes(mat []uint, vec uint) uint {
+ var sum uint
+
+ for vec != 0 {
+ if vec&1 != 0 {
+ sum ^= mat[0]
+ }
+ vec >>= 1
+ mat = mat[1:]
+ }
+ return sum
+}
+
+func gf2MatrixSquare(square, mat []uint) {
+ for n := 0; n < 32; n++ {
+ square[n] = gf2MatrixTimes(mat, mat[n])
+ }
+}
+
+// CRC32Combine returns the combined CRC-32 hash value of the two passed CRC-32
+// hash values crc1 and crc2. poly represents the generator polynomial
+// and len2 specifies the byte length that the crc2 hash covers.
+func CRC32Combine(poly uint32, crc1, crc2 uint32, len2 int64) uint32 {
+ // degenerate case (also disallow negative lengths)
+ if len2 <= 0 {
+ return crc1
+ }
+
+ even := make([]uint, 32) // even-power-of-two zeros operator
+ odd := make([]uint, 32) // odd-power-of-two zeros operator
+
+ // put operator for one zero bit in odd
+ odd[0] = uint(poly) // CRC-32 polynomial
+ row := uint(1)
+ for n := 1; n < 32; n++ {
+ odd[n] = row
+ row <<= 1
+ }
+
+ // put operator for two zero bits in even
+ gf2MatrixSquare(even, odd)
+
+ // put operator for four zero bits in odd
+ gf2MatrixSquare(odd, even)
+
+ // apply len2 zeros to crc1 (first square will put the operator for one
+ // zero byte, eight zero bits, in even)
+ crc1n := uint(crc1)
+ for {
+ // apply zeros operator for this bit of len2
+ gf2MatrixSquare(even, odd)
+ if len2&1 != 0 {
+ crc1n = gf2MatrixTimes(even, crc1n)
+ }
+ len2 >>= 1
+
+ // if no more bits set, then done
+ if len2 == 0 {
+ break
+ }
+
+ // another iteration of the loop with odd and even swapped
+ gf2MatrixSquare(odd, even)
+ if len2&1 != 0 {
+ crc1n = gf2MatrixTimes(odd, crc1n)
+ }
+ len2 >>= 1
+
+ // if no more bits set, then done
+ if len2 == 0 {
+ break
+ }
+ }
+
+ // return combined crc
+ crc1n ^= uint(crc2)
+ return uint32(crc1n)
+}
diff --git a/vendor/go4.org/LICENSE b/vendor/go4.org/LICENSE
new file mode 100644
index 0000000..8f71f43
--- /dev/null
+++ b/vendor/go4.org/LICENSE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
+
diff --git a/vendor/go4.org/syncutil/singleflight/singleflight.go b/vendor/go4.org/syncutil/singleflight/singleflight.go
new file mode 100644
index 0000000..ee2e1b3
--- /dev/null
+++ b/vendor/go4.org/syncutil/singleflight/singleflight.go
@@ -0,0 +1,64 @@
+/*
+Copyright 2013 Google Inc.
+
+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 singleflight provides a duplicate function call suppression
+// mechanism.
+package singleflight // import "go4.org/syncutil/singleflight"
+
+import "sync"
+
+// call is an in-flight or completed Do call
+type call struct {
+ wg sync.WaitGroup
+ val interface{}
+ err error
+}
+
+// Group represents a class of work and forms a namespace in which
+// units of work can be executed with duplicate suppression.
+type Group struct {
+ mu sync.Mutex // protects m
+ m map[string]*call // lazily initialized
+}
+
+// Do executes and returns the results of the given function, making
+// sure that only one execution is in-flight for a given key at a
+// time. If a duplicate comes in, the duplicate caller waits for the
+// original to complete and receives the same results.
+func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) {
+ g.mu.Lock()
+ if g.m == nil {
+ g.m = make(map[string]*call)
+ }
+ if c, ok := g.m[key]; ok {
+ g.mu.Unlock()
+ c.wg.Wait()
+ return c.val, c.err
+ }
+ c := new(call)
+ c.wg.Add(1)
+ g.m[key] = c
+ g.mu.Unlock()
+
+ c.val, c.err = fn()
+ c.wg.Done()
+
+ g.mu.Lock()
+ delete(g.m, key)
+ g.mu.Unlock()
+
+ return c.val, c.err
+}
diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/crypto/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/crypto/PATENTS b/vendor/golang.org/x/crypto/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/crypto/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go
new file mode 100644
index 0000000..fa9c4b3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/acme.go
@@ -0,0 +1,1058 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package acme provides an implementation of the
+// Automatic Certificate Management Environment (ACME) spec.
+// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details.
+//
+// Most common scenarios will want to use autocert subdirectory instead,
+// which provides automatic access to certificates from Let's Encrypt
+// and any other ACME-based CA.
+//
+// This package is a work in progress and makes no API stability promises.
+package acme
+
+import (
+ "bytes"
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/sha256"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/json"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/big"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
+const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
+
+const (
+ maxChainLen = 5 // max depth and breadth of a certificate chain
+ maxCertSize = 1 << 20 // max size of a certificate, in bytes
+
+ // Max number of collected nonces kept in memory.
+ // Expect usual peak of 1 or 2.
+ maxNonces = 100
+)
+
+// Client is an ACME client.
+// The only required field is Key. An example of creating a client with a new key
+// is as follows:
+//
+// key, err := rsa.GenerateKey(rand.Reader, 2048)
+// if err != nil {
+// log.Fatal(err)
+// }
+// client := &Client{Key: key}
+//
+type Client struct {
+ // Key is the account key used to register with a CA and sign requests.
+ // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey.
+ Key crypto.Signer
+
+ // HTTPClient optionally specifies an HTTP client to use
+ // instead of http.DefaultClient.
+ HTTPClient *http.Client
+
+ // DirectoryURL points to the CA directory endpoint.
+ // If empty, LetsEncryptURL is used.
+ // Mutating this value after a successful call of Client's Discover method
+ // will have no effect.
+ DirectoryURL string
+
+ dirMu sync.Mutex // guards writes to dir
+ dir *Directory // cached result of Client's Discover method
+
+ noncesMu sync.Mutex
+ nonces map[string]struct{} // nonces collected from previous responses
+}
+
+// Discover performs ACME server discovery using c.DirectoryURL.
+//
+// It caches successful result. So, subsequent calls will not result in
+// a network round-trip. This also means mutating c.DirectoryURL after successful call
+// of this method will have no effect.
+func (c *Client) Discover(ctx context.Context) (Directory, error) {
+ c.dirMu.Lock()
+ defer c.dirMu.Unlock()
+ if c.dir != nil {
+ return *c.dir, nil
+ }
+
+ dirURL := c.DirectoryURL
+ if dirURL == "" {
+ dirURL = LetsEncryptURL
+ }
+ res, err := c.get(ctx, dirURL)
+ if err != nil {
+ return Directory{}, err
+ }
+ defer res.Body.Close()
+ c.addNonce(res.Header)
+ if res.StatusCode != http.StatusOK {
+ return Directory{}, responseError(res)
+ }
+
+ var v struct {
+ Reg string `json:"new-reg"`
+ Authz string `json:"new-authz"`
+ Cert string `json:"new-cert"`
+ Revoke string `json:"revoke-cert"`
+ Meta struct {
+ Terms string `json:"terms-of-service"`
+ Website string `json:"website"`
+ CAA []string `json:"caa-identities"`
+ }
+ }
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return Directory{}, err
+ }
+ c.dir = &Directory{
+ RegURL: v.Reg,
+ AuthzURL: v.Authz,
+ CertURL: v.Cert,
+ RevokeURL: v.Revoke,
+ Terms: v.Meta.Terms,
+ Website: v.Meta.Website,
+ CAA: v.Meta.CAA,
+ }
+ return *c.dir, nil
+}
+
+// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
+// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
+// with a different duration.
+// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
+//
+// In the case where CA server does not provide the issued certificate in the response,
+// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
+// In such a scenario, the caller can cancel the polling with ctx.
+//
+// CreateCert returns an error if the CA's response or chain was unreasonably large.
+// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
+func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, "", err
+ }
+
+ req := struct {
+ Resource string `json:"resource"`
+ CSR string `json:"csr"`
+ NotBefore string `json:"notBefore,omitempty"`
+ NotAfter string `json:"notAfter,omitempty"`
+ }{
+ Resource: "new-cert",
+ CSR: base64.RawURLEncoding.EncodeToString(csr),
+ }
+ now := timeNow()
+ req.NotBefore = now.Format(time.RFC3339)
+ if exp > 0 {
+ req.NotAfter = now.Add(exp).Format(time.RFC3339)
+ }
+
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req)
+ if err != nil {
+ return nil, "", err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusCreated {
+ return nil, "", responseError(res)
+ }
+
+ curl := res.Header.Get("Location") // cert permanent URL
+ if res.ContentLength == 0 {
+ // no cert in the body; poll until we get it
+ cert, err := c.FetchCert(ctx, curl, bundle)
+ return cert, curl, err
+ }
+ // slurp issued cert and CA chain, if requested
+ cert, err := c.responseCert(ctx, res, bundle)
+ return cert, curl, err
+}
+
+// FetchCert retrieves already issued certificate from the given url, in DER format.
+// It retries the request until the certificate is successfully retrieved,
+// context is cancelled by the caller or an error response is received.
+//
+// The returned value will also contain the CA (issuer) certificate if the bundle argument is true.
+//
+// FetchCert returns an error if the CA's response or chain was unreasonably large.
+// Callers are encouraged to parse the returned value to ensure the certificate is valid
+// and has expected features.
+func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
+ for {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode == http.StatusOK {
+ return c.responseCert(ctx, res, bundle)
+ }
+ if res.StatusCode > 299 {
+ return nil, responseError(res)
+ }
+ d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second)
+ select {
+ case <-time.After(d):
+ // retry
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+}
+
+// RevokeCert revokes a previously issued certificate cert, provided in DER format.
+//
+// The key argument, used to sign the request, must be authorized
+// to revoke the certificate. It's up to the CA to decide which keys are authorized.
+// For instance, the key pair of the certificate may be authorized.
+// If the key is nil, c.Key is used instead.
+func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
+ if _, err := c.Discover(ctx); err != nil {
+ return err
+ }
+
+ body := &struct {
+ Resource string `json:"resource"`
+ Cert string `json:"certificate"`
+ Reason int `json:"reason"`
+ }{
+ Resource: "revoke-cert",
+ Cert: base64.RawURLEncoding.EncodeToString(cert),
+ Reason: int(reason),
+ }
+ if key == nil {
+ key = c.Key
+ }
+ res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return responseError(res)
+ }
+ return nil
+}
+
+// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service
+// during account registration. See Register method of Client for more details.
+func AcceptTOS(tosURL string) bool { return true }
+
+// Register creates a new account registration by following the "new-reg" flow.
+// It returns the registered account. The account is not modified.
+//
+// The registration may require the caller to agree to the CA's Terms of Service (TOS).
+// If so, and the account has not indicated the acceptance of the terms (see Account for details),
+// Register calls prompt with a TOS URL provided by the CA. Prompt should report
+// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
+func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, err
+ }
+
+ var err error
+ if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil {
+ return nil, err
+ }
+ var accept bool
+ if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms {
+ accept = prompt(a.CurrentTerms)
+ }
+ if accept {
+ a.AgreedTerms = a.CurrentTerms
+ a, err = c.UpdateReg(ctx, a)
+ }
+ return a, err
+}
+
+// GetReg retrieves an existing registration.
+// The url argument is an Account URI.
+func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
+ a, err := c.doReg(ctx, url, "reg", nil)
+ if err != nil {
+ return nil, err
+ }
+ a.URI = url
+ return a, nil
+}
+
+// UpdateReg updates an existing registration.
+// It returns an updated account copy. The provided account is not modified.
+func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
+ uri := a.URI
+ a, err := c.doReg(ctx, uri, "reg", a)
+ if err != nil {
+ return nil, err
+ }
+ a.URI = uri
+ return a, nil
+}
+
+// Authorize performs the initial step in an authorization flow.
+// The caller will then need to choose from and perform a set of returned
+// challenges using c.Accept in order to successfully complete authorization.
+//
+// If an authorization has been previously granted, the CA may return
+// a valid authorization (Authorization.Status is StatusValid). If so, the caller
+// need not fulfill any challenge and can proceed to requesting a certificate.
+func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, err
+ }
+
+ type authzID struct {
+ Type string `json:"type"`
+ Value string `json:"value"`
+ }
+ req := struct {
+ Resource string `json:"resource"`
+ Identifier authzID `json:"identifier"`
+ }{
+ Resource: "new-authz",
+ Identifier: authzID{Type: "dns", Value: domain},
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusCreated {
+ return nil, responseError(res)
+ }
+
+ var v wireAuthz
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ if v.Status != StatusPending && v.Status != StatusValid {
+ return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
+ }
+ return v.authorization(res.Header.Get("Location")), nil
+}
+
+// GetAuthorization retrieves an authorization identified by the given URL.
+//
+// If a caller needs to poll an authorization until its status is final,
+// see the WaitAuthorization method.
+func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+ var v wireAuthz
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.authorization(url), nil
+}
+
+// RevokeAuthorization relinquishes an existing authorization identified
+// by the given URL.
+// The url argument is an Authorization.URI value.
+//
+// If successful, the caller will be required to obtain a new authorization
+// using the Authorize method before being able to request a new certificate
+// for the domain associated with the authorization.
+//
+// It does not revoke existing certificates.
+func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
+ req := struct {
+ Resource string `json:"resource"`
+ Status string `json:"status"`
+ Delete bool `json:"delete"`
+ }{
+ Resource: "authz",
+ Status: "deactivated",
+ Delete: true,
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return responseError(res)
+ }
+ return nil
+}
+
+// WaitAuthorization polls an authorization at the given URL
+// until it is in one of the final states, StatusValid or StatusInvalid,
+// or the context is done.
+//
+// It returns a non-nil Authorization only if its Status is StatusValid.
+// In all other cases WaitAuthorization returns an error.
+// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
+func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
+ sleep := sleeper(ctx)
+ for {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ retry := res.Header.Get("Retry-After")
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ res.Body.Close()
+ if err := sleep(retry, 1); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ var raw wireAuthz
+ err = json.NewDecoder(res.Body).Decode(&raw)
+ res.Body.Close()
+ if err != nil {
+ if err := sleep(retry, 0); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ if raw.Status == StatusValid {
+ return raw.authorization(url), nil
+ }
+ if raw.Status == StatusInvalid {
+ return nil, raw.error(url)
+ }
+ if err := sleep(retry, 0); err != nil {
+ return nil, err
+ }
+ }
+}
+
+// GetChallenge retrieves the current status of an challenge.
+//
+// A client typically polls a challenge status using this method.
+func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+ v := wireChallenge{URI: url}
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.challenge(), nil
+}
+
+// Accept informs the server that the client accepts one of its challenges
+// previously obtained with c.Authorize.
+//
+// The server will then perform the validation asynchronously.
+func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
+ auth, err := keyAuth(c.Key.Public(), chal.Token)
+ if err != nil {
+ return nil, err
+ }
+
+ req := struct {
+ Resource string `json:"resource"`
+ Type string `json:"type"`
+ Auth string `json:"keyAuthorization"`
+ }{
+ Resource: "challenge",
+ Type: chal.Type,
+ Auth: auth,
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ // Note: the protocol specifies 200 as the expected response code, but
+ // letsencrypt seems to be returning 202.
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+
+ var v wireChallenge
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.challenge(), nil
+}
+
+// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response.
+// A TXT record containing the returned value must be provisioned under
+// "_acme-challenge" name of the domain being validated.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return "", err
+ }
+ b := sha256.Sum256([]byte(ka))
+ return base64.RawURLEncoding.EncodeToString(b[:]), nil
+}
+
+// HTTP01ChallengeResponse returns the response for an http-01 challenge.
+// Servers should respond with the value to HTTP requests at the URL path
+// provided by HTTP01ChallengePath to validate the challenge and prove control
+// over a domain name.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
+ return keyAuth(c.Key.Public(), token)
+}
+
+// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
+// should be provided by the servers.
+// The response value can be obtained with HTTP01ChallengeResponse.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) HTTP01ChallengePath(token string) string {
+ return "/.well-known/acme-challenge/" + token
+}
+
+// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
+// Servers can present the certificate to validate the challenge and prove control
+// over a domain name.
+//
+// The implementation is incomplete in that the returned value is a single certificate,
+// computed only for Z0 of the key authorization. ACME CAs are expected to update
+// their implementations to use the newer version, TLS-SNI-02.
+// For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3.
+//
+// The token argument is a Challenge.Token value.
+// If a WithKey option is provided, its private part signs the returned cert,
+// and the public part is used to specify the signee.
+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
+//
+// The returned certificate is valid for the next 24 hours and must be presented only when
+// the server name of the client hello matches exactly the returned name value.
+func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ b := sha256.Sum256([]byte(ka))
+ h := hex.EncodeToString(b[:])
+ name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
+ cert, err = tlsChallengeCert([]string{name}, opt)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ return cert, name, nil
+}
+
+// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
+// Servers can present the certificate to validate the challenge and prove control
+// over a domain name. For more details on TLS-SNI-02 see
+// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3.
+//
+// The token argument is a Challenge.Token value.
+// If a WithKey option is provided, its private part signs the returned cert,
+// and the public part is used to specify the signee.
+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
+//
+// The returned certificate is valid for the next 24 hours and must be presented only when
+// the server name in the client hello matches exactly the returned name value.
+func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
+ b := sha256.Sum256([]byte(token))
+ h := hex.EncodeToString(b[:])
+ sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
+
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ b = sha256.Sum256([]byte(ka))
+ h = hex.EncodeToString(b[:])
+ sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
+
+ cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ return cert, sanA, nil
+}
+
+// doReg sends all types of registration requests.
+// The type of request is identified by typ argument, which is a "resource"
+// in the ACME spec terms.
+//
+// A non-nil acct argument indicates whether the intention is to mutate data
+// of the Account. Only Contact and Agreement of its fields are used
+// in such cases.
+func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) {
+ req := struct {
+ Resource string `json:"resource"`
+ Contact []string `json:"contact,omitempty"`
+ Agreement string `json:"agreement,omitempty"`
+ }{
+ Resource: typ,
+ }
+ if acct != nil {
+ req.Contact = acct.Contact
+ req.Agreement = acct.AgreedTerms
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode < 200 || res.StatusCode > 299 {
+ return nil, responseError(res)
+ }
+
+ var v struct {
+ Contact []string
+ Agreement string
+ Authorizations string
+ Certificates string
+ }
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ var tos string
+ if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 {
+ tos = v[0]
+ }
+ var authz string
+ if v := linkHeader(res.Header, "next"); len(v) > 0 {
+ authz = v[0]
+ }
+ return &Account{
+ URI: res.Header.Get("Location"),
+ Contact: v.Contact,
+ AgreedTerms: v.Agreement,
+ CurrentTerms: tos,
+ Authz: authz,
+ Authorizations: v.Authorizations,
+ Certificates: v.Certificates,
+ }, nil
+}
+
+// retryPostJWS will retry calls to postJWS if there is a badNonce error,
+// clearing the stored nonces after each error.
+// If the response was 4XX-5XX, then responseError is called on the body,
+// the body is closed, and the error returned.
+func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ sleep := sleeper(ctx)
+ for {
+ res, err := c.postJWS(ctx, key, url, body)
+ if err != nil {
+ return nil, err
+ }
+ // handle errors 4XX-5XX with responseError
+ if res.StatusCode >= 400 && res.StatusCode <= 599 {
+ err := responseError(res)
+ res.Body.Close()
+ // according to spec badNonce is urn:ietf:params:acme:error:badNonce
+ // however, acme servers in the wild return their version of the error
+ // https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
+ if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") {
+ // clear any nonces that we might've stored that might now be
+ // considered bad
+ c.clearNonces()
+ retry := res.Header.Get("Retry-After")
+ if err := sleep(retry, 1); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ return nil, err
+ }
+ return res, nil
+ }
+}
+
+// postJWS signs the body with the given key and POSTs it to the provided url.
+// The body argument must be JSON-serializable.
+func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ nonce, err := c.popNonce(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ b, err := jwsEncodeJSON(body, key, nonce)
+ if err != nil {
+ return nil, err
+ }
+ res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b))
+ if err != nil {
+ return nil, err
+ }
+ c.addNonce(res.Header)
+ return res, nil
+}
+
+// popNonce returns a nonce value previously stored with c.addNonce
+// or fetches a fresh one from the given URL.
+func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) == 0 {
+ return c.fetchNonce(ctx, url)
+ }
+ var nonce string
+ for nonce = range c.nonces {
+ delete(c.nonces, nonce)
+ break
+ }
+ return nonce, nil
+}
+
+// clearNonces clears any stored nonces
+func (c *Client) clearNonces() {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ c.nonces = make(map[string]struct{})
+}
+
+// addNonce stores a nonce value found in h (if any) for future use.
+func (c *Client) addNonce(h http.Header) {
+ v := nonceFromHeader(h)
+ if v == "" {
+ return
+ }
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) >= maxNonces {
+ return
+ }
+ if c.nonces == nil {
+ c.nonces = make(map[string]struct{})
+ }
+ c.nonces[v] = struct{}{}
+}
+
+func (c *Client) httpClient() *http.Client {
+ if c.HTTPClient != nil {
+ return c.HTTPClient
+ }
+ return http.DefaultClient
+}
+
+func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", urlStr, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", contentType)
+ return c.do(ctx, req)
+}
+
+func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) {
+ res, err := c.httpClient().Do(req.WithContext(ctx))
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ // Prefer the unadorned context error.
+ // (The acme package had tests assuming this, previously from ctxhttp's
+ // behavior, predating net/http supporting contexts natively)
+ // TODO(bradfitz): reconsider this in the future. But for now this
+ // requires no test updates.
+ return nil, ctx.Err()
+ default:
+ return nil, err
+ }
+ }
+ return res, nil
+}
+
+func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
+ resp, err := c.head(ctx, url)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+ nonce := nonceFromHeader(resp.Header)
+ if nonce == "" {
+ if resp.StatusCode > 299 {
+ return "", responseError(resp)
+ }
+ return "", errors.New("acme: nonce not found")
+ }
+ return nonce, nil
+}
+
+func nonceFromHeader(h http.Header) string {
+ return h.Get("Replay-Nonce")
+}
+
+func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bool) ([][]byte, error) {
+ b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
+ if err != nil {
+ return nil, fmt.Errorf("acme: response stream: %v", err)
+ }
+ if len(b) > maxCertSize {
+ return nil, errors.New("acme: certificate is too big")
+ }
+ cert := [][]byte{b}
+ if !bundle {
+ return cert, nil
+ }
+
+ // Append CA chain cert(s).
+ // At least one is required according to the spec:
+ // https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1
+ up := linkHeader(res.Header, "up")
+ if len(up) == 0 {
+ return nil, errors.New("acme: rel=up link not found")
+ }
+ if len(up) > maxChainLen {
+ return nil, errors.New("acme: rel=up link is too large")
+ }
+ for _, url := range up {
+ cc, err := c.chainCert(ctx, url, 0)
+ if err != nil {
+ return nil, err
+ }
+ cert = append(cert, cc...)
+ }
+ return cert, nil
+}
+
+// responseError creates an error of Error type from resp.
+func responseError(resp *http.Response) error {
+ // don't care if ReadAll returns an error:
+ // json.Unmarshal will fail in that case anyway
+ b, _ := ioutil.ReadAll(resp.Body)
+ e := &wireError{Status: resp.StatusCode}
+ if err := json.Unmarshal(b, e); err != nil {
+ // this is not a regular error response:
+ // populate detail with anything we received,
+ // e.Status will already contain HTTP response code value
+ e.Detail = string(b)
+ if e.Detail == "" {
+ e.Detail = resp.Status
+ }
+ }
+ return e.error(resp.Header)
+}
+
+// chainCert fetches CA certificate chain recursively by following "up" links.
+// Each recursive call increments the depth by 1, resulting in an error
+// if the recursion level reaches maxChainLen.
+//
+// First chainCert call starts with depth of 0.
+func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte, error) {
+ if depth >= maxChainLen {
+ return nil, errors.New("acme: certificate chain is too deep")
+ }
+
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return nil, responseError(res)
+ }
+ b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
+ if err != nil {
+ return nil, err
+ }
+ if len(b) > maxCertSize {
+ return nil, errors.New("acme: certificate is too big")
+ }
+ chain := [][]byte{b}
+
+ uplink := linkHeader(res.Header, "up")
+ if len(uplink) > maxChainLen {
+ return nil, errors.New("acme: certificate chain is too large")
+ }
+ for _, up := range uplink {
+ cc, err := c.chainCert(ctx, up, depth+1)
+ if err != nil {
+ return nil, err
+ }
+ chain = append(chain, cc...)
+ }
+
+ return chain, nil
+}
+
+// linkHeader returns URI-Reference values of all Link headers
+// with relation-type rel.
+// See https://tools.ietf.org/html/rfc5988#section-5 for details.
+func linkHeader(h http.Header, rel string) []string {
+ var links []string
+ for _, v := range h["Link"] {
+ parts := strings.Split(v, ";")
+ for _, p := range parts {
+ p = strings.TrimSpace(p)
+ if !strings.HasPrefix(p, "rel=") {
+ continue
+ }
+ if v := strings.Trim(p[4:], `"`); v == rel {
+ links = append(links, strings.Trim(parts[0], "<>"))
+ }
+ }
+ }
+ return links
+}
+
+// sleeper returns a function that accepts the Retry-After HTTP header value
+// and an increment that's used with backoff to increasingly sleep on
+// consecutive calls until the context is done. If the Retry-After header
+// cannot be parsed, then backoff is used with a maximum sleep time of 10
+// seconds.
+func sleeper(ctx context.Context) func(ra string, inc int) error {
+ var count int
+ return func(ra string, inc int) error {
+ count += inc
+ d := backoff(count, 10*time.Second)
+ d = retryAfter(ra, d)
+ wakeup := time.NewTimer(d)
+ defer wakeup.Stop()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-wakeup.C:
+ return nil
+ }
+ }
+}
+
+// retryAfter parses a Retry-After HTTP header value,
+// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
+// It returns d if v cannot be parsed.
+func retryAfter(v string, d time.Duration) time.Duration {
+ if i, err := strconv.Atoi(v); err == nil {
+ return time.Duration(i) * time.Second
+ }
+ t, err := http.ParseTime(v)
+ if err != nil {
+ return d
+ }
+ return t.Sub(timeNow())
+}
+
+// backoff computes a duration after which an n+1 retry iteration should occur
+// using truncated exponential backoff algorithm.
+//
+// The n argument is always bounded between 0 and 30.
+// The max argument defines upper bound for the returned value.
+func backoff(n int, max time.Duration) time.Duration {
+ if n < 0 {
+ n = 0
+ }
+ if n > 30 {
+ n = 30
+ }
+ var d time.Duration
+ if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
+ d = time.Duration(x.Int64()) * time.Millisecond
+ }
+ d += time.Duration(1< max {
+ return max
+ }
+ return d
+}
+
+// keyAuth generates a key authorization string for a given token.
+func keyAuth(pub crypto.PublicKey, token string) (string, error) {
+ th, err := JWKThumbprint(pub)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%s.%s", token, th), nil
+}
+
+// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
+// with the given SANs and auto-generated public/private key pair.
+// The Subject Common Name is set to the first SAN to aid debugging.
+// To create a cert with a custom key pair, specify WithKey option.
+func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
+ var (
+ key crypto.Signer
+ tmpl *x509.Certificate
+ )
+ for _, o := range opt {
+ switch o := o.(type) {
+ case *certOptKey:
+ if key != nil {
+ return tls.Certificate{}, errors.New("acme: duplicate key option")
+ }
+ key = o.key
+ case *certOptTemplate:
+ var t = *(*x509.Certificate)(o) // shallow copy is ok
+ tmpl = &t
+ default:
+ // package's fault, if we let this happen:
+ panic(fmt.Sprintf("unsupported option type %T", o))
+ }
+ }
+ if key == nil {
+ var err error
+ if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
+ return tls.Certificate{}, err
+ }
+ }
+ if tmpl == nil {
+ tmpl = &x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(24 * time.Hour),
+ BasicConstraintsValid: true,
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ }
+ }
+ tmpl.DNSNames = san
+ if len(san) > 0 {
+ tmpl.Subject.CommonName = san[0]
+ }
+
+ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+ return tls.Certificate{
+ Certificate: [][]byte{der},
+ PrivateKey: key,
+ }, nil
+}
+
+// encodePEM returns b encoded as PEM with block of type typ.
+func encodePEM(typ string, b []byte) []byte {
+ pb := &pem.Block{Type: typ, Bytes: b}
+ return pem.EncodeToMemory(pb)
+}
+
+// timeNow is useful for testing for fixed current time.
+var timeNow = time.Now
diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/golang.org/x/crypto/acme/autocert/autocert.go
new file mode 100644
index 0000000..94edba9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/autocert.go
@@ -0,0 +1,821 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package autocert provides automatic access to certificates from Let's Encrypt
+// and any other ACME-based CA.
+//
+// This package is a work in progress and makes no API stability promises.
+package autocert
+
+import (
+ "bytes"
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ mathrand "math/rand"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/crypto/acme"
+)
+
+// createCertRetryAfter is how much time to wait before removing a failed state
+// entry due to an unsuccessful createCert call.
+// This is a variable instead of a const for testing.
+// TODO: Consider making it configurable or an exp backoff?
+var createCertRetryAfter = time.Minute
+
+// pseudoRand is safe for concurrent use.
+var pseudoRand *lockedMathRand
+
+func init() {
+ src := mathrand.NewSource(timeNow().UnixNano())
+ pseudoRand = &lockedMathRand{rnd: mathrand.New(src)}
+}
+
+// AcceptTOS is a Manager.Prompt function that always returns true to
+// indicate acceptance of the CA's Terms of Service during account
+// registration.
+func AcceptTOS(tosURL string) bool { return true }
+
+// HostPolicy specifies which host names the Manager is allowed to respond to.
+// It returns a non-nil error if the host should be rejected.
+// The returned error is accessible via tls.Conn.Handshake and its callers.
+// See Manager's HostPolicy field and GetCertificate method docs for more details.
+type HostPolicy func(ctx context.Context, host string) error
+
+// HostWhitelist returns a policy where only the specified host names are allowed.
+// Only exact matches are currently supported. Subdomains, regexp or wildcard
+// will not match.
+func HostWhitelist(hosts ...string) HostPolicy {
+ whitelist := make(map[string]bool, len(hosts))
+ for _, h := range hosts {
+ whitelist[h] = true
+ }
+ return func(_ context.Context, host string) error {
+ if !whitelist[host] {
+ return errors.New("acme/autocert: host not configured")
+ }
+ return nil
+ }
+}
+
+// defaultHostPolicy is used when Manager.HostPolicy is not set.
+func defaultHostPolicy(context.Context, string) error {
+ return nil
+}
+
+// Manager is a stateful certificate manager built on top of acme.Client.
+// It obtains and refreshes certificates automatically,
+// as well as providing them to a TLS server via tls.Config.
+//
+// You must specify a cache implementation, such as DirCache,
+// to reuse obtained certificates across program restarts.
+// Otherwise your server is very likely to exceed the certificate
+// issuer's request rate limits.
+type Manager struct {
+ // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS).
+ // The registration may require the caller to agree to the CA's TOS.
+ // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report
+ // whether the caller agrees to the terms.
+ //
+ // To always accept the terms, the callers can use AcceptTOS.
+ Prompt func(tosURL string) bool
+
+ // Cache optionally stores and retrieves previously-obtained certificates.
+ // If nil, certs will only be cached for the lifetime of the Manager.
+ //
+ // Manager passes the Cache certificates data encoded in PEM, with private/public
+ // parts combined in a single Cache.Put call, private key first.
+ Cache Cache
+
+ // HostPolicy controls which domains the Manager will attempt
+ // to retrieve new certificates for. It does not affect cached certs.
+ //
+ // If non-nil, HostPolicy is called before requesting a new cert.
+ // If nil, all hosts are currently allowed. This is not recommended,
+ // as it opens a potential attack where clients connect to a server
+ // by IP address and pretend to be asking for an incorrect host name.
+ // Manager will attempt to obtain a certificate for that host, incorrectly,
+ // eventually reaching the CA's rate limit for certificate requests
+ // and making it impossible to obtain actual certificates.
+ //
+ // See GetCertificate for more details.
+ HostPolicy HostPolicy
+
+ // RenewBefore optionally specifies how early certificates should
+ // be renewed before they expire.
+ //
+ // If zero, they're renewed 30 days before expiration.
+ RenewBefore time.Duration
+
+ // Client is used to perform low-level operations, such as account registration
+ // and requesting new certificates.
+ // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
+ // directory endpoint and a newly-generated ECDSA P-256 key.
+ //
+ // Mutating the field after the first call of GetCertificate method will have no effect.
+ Client *acme.Client
+
+ // Email optionally specifies a contact email address.
+ // This is used by CAs, such as Let's Encrypt, to notify about problems
+ // with issued certificates.
+ //
+ // If the Client's account key is already registered, Email is not used.
+ Email string
+
+ // ForceRSA makes the Manager generate certificates with 2048-bit RSA keys.
+ //
+ // If false, a default is used. Currently the default
+ // is EC-based keys using the P-256 curve.
+ ForceRSA bool
+
+ clientMu sync.Mutex
+ client *acme.Client // initialized by acmeClient method
+
+ stateMu sync.Mutex
+ state map[string]*certState // keyed by domain name
+
+ // tokenCert is keyed by token domain name, which matches server name
+ // of ClientHello. Keys always have ".acme.invalid" suffix.
+ tokenCertMu sync.RWMutex
+ tokenCert map[string]*tls.Certificate
+
+ // renewal tracks the set of domains currently running renewal timers.
+ // It is keyed by domain name.
+ renewalMu sync.Mutex
+ renewal map[string]*domainRenewal
+}
+
+// GetCertificate implements the tls.Config.GetCertificate hook.
+// It provides a TLS certificate for hello.ServerName host, including answering
+// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored.
+//
+// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting
+// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation.
+// The error is propagated back to the caller of GetCertificate and is user-visible.
+// This does not affect cached certs. See HostPolicy field description for more details.
+func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ if m.Prompt == nil {
+ return nil, errors.New("acme/autocert: Manager.Prompt not set")
+ }
+
+ name := hello.ServerName
+ if name == "" {
+ return nil, errors.New("acme/autocert: missing server name")
+ }
+ if !strings.Contains(strings.Trim(name, "."), ".") {
+ return nil, errors.New("acme/autocert: server name component count invalid")
+ }
+ if strings.ContainsAny(name, `/\`) {
+ return nil, errors.New("acme/autocert: server name contains invalid character")
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
+ defer cancel()
+
+ // check whether this is a token cert requested for TLS-SNI challenge
+ if strings.HasSuffix(name, ".acme.invalid") {
+ m.tokenCertMu.RLock()
+ defer m.tokenCertMu.RUnlock()
+ if cert := m.tokenCert[name]; cert != nil {
+ return cert, nil
+ }
+ if cert, err := m.cacheGet(ctx, name); err == nil {
+ return cert, nil
+ }
+ // TODO: cache error results?
+ return nil, fmt.Errorf("acme/autocert: no token cert for %q", name)
+ }
+
+ // regular domain
+ name = strings.TrimSuffix(name, ".") // golang.org/issue/18114
+ cert, err := m.cert(ctx, name)
+ if err == nil {
+ return cert, nil
+ }
+ if err != ErrCacheMiss {
+ return nil, err
+ }
+
+ // first-time
+ if err := m.hostPolicy()(ctx, name); err != nil {
+ return nil, err
+ }
+ cert, err = m.createCert(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ m.cachePut(ctx, name, cert)
+ return cert, nil
+}
+
+// cert returns an existing certificate either from m.state or cache.
+// If a certificate is found in cache but not in m.state, the latter will be filled
+// with the cached value.
+func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) {
+ m.stateMu.Lock()
+ if s, ok := m.state[name]; ok {
+ m.stateMu.Unlock()
+ s.RLock()
+ defer s.RUnlock()
+ return s.tlscert()
+ }
+ defer m.stateMu.Unlock()
+ cert, err := m.cacheGet(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ signer, ok := cert.PrivateKey.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key cannot sign")
+ }
+ if m.state == nil {
+ m.state = make(map[string]*certState)
+ }
+ s := &certState{
+ key: signer,
+ cert: cert.Certificate,
+ leaf: cert.Leaf,
+ }
+ m.state[name] = s
+ go m.renew(name, s.key, s.leaf.NotAfter)
+ return cert, nil
+}
+
+// cacheGet always returns a valid certificate, or an error otherwise.
+// If a cached certficate exists but is not valid, ErrCacheMiss is returned.
+func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) {
+ if m.Cache == nil {
+ return nil, ErrCacheMiss
+ }
+ data, err := m.Cache.Get(ctx, domain)
+ if err != nil {
+ return nil, err
+ }
+
+ // private
+ priv, pub := pem.Decode(data)
+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
+ return nil, ErrCacheMiss
+ }
+ privKey, err := parsePrivateKey(priv.Bytes)
+ if err != nil {
+ return nil, err
+ }
+
+ // public
+ var pubDER [][]byte
+ for len(pub) > 0 {
+ var b *pem.Block
+ b, pub = pem.Decode(pub)
+ if b == nil {
+ break
+ }
+ pubDER = append(pubDER, b.Bytes)
+ }
+ if len(pub) > 0 {
+ // Leftover content not consumed by pem.Decode. Corrupt. Ignore.
+ return nil, ErrCacheMiss
+ }
+
+ // verify and create TLS cert
+ leaf, err := validCert(domain, pubDER, privKey)
+ if err != nil {
+ return nil, ErrCacheMiss
+ }
+ tlscert := &tls.Certificate{
+ Certificate: pubDER,
+ PrivateKey: privKey,
+ Leaf: leaf,
+ }
+ return tlscert, nil
+}
+
+func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error {
+ if m.Cache == nil {
+ return nil
+ }
+
+ // contains PEM-encoded data
+ var buf bytes.Buffer
+
+ // private
+ switch key := tlscert.PrivateKey.(type) {
+ case *ecdsa.PrivateKey:
+ if err := encodeECDSAKey(&buf, key); err != nil {
+ return err
+ }
+ case *rsa.PrivateKey:
+ b := x509.MarshalPKCS1PrivateKey(key)
+ pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b}
+ if err := pem.Encode(&buf, pb); err != nil {
+ return err
+ }
+ default:
+ return errors.New("acme/autocert: unknown private key type")
+ }
+
+ // public
+ for _, b := range tlscert.Certificate {
+ pb := &pem.Block{Type: "CERTIFICATE", Bytes: b}
+ if err := pem.Encode(&buf, pb); err != nil {
+ return err
+ }
+ }
+
+ return m.Cache.Put(ctx, domain, buf.Bytes())
+}
+
+func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
+ b, err := x509.MarshalECPrivateKey(key)
+ if err != nil {
+ return err
+ }
+ pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+ return pem.Encode(w, pb)
+}
+
+// createCert starts the domain ownership verification and returns a certificate
+// for that domain upon success.
+//
+// If the domain is already being verified, it waits for the existing verification to complete.
+// Either way, createCert blocks for the duration of the whole process.
+func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) {
+ // TODO: maybe rewrite this whole piece using sync.Once
+ state, err := m.certState(domain)
+ if err != nil {
+ return nil, err
+ }
+ // state may exist if another goroutine is already working on it
+ // in which case just wait for it to finish
+ if !state.locked {
+ state.RLock()
+ defer state.RUnlock()
+ return state.tlscert()
+ }
+
+ // We are the first; state is locked.
+ // Unblock the readers when domain ownership is verified
+ // and we got the cert or the process failed.
+ defer state.Unlock()
+ state.locked = false
+
+ der, leaf, err := m.authorizedCert(ctx, state.key, domain)
+ if err != nil {
+ // Remove the failed state after some time,
+ // making the manager call createCert again on the following TLS hello.
+ time.AfterFunc(createCertRetryAfter, func() {
+ defer testDidRemoveState(domain)
+ m.stateMu.Lock()
+ defer m.stateMu.Unlock()
+ // Verify the state hasn't changed and it's still invalid
+ // before deleting.
+ s, ok := m.state[domain]
+ if !ok {
+ return
+ }
+ if _, err := validCert(domain, s.cert, s.key); err == nil {
+ return
+ }
+ delete(m.state, domain)
+ })
+ return nil, err
+ }
+ state.cert = der
+ state.leaf = leaf
+ go m.renew(domain, state.key, state.leaf.NotAfter)
+ return state.tlscert()
+}
+
+// certState returns a new or existing certState.
+// If a new certState is returned, state.exist is false and the state is locked.
+// The returned error is non-nil only in the case where a new state could not be created.
+func (m *Manager) certState(domain string) (*certState, error) {
+ m.stateMu.Lock()
+ defer m.stateMu.Unlock()
+ if m.state == nil {
+ m.state = make(map[string]*certState)
+ }
+ // existing state
+ if state, ok := m.state[domain]; ok {
+ return state, nil
+ }
+
+ // new locked state
+ var (
+ err error
+ key crypto.Signer
+ )
+ if m.ForceRSA {
+ key, err = rsa.GenerateKey(rand.Reader, 2048)
+ } else {
+ key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ state := &certState{
+ key: key,
+ locked: true,
+ }
+ state.Lock() // will be unlocked by m.certState caller
+ m.state[domain] = state
+ return state, nil
+}
+
+// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
+// The key argument is the certificate private key.
+func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
+ if err := m.verify(ctx, domain); err != nil {
+ return nil, nil, err
+ }
+ client, err := m.acmeClient(ctx)
+ if err != nil {
+ return nil, nil, err
+ }
+ csr, err := certRequest(key, domain)
+ if err != nil {
+ return nil, nil, err
+ }
+ der, _, err = client.CreateCert(ctx, csr, 0, true)
+ if err != nil {
+ return nil, nil, err
+ }
+ leaf, err = validCert(domain, der, key)
+ if err != nil {
+ return nil, nil, err
+ }
+ return der, leaf, nil
+}
+
+// verify starts a new identifier (domain) authorization flow.
+// It prepares a challenge response and then blocks until the authorization
+// is marked as "completed" by the CA (either succeeded or failed).
+//
+// verify returns nil iff the verification was successful.
+func (m *Manager) verify(ctx context.Context, domain string) error {
+ client, err := m.acmeClient(ctx)
+ if err != nil {
+ return err
+ }
+
+ // start domain authorization and get the challenge
+ authz, err := client.Authorize(ctx, domain)
+ if err != nil {
+ return err
+ }
+ // maybe don't need to at all
+ if authz.Status == acme.StatusValid {
+ return nil
+ }
+
+ // pick a challenge: prefer tls-sni-02 over tls-sni-01
+ // TODO: consider authz.Combinations
+ var chal *acme.Challenge
+ for _, c := range authz.Challenges {
+ if c.Type == "tls-sni-02" {
+ chal = c
+ break
+ }
+ if c.Type == "tls-sni-01" {
+ chal = c
+ }
+ }
+ if chal == nil {
+ return errors.New("acme/autocert: no supported challenge type found")
+ }
+
+ // create a token cert for the challenge response
+ var (
+ cert tls.Certificate
+ name string
+ )
+ switch chal.Type {
+ case "tls-sni-01":
+ cert, name, err = client.TLSSNI01ChallengeCert(chal.Token)
+ case "tls-sni-02":
+ cert, name, err = client.TLSSNI02ChallengeCert(chal.Token)
+ default:
+ err = fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
+ }
+ if err != nil {
+ return err
+ }
+ m.putTokenCert(ctx, name, &cert)
+ defer func() {
+ // verification has ended at this point
+ // don't need token cert anymore
+ go m.deleteTokenCert(name)
+ }()
+
+ // ready to fulfill the challenge
+ if _, err := client.Accept(ctx, chal); err != nil {
+ return err
+ }
+ // wait for the CA to validate
+ _, err = client.WaitAuthorization(ctx, authz.URI)
+ return err
+}
+
+// putTokenCert stores the cert under the named key in both m.tokenCert map
+// and m.Cache.
+func (m *Manager) putTokenCert(ctx context.Context, name string, cert *tls.Certificate) {
+ m.tokenCertMu.Lock()
+ defer m.tokenCertMu.Unlock()
+ if m.tokenCert == nil {
+ m.tokenCert = make(map[string]*tls.Certificate)
+ }
+ m.tokenCert[name] = cert
+ m.cachePut(ctx, name, cert)
+}
+
+// deleteTokenCert removes the token certificate for the specified domain name
+// from both m.tokenCert map and m.Cache.
+func (m *Manager) deleteTokenCert(name string) {
+ m.tokenCertMu.Lock()
+ defer m.tokenCertMu.Unlock()
+ delete(m.tokenCert, name)
+ if m.Cache != nil {
+ m.Cache.Delete(context.Background(), name)
+ }
+}
+
+// renew starts a cert renewal timer loop, one per domain.
+//
+// The loop is scheduled in two cases:
+// - a cert was fetched from cache for the first time (wasn't in m.state)
+// - a new cert was created by m.createCert
+//
+// The key argument is a certificate private key.
+// The exp argument is the cert expiration time (NotAfter).
+func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) {
+ m.renewalMu.Lock()
+ defer m.renewalMu.Unlock()
+ if m.renewal[domain] != nil {
+ // another goroutine is already on it
+ return
+ }
+ if m.renewal == nil {
+ m.renewal = make(map[string]*domainRenewal)
+ }
+ dr := &domainRenewal{m: m, domain: domain, key: key}
+ m.renewal[domain] = dr
+ dr.start(exp)
+}
+
+// stopRenew stops all currently running cert renewal timers.
+// The timers are not restarted during the lifetime of the Manager.
+func (m *Manager) stopRenew() {
+ m.renewalMu.Lock()
+ defer m.renewalMu.Unlock()
+ for name, dr := range m.renewal {
+ delete(m.renewal, name)
+ dr.stop()
+ }
+}
+
+func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
+ const keyName = "acme_account.key"
+
+ genKey := func() (*ecdsa.PrivateKey, error) {
+ return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ }
+
+ if m.Cache == nil {
+ return genKey()
+ }
+
+ data, err := m.Cache.Get(ctx, keyName)
+ if err == ErrCacheMiss {
+ key, err := genKey()
+ if err != nil {
+ return nil, err
+ }
+ var buf bytes.Buffer
+ if err := encodeECDSAKey(&buf, key); err != nil {
+ return nil, err
+ }
+ if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil {
+ return nil, err
+ }
+ return key, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ priv, _ := pem.Decode(data)
+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
+ return nil, errors.New("acme/autocert: invalid account key found in cache")
+ }
+ return parsePrivateKey(priv.Bytes)
+}
+
+func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) {
+ m.clientMu.Lock()
+ defer m.clientMu.Unlock()
+ if m.client != nil {
+ return m.client, nil
+ }
+
+ client := m.Client
+ if client == nil {
+ client = &acme.Client{DirectoryURL: acme.LetsEncryptURL}
+ }
+ if client.Key == nil {
+ var err error
+ client.Key, err = m.accountKey(ctx)
+ if err != nil {
+ return nil, err
+ }
+ }
+ var contact []string
+ if m.Email != "" {
+ contact = []string{"mailto:" + m.Email}
+ }
+ a := &acme.Account{Contact: contact}
+ _, err := client.Register(ctx, a, m.Prompt)
+ if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict {
+ // conflict indicates the key is already registered
+ m.client = client
+ err = nil
+ }
+ return m.client, err
+}
+
+func (m *Manager) hostPolicy() HostPolicy {
+ if m.HostPolicy != nil {
+ return m.HostPolicy
+ }
+ return defaultHostPolicy
+}
+
+func (m *Manager) renewBefore() time.Duration {
+ if m.RenewBefore > renewJitter {
+ return m.RenewBefore
+ }
+ return 720 * time.Hour // 30 days
+}
+
+// certState is ready when its mutex is unlocked for reading.
+type certState struct {
+ sync.RWMutex
+ locked bool // locked for read/write
+ key crypto.Signer // private key for cert
+ cert [][]byte // DER encoding
+ leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil
+}
+
+// tlscert creates a tls.Certificate from s.key and s.cert.
+// Callers should wrap it in s.RLock() and s.RUnlock().
+func (s *certState) tlscert() (*tls.Certificate, error) {
+ if s.key == nil {
+ return nil, errors.New("acme/autocert: missing signer")
+ }
+ if len(s.cert) == 0 {
+ return nil, errors.New("acme/autocert: missing certificate")
+ }
+ return &tls.Certificate{
+ PrivateKey: s.key,
+ Certificate: s.cert,
+ Leaf: s.leaf,
+ }, nil
+}
+
+// certRequest creates a certificate request for the given common name cn
+// and optional SANs.
+func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) {
+ req := &x509.CertificateRequest{
+ Subject: pkix.Name{CommonName: cn},
+ DNSNames: san,
+ }
+ return x509.CreateCertificateRequest(rand.Reader, req, key)
+}
+
+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
+//
+// Inspired by parsePrivateKey in crypto/tls/tls.go.
+func parsePrivateKey(der []byte) (crypto.Signer, error) {
+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+ return key, nil
+ }
+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key, nil
+ case *ecdsa.PrivateKey:
+ return key, nil
+ default:
+ return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping")
+ }
+ }
+ if key, err := x509.ParseECPrivateKey(der); err == nil {
+ return key, nil
+ }
+
+ return nil, errors.New("acme/autocert: failed to parse private key")
+}
+
+// validCert parses a cert chain provided as der argument and verifies the leaf, der[0],
+// corresponds to the private key, as well as the domain match and expiration dates.
+// It doesn't do any revocation checking.
+//
+// The returned value is the verified leaf cert.
+func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) {
+ // parse public part(s)
+ var n int
+ for _, b := range der {
+ n += len(b)
+ }
+ pub := make([]byte, n)
+ n = 0
+ for _, b := range der {
+ n += copy(pub[n:], b)
+ }
+ x509Cert, err := x509.ParseCertificates(pub)
+ if len(x509Cert) == 0 {
+ return nil, errors.New("acme/autocert: no public key found")
+ }
+ // verify the leaf is not expired and matches the domain name
+ leaf = x509Cert[0]
+ now := timeNow()
+ if now.Before(leaf.NotBefore) {
+ return nil, errors.New("acme/autocert: certificate is not valid yet")
+ }
+ if now.After(leaf.NotAfter) {
+ return nil, errors.New("acme/autocert: expired certificate")
+ }
+ if err := leaf.VerifyHostname(domain); err != nil {
+ return nil, err
+ }
+ // ensure the leaf corresponds to the private key
+ switch pub := leaf.PublicKey.(type) {
+ case *rsa.PublicKey:
+ prv, ok := key.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key type does not match public key type")
+ }
+ if pub.N.Cmp(prv.N) != 0 {
+ return nil, errors.New("acme/autocert: private key does not match public key")
+ }
+ case *ecdsa.PublicKey:
+ prv, ok := key.(*ecdsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key type does not match public key type")
+ }
+ if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 {
+ return nil, errors.New("acme/autocert: private key does not match public key")
+ }
+ default:
+ return nil, errors.New("acme/autocert: unknown public key algorithm")
+ }
+ return leaf, nil
+}
+
+func retryAfter(v string) time.Duration {
+ if i, err := strconv.Atoi(v); err == nil {
+ return time.Duration(i) * time.Second
+ }
+ if t, err := http.ParseTime(v); err == nil {
+ return t.Sub(timeNow())
+ }
+ return time.Second
+}
+
+type lockedMathRand struct {
+ sync.Mutex
+ rnd *mathrand.Rand
+}
+
+func (r *lockedMathRand) int63n(max int64) int64 {
+ r.Lock()
+ n := r.rnd.Int63n(max)
+ r.Unlock()
+ return n
+}
+
+// For easier testing.
+var (
+ timeNow = time.Now
+
+ // Called when a state is removed.
+ testDidRemoveState = func(domain string) {}
+)
diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go
new file mode 100644
index 0000000..61a5fd2
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/cache.go
@@ -0,0 +1,130 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+ "context"
+ "errors"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+// ErrCacheMiss is returned when a certificate is not found in cache.
+var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
+
+// Cache is used by Manager to store and retrieve previously obtained certificates
+// as opaque data.
+//
+// The key argument of the methods refers to a domain name but need not be an FQDN.
+// Cache implementations should not rely on the key naming pattern.
+type Cache interface {
+ // Get returns a certificate data for the specified key.
+ // If there's no such key, Get returns ErrCacheMiss.
+ Get(ctx context.Context, key string) ([]byte, error)
+
+ // Put stores the data in the cache under the specified key.
+ // Underlying implementations may use any data storage format,
+ // as long as the reverse operation, Get, results in the original data.
+ Put(ctx context.Context, key string, data []byte) error
+
+ // Delete removes a certificate data from the cache under the specified key.
+ // If there's no such key in the cache, Delete returns nil.
+ Delete(ctx context.Context, key string) error
+}
+
+// DirCache implements Cache using a directory on the local filesystem.
+// If the directory does not exist, it will be created with 0700 permissions.
+type DirCache string
+
+// Get reads a certificate data from the specified file name.
+func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
+ name = filepath.Join(string(d), name)
+ var (
+ data []byte
+ err error
+ done = make(chan struct{})
+ )
+ go func() {
+ data, err = ioutil.ReadFile(name)
+ close(done)
+ }()
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case <-done:
+ }
+ if os.IsNotExist(err) {
+ return nil, ErrCacheMiss
+ }
+ return data, err
+}
+
+// Put writes the certificate data to the specified file name.
+// The file will be created with 0600 permissions.
+func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
+ if err := os.MkdirAll(string(d), 0700); err != nil {
+ return err
+ }
+
+ done := make(chan struct{})
+ var err error
+ go func() {
+ defer close(done)
+ var tmp string
+ if tmp, err = d.writeTempFile(name, data); err != nil {
+ return
+ }
+ select {
+ case <-ctx.Done():
+ // Don't overwrite the file if the context was canceled.
+ default:
+ newName := filepath.Join(string(d), name)
+ err = os.Rename(tmp, newName)
+ }
+ }()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ }
+ return err
+}
+
+// Delete removes the specified file name.
+func (d DirCache) Delete(ctx context.Context, name string) error {
+ name = filepath.Join(string(d), name)
+ var (
+ err error
+ done = make(chan struct{})
+ )
+ go func() {
+ err = os.Remove(name)
+ close(done)
+ }()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ }
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ return nil
+}
+
+// writeTempFile writes b to a temporary file, closes the file and returns its path.
+func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
+ // TempFile uses 0600 permissions
+ f, err := ioutil.TempFile(string(d), prefix)
+ if err != nil {
+ return "", err
+ }
+ if _, err := f.Write(b); err != nil {
+ f.Close()
+ return "", err
+ }
+ return f.Name(), f.Close()
+}
diff --git a/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/golang.org/x/crypto/acme/autocert/listener.go
new file mode 100644
index 0000000..d744df0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/listener.go
@@ -0,0 +1,160 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+ "crypto/tls"
+ "log"
+ "net"
+ "os"
+ "path/filepath"
+ "runtime"
+ "time"
+)
+
+// NewListener returns a net.Listener that listens on the standard TLS
+// port (443) on all interfaces and returns *tls.Conn connections with
+// LetsEncrypt certificates for the provided domain or domains.
+//
+// It enables one-line HTTPS servers:
+//
+// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
+//
+// NewListener is a convenience function for a common configuration.
+// More complex or custom configurations can use the autocert.Manager
+// type instead.
+//
+// Use of this function implies acceptance of the LetsEncrypt Terms of
+// Service. If domains is not empty, the provided domains are passed
+// to HostWhitelist. If domains is empty, the listener will do
+// LetsEncrypt challenges for any requested domain, which is not
+// recommended.
+//
+// Certificates are cached in a "golang-autocert" directory under an
+// operating system-specific cache or temp directory. This may not
+// be suitable for servers spanning multiple machines.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+func NewListener(domains ...string) net.Listener {
+ m := &Manager{
+ Prompt: AcceptTOS,
+ }
+ if len(domains) > 0 {
+ m.HostPolicy = HostWhitelist(domains...)
+ }
+ dir := cacheDir()
+ if err := os.MkdirAll(dir, 0700); err != nil {
+ log.Printf("warning: autocert.NewListener not using a cache: %v", err)
+ } else {
+ m.Cache = DirCache(dir)
+ }
+ return m.Listener()
+}
+
+// Listener listens on the standard TLS port (443) on all interfaces
+// and returns a net.Listener returning *tls.Conn connections.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+//
+// Unlike NewListener, it is the caller's responsibility to initialize
+// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
+func (m *Manager) Listener() net.Listener {
+ ln := &listener{
+ m: m,
+ conf: &tls.Config{
+ GetCertificate: m.GetCertificate, // bonus: panic on nil m
+ NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
+ },
+ }
+ ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
+ return ln
+}
+
+type listener struct {
+ m *Manager
+ conf *tls.Config
+
+ tcpListener net.Listener
+ tcpListenErr error
+}
+
+func (ln *listener) Accept() (net.Conn, error) {
+ if ln.tcpListenErr != nil {
+ return nil, ln.tcpListenErr
+ }
+ conn, err := ln.tcpListener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ tcpConn := conn.(*net.TCPConn)
+
+ // Because Listener is a convenience function, help out with
+ // this too. This is not possible for the caller to set once
+ // we return a *tcp.Conn wrapping an inaccessible net.Conn.
+ // If callers don't want this, they can do things the manual
+ // way and tweak as needed. But this is what net/http does
+ // itself, so copy that. If net/http changes, we can change
+ // here too.
+ tcpConn.SetKeepAlive(true)
+ tcpConn.SetKeepAlivePeriod(3 * time.Minute)
+
+ return tls.Server(tcpConn, ln.conf), nil
+}
+
+func (ln *listener) Addr() net.Addr {
+ if ln.tcpListener != nil {
+ return ln.tcpListener.Addr()
+ }
+ // net.Listen failed. Return something non-nil in case callers
+ // call Addr before Accept:
+ return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443}
+}
+
+func (ln *listener) Close() error {
+ if ln.tcpListenErr != nil {
+ return ln.tcpListenErr
+ }
+ return ln.tcpListener.Close()
+}
+
+func homeDir() string {
+ if runtime.GOOS == "windows" {
+ return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+ }
+ if h := os.Getenv("HOME"); h != "" {
+ return h
+ }
+ return "/"
+}
+
+func cacheDir() string {
+ const base = "golang-autocert"
+ switch runtime.GOOS {
+ case "darwin":
+ return filepath.Join(homeDir(), "Library", "Caches", base)
+ case "windows":
+ for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
+ if v := os.Getenv(ev); v != "" {
+ return filepath.Join(v, base)
+ }
+ }
+ // Worst case:
+ return filepath.Join(homeDir(), base)
+ }
+ if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
+ return filepath.Join(xdg, base)
+ }
+ return filepath.Join(homeDir(), ".cache", base)
+}
diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/golang.org/x/crypto/acme/autocert/renewal.go
new file mode 100644
index 0000000..6c5da2b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/renewal.go
@@ -0,0 +1,124 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+ "context"
+ "crypto"
+ "sync"
+ "time"
+)
+
+// renewJitter is the maximum deviation from Manager.RenewBefore.
+const renewJitter = time.Hour
+
+// domainRenewal tracks the state used by the periodic timers
+// renewing a single domain's cert.
+type domainRenewal struct {
+ m *Manager
+ domain string
+ key crypto.Signer
+
+ timerMu sync.Mutex
+ timer *time.Timer
+}
+
+// start starts a cert renewal timer at the time
+// defined by the certificate expiration time exp.
+//
+// If the timer is already started, calling start is a noop.
+func (dr *domainRenewal) start(exp time.Time) {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer != nil {
+ return
+ }
+ dr.timer = time.AfterFunc(dr.next(exp), dr.renew)
+}
+
+// stop stops the cert renewal timer.
+// If the timer is already stopped, calling stop is a noop.
+func (dr *domainRenewal) stop() {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer == nil {
+ return
+ }
+ dr.timer.Stop()
+ dr.timer = nil
+}
+
+// renew is called periodically by a timer.
+// The first renew call is kicked off by dr.start.
+func (dr *domainRenewal) renew() {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer == nil {
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
+ defer cancel()
+ // TODO: rotate dr.key at some point?
+ next, err := dr.do(ctx)
+ if err != nil {
+ next = renewJitter / 2
+ next += time.Duration(pseudoRand.int63n(int64(next)))
+ }
+ dr.timer = time.AfterFunc(next, dr.renew)
+ testDidRenewLoop(next, err)
+}
+
+// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
+// Instead, it requests a new certificate independently and, upon success,
+// replaces dr.m.state item with a new one and updates cache for the given domain.
+//
+// It may return immediately if the expiration date of the currently cached cert
+// is far enough in the future.
+//
+// The returned value is a time interval after which the renewal should occur again.
+func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
+ // a race is likely unavoidable in a distributed environment
+ // but we try nonetheless
+ if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil {
+ next := dr.next(tlscert.Leaf.NotAfter)
+ if next > dr.m.renewBefore()+renewJitter {
+ return next, nil
+ }
+ }
+
+ der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain)
+ if err != nil {
+ return 0, err
+ }
+ state := &certState{
+ key: dr.key,
+ cert: der,
+ leaf: leaf,
+ }
+ tlscert, err := state.tlscert()
+ if err != nil {
+ return 0, err
+ }
+ dr.m.cachePut(ctx, dr.domain, tlscert)
+ dr.m.stateMu.Lock()
+ defer dr.m.stateMu.Unlock()
+ // m.state is guaranteed to be non-nil at this point
+ dr.m.state[dr.domain] = state
+ return dr.next(leaf.NotAfter), nil
+}
+
+func (dr *domainRenewal) next(expiry time.Time) time.Duration {
+ d := expiry.Sub(timeNow()) - dr.m.renewBefore()
+ // add a bit of randomness to renew deadline
+ n := pseudoRand.int63n(int64(renewJitter))
+ d -= time.Duration(n)
+ if d < 0 {
+ return 0
+ }
+ return d
+}
+
+var testDidRenewLoop = func(next time.Duration, err error) {}
diff --git a/vendor/golang.org/x/crypto/acme/jws.go b/vendor/golang.org/x/crypto/acme/jws.go
new file mode 100644
index 0000000..6cbca25
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/jws.go
@@ -0,0 +1,153 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package acme
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ _ "crypto/sha512" // need for EC keys
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "math/big"
+)
+
+// jwsEncodeJSON signs claimset using provided key and a nonce.
+// The result is serialized in JSON format.
+// See https://tools.ietf.org/html/rfc7515#section-7.
+func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
+ jwk, err := jwkEncode(key.Public())
+ if err != nil {
+ return nil, err
+ }
+ alg, sha := jwsHasher(key)
+ if alg == "" || !sha.Available() {
+ return nil, ErrUnsupportedKey
+ }
+ phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce)
+ phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
+ cs, err := json.Marshal(claimset)
+ if err != nil {
+ return nil, err
+ }
+ payload := base64.RawURLEncoding.EncodeToString(cs)
+ hash := sha.New()
+ hash.Write([]byte(phead + "." + payload))
+ sig, err := jwsSign(key, sha, hash.Sum(nil))
+ if err != nil {
+ return nil, err
+ }
+
+ enc := struct {
+ Protected string `json:"protected"`
+ Payload string `json:"payload"`
+ Sig string `json:"signature"`
+ }{
+ Protected: phead,
+ Payload: payload,
+ Sig: base64.RawURLEncoding.EncodeToString(sig),
+ }
+ return json.Marshal(&enc)
+}
+
+// jwkEncode encodes public part of an RSA or ECDSA key into a JWK.
+// The result is also suitable for creating a JWK thumbprint.
+// https://tools.ietf.org/html/rfc7517
+func jwkEncode(pub crypto.PublicKey) (string, error) {
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
+ // https://tools.ietf.org/html/rfc7518#section-6.3.1
+ n := pub.N
+ e := big.NewInt(int64(pub.E))
+ // Field order is important.
+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
+ return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`,
+ base64.RawURLEncoding.EncodeToString(e.Bytes()),
+ base64.RawURLEncoding.EncodeToString(n.Bytes()),
+ ), nil
+ case *ecdsa.PublicKey:
+ // https://tools.ietf.org/html/rfc7518#section-6.2.1
+ p := pub.Curve.Params()
+ n := p.BitSize / 8
+ if p.BitSize%8 != 0 {
+ n++
+ }
+ x := pub.X.Bytes()
+ if n > len(x) {
+ x = append(make([]byte, n-len(x)), x...)
+ }
+ y := pub.Y.Bytes()
+ if n > len(y) {
+ y = append(make([]byte, n-len(y)), y...)
+ }
+ // Field order is important.
+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
+ return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`,
+ p.Name,
+ base64.RawURLEncoding.EncodeToString(x),
+ base64.RawURLEncoding.EncodeToString(y),
+ ), nil
+ }
+ return "", ErrUnsupportedKey
+}
+
+// jwsSign signs the digest using the given key.
+// It returns ErrUnsupportedKey if the key type is unknown.
+// The hash is used only for RSA keys.
+func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key.Sign(rand.Reader, digest, hash)
+ case *ecdsa.PrivateKey:
+ r, s, err := ecdsa.Sign(rand.Reader, key, digest)
+ if err != nil {
+ return nil, err
+ }
+ rb, sb := r.Bytes(), s.Bytes()
+ size := key.Params().BitSize / 8
+ if size%8 > 0 {
+ size++
+ }
+ sig := make([]byte, size*2)
+ copy(sig[size-len(rb):], rb)
+ copy(sig[size*2-len(sb):], sb)
+ return sig, nil
+ }
+ return nil, ErrUnsupportedKey
+}
+
+// jwsHasher indicates suitable JWS algorithm name and a hash function
+// to use for signing a digest with the provided key.
+// It returns ("", 0) if the key is not supported.
+func jwsHasher(key crypto.Signer) (string, crypto.Hash) {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return "RS256", crypto.SHA256
+ case *ecdsa.PrivateKey:
+ switch key.Params().Name {
+ case "P-256":
+ return "ES256", crypto.SHA256
+ case "P-384":
+ return "ES384", crypto.SHA384
+ case "P-521":
+ return "ES512", crypto.SHA512
+ }
+ }
+ return "", 0
+}
+
+// JWKThumbprint creates a JWK thumbprint out of pub
+// as specified in https://tools.ietf.org/html/rfc7638.
+func JWKThumbprint(pub crypto.PublicKey) (string, error) {
+ jwk, err := jwkEncode(pub)
+ if err != nil {
+ return "", err
+ }
+ b := sha256.Sum256([]byte(jwk))
+ return base64.RawURLEncoding.EncodeToString(b[:]), nil
+}
diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go
new file mode 100644
index 0000000..3e19974
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/types.go
@@ -0,0 +1,329 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package acme
+
+import (
+ "crypto"
+ "crypto/x509"
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+)
+
+// ACME server response statuses used to describe Authorization and Challenge states.
+const (
+ StatusUnknown = "unknown"
+ StatusPending = "pending"
+ StatusProcessing = "processing"
+ StatusValid = "valid"
+ StatusInvalid = "invalid"
+ StatusRevoked = "revoked"
+)
+
+// CRLReasonCode identifies the reason for a certificate revocation.
+type CRLReasonCode int
+
+// CRL reason codes as defined in RFC 5280.
+const (
+ CRLReasonUnspecified CRLReasonCode = 0
+ CRLReasonKeyCompromise CRLReasonCode = 1
+ CRLReasonCACompromise CRLReasonCode = 2
+ CRLReasonAffiliationChanged CRLReasonCode = 3
+ CRLReasonSuperseded CRLReasonCode = 4
+ CRLReasonCessationOfOperation CRLReasonCode = 5
+ CRLReasonCertificateHold CRLReasonCode = 6
+ CRLReasonRemoveFromCRL CRLReasonCode = 8
+ CRLReasonPrivilegeWithdrawn CRLReasonCode = 9
+ CRLReasonAACompromise CRLReasonCode = 10
+)
+
+// ErrUnsupportedKey is returned when an unsupported key type is encountered.
+var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
+
+// Error is an ACME error, defined in Problem Details for HTTP APIs doc
+// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
+type Error struct {
+ // StatusCode is The HTTP status code generated by the origin server.
+ StatusCode int
+ // ProblemType is a URI reference that identifies the problem type,
+ // typically in a "urn:acme:error:xxx" form.
+ ProblemType string
+ // Detail is a human-readable explanation specific to this occurrence of the problem.
+ Detail string
+ // Header is the original server error response headers.
+ // It may be nil.
+ Header http.Header
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
+}
+
+// AuthorizationError indicates that an authorization for an identifier
+// did not succeed.
+// It contains all errors from Challenge items of the failed Authorization.
+type AuthorizationError struct {
+ // URI uniquely identifies the failed Authorization.
+ URI string
+
+ // Identifier is an AuthzID.Value of the failed Authorization.
+ Identifier string
+
+ // Errors is a collection of non-nil error values of Challenge items
+ // of the failed Authorization.
+ Errors []error
+}
+
+func (a *AuthorizationError) Error() string {
+ e := make([]string, len(a.Errors))
+ for i, err := range a.Errors {
+ e[i] = err.Error()
+ }
+ return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
+}
+
+// RateLimit reports whether err represents a rate limit error and
+// any Retry-After duration returned by the server.
+//
+// See the following for more details on rate limiting:
+// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6
+func RateLimit(err error) (time.Duration, bool) {
+ e, ok := err.(*Error)
+ if !ok {
+ return 0, false
+ }
+ // Some CA implementations may return incorrect values.
+ // Use case-insensitive comparison.
+ if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") {
+ return 0, false
+ }
+ if e.Header == nil {
+ return 0, true
+ }
+ return retryAfter(e.Header.Get("Retry-After"), 0), true
+}
+
+// Account is a user account. It is associated with a private key.
+type Account struct {
+ // URI is the account unique ID, which is also a URL used to retrieve
+ // account data from the CA.
+ URI string
+
+ // Contact is a slice of contact info used during registration.
+ Contact []string
+
+ // The terms user has agreed to.
+ // A value not matching CurrentTerms indicates that the user hasn't agreed
+ // to the actual Terms of Service of the CA.
+ AgreedTerms string
+
+ // Actual terms of a CA.
+ CurrentTerms string
+
+ // Authz is the authorization URL used to initiate a new authz flow.
+ Authz string
+
+ // Authorizations is a URI from which a list of authorizations
+ // granted to this account can be fetched via a GET request.
+ Authorizations string
+
+ // Certificates is a URI from which a list of certificates
+ // issued for this account can be fetched via a GET request.
+ Certificates string
+}
+
+// Directory is ACME server discovery data.
+type Directory struct {
+ // RegURL is an account endpoint URL, allowing for creating new
+ // and modifying existing accounts.
+ RegURL string
+
+ // AuthzURL is used to initiate Identifier Authorization flow.
+ AuthzURL string
+
+ // CertURL is a new certificate issuance endpoint URL.
+ CertURL string
+
+ // RevokeURL is used to initiate a certificate revocation flow.
+ RevokeURL string
+
+ // Term is a URI identifying the current terms of service.
+ Terms string
+
+ // Website is an HTTP or HTTPS URL locating a website
+ // providing more information about the ACME server.
+ Website string
+
+ // CAA consists of lowercase hostname elements, which the ACME server
+ // recognises as referring to itself for the purposes of CAA record validation
+ // as defined in RFC6844.
+ CAA []string
+}
+
+// Challenge encodes a returned CA challenge.
+// Its Error field may be non-nil if the challenge is part of an Authorization
+// with StatusInvalid.
+type Challenge struct {
+ // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
+ Type string
+
+ // URI is where a challenge response can be posted to.
+ URI string
+
+ // Token is a random value that uniquely identifies the challenge.
+ Token string
+
+ // Status identifies the status of this challenge.
+ Status string
+
+ // Error indicates the reason for an authorization failure
+ // when this challenge was used.
+ // The type of a non-nil value is *Error.
+ Error error
+}
+
+// Authorization encodes an authorization response.
+type Authorization struct {
+ // URI uniquely identifies a authorization.
+ URI string
+
+ // Status identifies the status of an authorization.
+ Status string
+
+ // Identifier is what the account is authorized to represent.
+ Identifier AuthzID
+
+ // Challenges that the client needs to fulfill in order to prove possession
+ // of the identifier (for pending authorizations).
+ // For final authorizations, the challenges that were used.
+ Challenges []*Challenge
+
+ // A collection of sets of challenges, each of which would be sufficient
+ // to prove possession of the identifier.
+ // Clients must complete a set of challenges that covers at least one set.
+ // Challenges are identified by their indices in the challenges array.
+ // If this field is empty, the client needs to complete all challenges.
+ Combinations [][]int
+}
+
+// AuthzID is an identifier that an account is authorized to represent.
+type AuthzID struct {
+ Type string // The type of identifier, e.g. "dns".
+ Value string // The identifier itself, e.g. "example.org".
+}
+
+// wireAuthz is ACME JSON representation of Authorization objects.
+type wireAuthz struct {
+ Status string
+ Challenges []wireChallenge
+ Combinations [][]int
+ Identifier struct {
+ Type string
+ Value string
+ }
+}
+
+func (z *wireAuthz) authorization(uri string) *Authorization {
+ a := &Authorization{
+ URI: uri,
+ Status: z.Status,
+ Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
+ Combinations: z.Combinations, // shallow copy
+ Challenges: make([]*Challenge, len(z.Challenges)),
+ }
+ for i, v := range z.Challenges {
+ a.Challenges[i] = v.challenge()
+ }
+ return a
+}
+
+func (z *wireAuthz) error(uri string) *AuthorizationError {
+ err := &AuthorizationError{
+ URI: uri,
+ Identifier: z.Identifier.Value,
+ }
+ for _, raw := range z.Challenges {
+ if raw.Error != nil {
+ err.Errors = append(err.Errors, raw.Error.error(nil))
+ }
+ }
+ return err
+}
+
+// wireChallenge is ACME JSON challenge representation.
+type wireChallenge struct {
+ URI string `json:"uri"`
+ Type string
+ Token string
+ Status string
+ Error *wireError
+}
+
+func (c *wireChallenge) challenge() *Challenge {
+ v := &Challenge{
+ URI: c.URI,
+ Type: c.Type,
+ Token: c.Token,
+ Status: c.Status,
+ }
+ if v.Status == "" {
+ v.Status = StatusPending
+ }
+ if c.Error != nil {
+ v.Error = c.Error.error(nil)
+ }
+ return v
+}
+
+// wireError is a subset of fields of the Problem Details object
+// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
+type wireError struct {
+ Status int
+ Type string
+ Detail string
+}
+
+func (e *wireError) error(h http.Header) *Error {
+ return &Error{
+ StatusCode: e.Status,
+ ProblemType: e.Type,
+ Detail: e.Detail,
+ Header: h,
+ }
+}
+
+// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for
+// customizing a temporary certificate for TLS-SNI challenges.
+type CertOption interface {
+ privateCertOpt()
+}
+
+// WithKey creates an option holding a private/public key pair.
+// The private part signs a certificate, and the public part represents the signee.
+func WithKey(key crypto.Signer) CertOption {
+ return &certOptKey{key}
+}
+
+type certOptKey struct {
+ key crypto.Signer
+}
+
+func (*certOptKey) privateCertOpt() {}
+
+// WithTemplate creates an option for specifying a certificate template.
+// See x509.CreateCertificate for template usage details.
+//
+// In TLSSNIxChallengeCert methods, the template is also used as parent,
+// resulting in a self-signed certificate.
+// The DNSNames field of t is always overwritten for tls-sni challenge certs.
+func WithTemplate(t *x509.Certificate) CertOption {
+ return (*certOptTemplate)(t)
+}
+
+type certOptTemplate x509.Certificate
+
+func (*certOptTemplate) privateCertOpt() {}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
new file mode 100644
index 0000000..18379a9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
@@ -0,0 +1,951 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package terminal
+
+import (
+ "bytes"
+ "io"
+ "sync"
+ "unicode/utf8"
+)
+
+// EscapeCodes contains escape sequences that can be written to the terminal in
+// order to achieve different styles of text.
+type EscapeCodes struct {
+ // Foreground colors
+ Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
+
+ // Reset all attributes
+ Reset []byte
+}
+
+var vt100EscapeCodes = EscapeCodes{
+ Black: []byte{keyEscape, '[', '3', '0', 'm'},
+ Red: []byte{keyEscape, '[', '3', '1', 'm'},
+ Green: []byte{keyEscape, '[', '3', '2', 'm'},
+ Yellow: []byte{keyEscape, '[', '3', '3', 'm'},
+ Blue: []byte{keyEscape, '[', '3', '4', 'm'},
+ Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
+ Cyan: []byte{keyEscape, '[', '3', '6', 'm'},
+ White: []byte{keyEscape, '[', '3', '7', 'm'},
+
+ Reset: []byte{keyEscape, '[', '0', 'm'},
+}
+
+// Terminal contains the state for running a VT100 terminal that is capable of
+// reading lines of input.
+type Terminal struct {
+ // AutoCompleteCallback, if non-null, is called for each keypress with
+ // the full input line and the current position of the cursor (in
+ // bytes, as an index into |line|). If it returns ok=false, the key
+ // press is processed normally. Otherwise it returns a replacement line
+ // and the new cursor position.
+ AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)
+
+ // Escape contains a pointer to the escape codes for this terminal.
+ // It's always a valid pointer, although the escape codes themselves
+ // may be empty if the terminal doesn't support them.
+ Escape *EscapeCodes
+
+ // lock protects the terminal and the state in this object from
+ // concurrent processing of a key press and a Write() call.
+ lock sync.Mutex
+
+ c io.ReadWriter
+ prompt []rune
+
+ // line is the current line being entered.
+ line []rune
+ // pos is the logical position of the cursor in line
+ pos int
+ // echo is true if local echo is enabled
+ echo bool
+ // pasteActive is true iff there is a bracketed paste operation in
+ // progress.
+ pasteActive bool
+
+ // cursorX contains the current X value of the cursor where the left
+ // edge is 0. cursorY contains the row number where the first row of
+ // the current line is 0.
+ cursorX, cursorY int
+ // maxLine is the greatest value of cursorY so far.
+ maxLine int
+
+ termWidth, termHeight int
+
+ // outBuf contains the terminal data to be sent.
+ outBuf []byte
+ // remainder contains the remainder of any partial key sequences after
+ // a read. It aliases into inBuf.
+ remainder []byte
+ inBuf [256]byte
+
+ // history contains previously entered commands so that they can be
+ // accessed with the up and down keys.
+ history stRingBuffer
+ // historyIndex stores the currently accessed history entry, where zero
+ // means the immediately previous entry.
+ historyIndex int
+ // When navigating up and down the history it's possible to return to
+ // the incomplete, initial line. That value is stored in
+ // historyPending.
+ historyPending string
+}
+
+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
+// a local terminal, that terminal must first have been put into raw mode.
+// prompt is a string that is written at the start of each input line (i.e.
+// "> ").
+func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
+ return &Terminal{
+ Escape: &vt100EscapeCodes,
+ c: c,
+ prompt: []rune(prompt),
+ termWidth: 80,
+ termHeight: 24,
+ echo: true,
+ historyIndex: -1,
+ }
+}
+
+const (
+ keyCtrlD = 4
+ keyCtrlU = 21
+ keyEnter = '\r'
+ keyEscape = 27
+ keyBackspace = 127
+ keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
+ keyUp
+ keyDown
+ keyLeft
+ keyRight
+ keyAltLeft
+ keyAltRight
+ keyHome
+ keyEnd
+ keyDeleteWord
+ keyDeleteLine
+ keyClearScreen
+ keyPasteStart
+ keyPasteEnd
+)
+
+var (
+ crlf = []byte{'\r', '\n'}
+ pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
+ pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
+)
+
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
+// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
+func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
+ if len(b) == 0 {
+ return utf8.RuneError, nil
+ }
+
+ if !pasteActive {
+ switch b[0] {
+ case 1: // ^A
+ return keyHome, b[1:]
+ case 5: // ^E
+ return keyEnd, b[1:]
+ case 8: // ^H
+ return keyBackspace, b[1:]
+ case 11: // ^K
+ return keyDeleteLine, b[1:]
+ case 12: // ^L
+ return keyClearScreen, b[1:]
+ case 23: // ^W
+ return keyDeleteWord, b[1:]
+ }
+ }
+
+ if b[0] != keyEscape {
+ if !utf8.FullRune(b) {
+ return utf8.RuneError, b
+ }
+ r, l := utf8.DecodeRune(b)
+ return r, b[l:]
+ }
+
+ if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
+ switch b[2] {
+ case 'A':
+ return keyUp, b[3:]
+ case 'B':
+ return keyDown, b[3:]
+ case 'C':
+ return keyRight, b[3:]
+ case 'D':
+ return keyLeft, b[3:]
+ case 'H':
+ return keyHome, b[3:]
+ case 'F':
+ return keyEnd, b[3:]
+ }
+ }
+
+ if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
+ switch b[5] {
+ case 'C':
+ return keyAltRight, b[6:]
+ case 'D':
+ return keyAltLeft, b[6:]
+ }
+ }
+
+ if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) {
+ return keyPasteStart, b[6:]
+ }
+
+ if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) {
+ return keyPasteEnd, b[6:]
+ }
+
+ // If we get here then we have a key that we don't recognise, or a
+ // partial sequence. It's not clear how one should find the end of a
+ // sequence without knowing them all, but it seems that [a-zA-Z~] only
+ // appears at the end of a sequence.
+ for i, c := range b[0:] {
+ if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' {
+ return keyUnknown, b[i+1:]
+ }
+ }
+
+ return utf8.RuneError, b
+}
+
+// queue appends data to the end of t.outBuf
+func (t *Terminal) queue(data []rune) {
+ t.outBuf = append(t.outBuf, []byte(string(data))...)
+}
+
+var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'}
+var space = []rune{' '}
+
+func isPrintable(key rune) bool {
+ isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
+ return key >= 32 && !isInSurrogateArea
+}
+
+// moveCursorToPos appends data to t.outBuf which will move the cursor to the
+// given, logical position in the text.
+func (t *Terminal) moveCursorToPos(pos int) {
+ if !t.echo {
+ return
+ }
+
+ x := visualLength(t.prompt) + pos
+ y := x / t.termWidth
+ x = x % t.termWidth
+
+ up := 0
+ if y < t.cursorY {
+ up = t.cursorY - y
+ }
+
+ down := 0
+ if y > t.cursorY {
+ down = y - t.cursorY
+ }
+
+ left := 0
+ if x < t.cursorX {
+ left = t.cursorX - x
+ }
+
+ right := 0
+ if x > t.cursorX {
+ right = x - t.cursorX
+ }
+
+ t.cursorX = x
+ t.cursorY = y
+ t.move(up, down, left, right)
+}
+
+func (t *Terminal) move(up, down, left, right int) {
+ movement := make([]rune, 3*(up+down+left+right))
+ m := movement
+ for i := 0; i < up; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'A'
+ m = m[3:]
+ }
+ for i := 0; i < down; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'B'
+ m = m[3:]
+ }
+ for i := 0; i < left; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'D'
+ m = m[3:]
+ }
+ for i := 0; i < right; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'C'
+ m = m[3:]
+ }
+
+ t.queue(movement)
+}
+
+func (t *Terminal) clearLineToRight() {
+ op := []rune{keyEscape, '[', 'K'}
+ t.queue(op)
+}
+
+const maxLineLength = 4096
+
+func (t *Terminal) setLine(newLine []rune, newPos int) {
+ if t.echo {
+ t.moveCursorToPos(0)
+ t.writeLine(newLine)
+ for i := len(newLine); i < len(t.line); i++ {
+ t.writeLine(space)
+ }
+ t.moveCursorToPos(newPos)
+ }
+ t.line = newLine
+ t.pos = newPos
+}
+
+func (t *Terminal) advanceCursor(places int) {
+ t.cursorX += places
+ t.cursorY += t.cursorX / t.termWidth
+ if t.cursorY > t.maxLine {
+ t.maxLine = t.cursorY
+ }
+ t.cursorX = t.cursorX % t.termWidth
+
+ if places > 0 && t.cursorX == 0 {
+ // Normally terminals will advance the current position
+ // when writing a character. But that doesn't happen
+ // for the last character in a line. However, when
+ // writing a character (except a new line) that causes
+ // a line wrap, the position will be advanced two
+ // places.
+ //
+ // So, if we are stopping at the end of a line, we
+ // need to write a newline so that our cursor can be
+ // advanced to the next line.
+ t.outBuf = append(t.outBuf, '\r', '\n')
+ }
+}
+
+func (t *Terminal) eraseNPreviousChars(n int) {
+ if n == 0 {
+ return
+ }
+
+ if t.pos < n {
+ n = t.pos
+ }
+ t.pos -= n
+ t.moveCursorToPos(t.pos)
+
+ copy(t.line[t.pos:], t.line[n+t.pos:])
+ t.line = t.line[:len(t.line)-n]
+ if t.echo {
+ t.writeLine(t.line[t.pos:])
+ for i := 0; i < n; i++ {
+ t.queue(space)
+ }
+ t.advanceCursor(n)
+ t.moveCursorToPos(t.pos)
+ }
+}
+
+// countToLeftWord returns then number of characters from the cursor to the
+// start of the previous word.
+func (t *Terminal) countToLeftWord() int {
+ if t.pos == 0 {
+ return 0
+ }
+
+ pos := t.pos - 1
+ for pos > 0 {
+ if t.line[pos] != ' ' {
+ break
+ }
+ pos--
+ }
+ for pos > 0 {
+ if t.line[pos] == ' ' {
+ pos++
+ break
+ }
+ pos--
+ }
+
+ return t.pos - pos
+}
+
+// countToRightWord returns then number of characters from the cursor to the
+// start of the next word.
+func (t *Terminal) countToRightWord() int {
+ pos := t.pos
+ for pos < len(t.line) {
+ if t.line[pos] == ' ' {
+ break
+ }
+ pos++
+ }
+ for pos < len(t.line) {
+ if t.line[pos] != ' ' {
+ break
+ }
+ pos++
+ }
+ return pos - t.pos
+}
+
+// visualLength returns the number of visible glyphs in s.
+func visualLength(runes []rune) int {
+ inEscapeSeq := false
+ length := 0
+
+ for _, r := range runes {
+ switch {
+ case inEscapeSeq:
+ if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
+ inEscapeSeq = false
+ }
+ case r == '\x1b':
+ inEscapeSeq = true
+ default:
+ length++
+ }
+ }
+
+ return length
+}
+
+// handleKey processes the given key and, optionally, returns a line of text
+// that the user has entered.
+func (t *Terminal) handleKey(key rune) (line string, ok bool) {
+ if t.pasteActive && key != keyEnter {
+ t.addKeyToLine(key)
+ return
+ }
+
+ switch key {
+ case keyBackspace:
+ if t.pos == 0 {
+ return
+ }
+ t.eraseNPreviousChars(1)
+ case keyAltLeft:
+ // move left by a word.
+ t.pos -= t.countToLeftWord()
+ t.moveCursorToPos(t.pos)
+ case keyAltRight:
+ // move right by a word.
+ t.pos += t.countToRightWord()
+ t.moveCursorToPos(t.pos)
+ case keyLeft:
+ if t.pos == 0 {
+ return
+ }
+ t.pos--
+ t.moveCursorToPos(t.pos)
+ case keyRight:
+ if t.pos == len(t.line) {
+ return
+ }
+ t.pos++
+ t.moveCursorToPos(t.pos)
+ case keyHome:
+ if t.pos == 0 {
+ return
+ }
+ t.pos = 0
+ t.moveCursorToPos(t.pos)
+ case keyEnd:
+ if t.pos == len(t.line) {
+ return
+ }
+ t.pos = len(t.line)
+ t.moveCursorToPos(t.pos)
+ case keyUp:
+ entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1)
+ if !ok {
+ return "", false
+ }
+ if t.historyIndex == -1 {
+ t.historyPending = string(t.line)
+ }
+ t.historyIndex++
+ runes := []rune(entry)
+ t.setLine(runes, len(runes))
+ case keyDown:
+ switch t.historyIndex {
+ case -1:
+ return
+ case 0:
+ runes := []rune(t.historyPending)
+ t.setLine(runes, len(runes))
+ t.historyIndex--
+ default:
+ entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1)
+ if ok {
+ t.historyIndex--
+ runes := []rune(entry)
+ t.setLine(runes, len(runes))
+ }
+ }
+ case keyEnter:
+ t.moveCursorToPos(len(t.line))
+ t.queue([]rune("\r\n"))
+ line = string(t.line)
+ ok = true
+ t.line = t.line[:0]
+ t.pos = 0
+ t.cursorX = 0
+ t.cursorY = 0
+ t.maxLine = 0
+ case keyDeleteWord:
+ // Delete zero or more spaces and then one or more characters.
+ t.eraseNPreviousChars(t.countToLeftWord())
+ case keyDeleteLine:
+ // Delete everything from the current cursor position to the
+ // end of line.
+ for i := t.pos; i < len(t.line); i++ {
+ t.queue(space)
+ t.advanceCursor(1)
+ }
+ t.line = t.line[:t.pos]
+ t.moveCursorToPos(t.pos)
+ case keyCtrlD:
+ // Erase the character under the current position.
+ // The EOF case when the line is empty is handled in
+ // readLine().
+ if t.pos < len(t.line) {
+ t.pos++
+ t.eraseNPreviousChars(1)
+ }
+ case keyCtrlU:
+ t.eraseNPreviousChars(t.pos)
+ case keyClearScreen:
+ // Erases the screen and moves the cursor to the home position.
+ t.queue([]rune("\x1b[2J\x1b[H"))
+ t.queue(t.prompt)
+ t.cursorX, t.cursorY = 0, 0
+ t.advanceCursor(visualLength(t.prompt))
+ t.setLine(t.line, t.pos)
+ default:
+ if t.AutoCompleteCallback != nil {
+ prefix := string(t.line[:t.pos])
+ suffix := string(t.line[t.pos:])
+
+ t.lock.Unlock()
+ newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key)
+ t.lock.Lock()
+
+ if completeOk {
+ t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos]))
+ return
+ }
+ }
+ if !isPrintable(key) {
+ return
+ }
+ if len(t.line) == maxLineLength {
+ return
+ }
+ t.addKeyToLine(key)
+ }
+ return
+}
+
+// addKeyToLine inserts the given key at the current position in the current
+// line.
+func (t *Terminal) addKeyToLine(key rune) {
+ if len(t.line) == cap(t.line) {
+ newLine := make([]rune, len(t.line), 2*(1+len(t.line)))
+ copy(newLine, t.line)
+ t.line = newLine
+ }
+ t.line = t.line[:len(t.line)+1]
+ copy(t.line[t.pos+1:], t.line[t.pos:])
+ t.line[t.pos] = key
+ if t.echo {
+ t.writeLine(t.line[t.pos:])
+ }
+ t.pos++
+ t.moveCursorToPos(t.pos)
+}
+
+func (t *Terminal) writeLine(line []rune) {
+ for len(line) != 0 {
+ remainingOnLine := t.termWidth - t.cursorX
+ todo := len(line)
+ if todo > remainingOnLine {
+ todo = remainingOnLine
+ }
+ t.queue(line[:todo])
+ t.advanceCursor(visualLength(line[:todo]))
+ line = line[todo:]
+ }
+}
+
+// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
+func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
+ for len(buf) > 0 {
+ i := bytes.IndexByte(buf, '\n')
+ todo := len(buf)
+ if i >= 0 {
+ todo = i
+ }
+
+ var nn int
+ nn, err = w.Write(buf[:todo])
+ n += nn
+ if err != nil {
+ return n, err
+ }
+ buf = buf[todo:]
+
+ if i >= 0 {
+ if _, err = w.Write(crlf); err != nil {
+ return n, err
+ }
+ n += 1
+ buf = buf[1:]
+ }
+ }
+
+ return n, nil
+}
+
+func (t *Terminal) Write(buf []byte) (n int, err error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ if t.cursorX == 0 && t.cursorY == 0 {
+ // This is the easy case: there's nothing on the screen that we
+ // have to move out of the way.
+ return writeWithCRLF(t.c, buf)
+ }
+
+ // We have a prompt and possibly user input on the screen. We
+ // have to clear it first.
+ t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
+ t.cursorX = 0
+ t.clearLineToRight()
+
+ for t.cursorY > 0 {
+ t.move(1 /* up */, 0, 0, 0)
+ t.cursorY--
+ t.clearLineToRight()
+ }
+
+ if _, err = t.c.Write(t.outBuf); err != nil {
+ return
+ }
+ t.outBuf = t.outBuf[:0]
+
+ if n, err = writeWithCRLF(t.c, buf); err != nil {
+ return
+ }
+
+ t.writeLine(t.prompt)
+ if t.echo {
+ t.writeLine(t.line)
+ }
+
+ t.moveCursorToPos(t.pos)
+
+ if _, err = t.c.Write(t.outBuf); err != nil {
+ return
+ }
+ t.outBuf = t.outBuf[:0]
+ return
+}
+
+// ReadPassword temporarily changes the prompt and reads a password, without
+// echo, from the terminal.
+func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ oldPrompt := t.prompt
+ t.prompt = []rune(prompt)
+ t.echo = false
+
+ line, err = t.readLine()
+
+ t.prompt = oldPrompt
+ t.echo = true
+
+ return
+}
+
+// ReadLine returns a line of input from the terminal.
+func (t *Terminal) ReadLine() (line string, err error) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ return t.readLine()
+}
+
+func (t *Terminal) readLine() (line string, err error) {
+ // t.lock must be held at this point
+
+ if t.cursorX == 0 && t.cursorY == 0 {
+ t.writeLine(t.prompt)
+ t.c.Write(t.outBuf)
+ t.outBuf = t.outBuf[:0]
+ }
+
+ lineIsPasted := t.pasteActive
+
+ for {
+ rest := t.remainder
+ lineOk := false
+ for !lineOk {
+ var key rune
+ key, rest = bytesToKey(rest, t.pasteActive)
+ if key == utf8.RuneError {
+ break
+ }
+ if !t.pasteActive {
+ if key == keyCtrlD {
+ if len(t.line) == 0 {
+ return "", io.EOF
+ }
+ }
+ if key == keyPasteStart {
+ t.pasteActive = true
+ if len(t.line) == 0 {
+ lineIsPasted = true
+ }
+ continue
+ }
+ } else if key == keyPasteEnd {
+ t.pasteActive = false
+ continue
+ }
+ if !t.pasteActive {
+ lineIsPasted = false
+ }
+ line, lineOk = t.handleKey(key)
+ }
+ if len(rest) > 0 {
+ n := copy(t.inBuf[:], rest)
+ t.remainder = t.inBuf[:n]
+ } else {
+ t.remainder = nil
+ }
+ t.c.Write(t.outBuf)
+ t.outBuf = t.outBuf[:0]
+ if lineOk {
+ if t.echo {
+ t.historyIndex = -1
+ t.history.Add(line)
+ }
+ if lineIsPasted {
+ err = ErrPasteIndicator
+ }
+ return
+ }
+
+ // t.remainder is a slice at the beginning of t.inBuf
+ // containing a partial key sequence
+ readBuf := t.inBuf[len(t.remainder):]
+ var n int
+
+ t.lock.Unlock()
+ n, err = t.c.Read(readBuf)
+ t.lock.Lock()
+
+ if err != nil {
+ return
+ }
+
+ t.remainder = t.inBuf[:n+len(t.remainder)]
+ }
+}
+
+// SetPrompt sets the prompt to be used when reading subsequent lines.
+func (t *Terminal) SetPrompt(prompt string) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ t.prompt = []rune(prompt)
+}
+
+func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
+ // Move cursor to column zero at the start of the line.
+ t.move(t.cursorY, 0, t.cursorX, 0)
+ t.cursorX, t.cursorY = 0, 0
+ t.clearLineToRight()
+ for t.cursorY < numPrevLines {
+ // Move down a line
+ t.move(0, 1, 0, 0)
+ t.cursorY++
+ t.clearLineToRight()
+ }
+ // Move back to beginning.
+ t.move(t.cursorY, 0, 0, 0)
+ t.cursorX, t.cursorY = 0, 0
+
+ t.queue(t.prompt)
+ t.advanceCursor(visualLength(t.prompt))
+ t.writeLine(t.line)
+ t.moveCursorToPos(t.pos)
+}
+
+func (t *Terminal) SetSize(width, height int) error {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ if width == 0 {
+ width = 1
+ }
+
+ oldWidth := t.termWidth
+ t.termWidth, t.termHeight = width, height
+
+ switch {
+ case width == oldWidth:
+ // If the width didn't change then nothing else needs to be
+ // done.
+ return nil
+ case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0:
+ // If there is nothing on current line and no prompt printed,
+ // just do nothing
+ return nil
+ case width < oldWidth:
+ // Some terminals (e.g. xterm) will truncate lines that were
+ // too long when shinking. Others, (e.g. gnome-terminal) will
+ // attempt to wrap them. For the former, repainting t.maxLine
+ // works great, but that behaviour goes badly wrong in the case
+ // of the latter because they have doubled every full line.
+
+ // We assume that we are working on a terminal that wraps lines
+ // and adjust the cursor position based on every previous line
+ // wrapping and turning into two. This causes the prompt on
+ // xterms to move upwards, which isn't great, but it avoids a
+ // huge mess with gnome-terminal.
+ if t.cursorX >= t.termWidth {
+ t.cursorX = t.termWidth - 1
+ }
+ t.cursorY *= 2
+ t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2)
+ case width > oldWidth:
+ // If the terminal expands then our position calculations will
+ // be wrong in the future because we think the cursor is
+ // |t.pos| chars into the string, but there will be a gap at
+ // the end of any wrapped line.
+ //
+ // But the position will actually be correct until we move, so
+ // we can move back to the beginning and repaint everything.
+ t.clearAndRepaintLinePlusNPrevious(t.maxLine)
+ }
+
+ _, err := t.c.Write(t.outBuf)
+ t.outBuf = t.outBuf[:0]
+ return err
+}
+
+type pasteIndicatorError struct{}
+
+func (pasteIndicatorError) Error() string {
+ return "terminal: ErrPasteIndicator not correctly handled"
+}
+
+// ErrPasteIndicator may be returned from ReadLine as the error, in addition
+// to valid line data. It indicates that bracketed paste mode is enabled and
+// that the returned line consists only of pasted data. Programs may wish to
+// interpret pasted data more literally than typed data.
+var ErrPasteIndicator = pasteIndicatorError{}
+
+// SetBracketedPasteMode requests that the terminal bracket paste operations
+// with markers. Not all terminals support this but, if it is supported, then
+// enabling this mode will stop any autocomplete callback from running due to
+// pastes. Additionally, any lines that are completely pasted will be returned
+// from ReadLine with the error set to ErrPasteIndicator.
+func (t *Terminal) SetBracketedPasteMode(on bool) {
+ if on {
+ io.WriteString(t.c, "\x1b[?2004h")
+ } else {
+ io.WriteString(t.c, "\x1b[?2004l")
+ }
+}
+
+// stRingBuffer is a ring buffer of strings.
+type stRingBuffer struct {
+ // entries contains max elements.
+ entries []string
+ max int
+ // head contains the index of the element most recently added to the ring.
+ head int
+ // size contains the number of elements in the ring.
+ size int
+}
+
+func (s *stRingBuffer) Add(a string) {
+ if s.entries == nil {
+ const defaultNumEntries = 100
+ s.entries = make([]string, defaultNumEntries)
+ s.max = defaultNumEntries
+ }
+
+ s.head = (s.head + 1) % s.max
+ s.entries[s.head] = a
+ if s.size < s.max {
+ s.size++
+ }
+}
+
+// NthPreviousEntry returns the value passed to the nth previous call to Add.
+// If n is zero then the immediately prior value is returned, if one, then the
+// next most recent, and so on. If such an element doesn't exist then ok is
+// false.
+func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
+ if n >= s.size {
+ return "", false
+ }
+ index := s.head - n
+ if index < 0 {
+ index += s.max
+ }
+ return s.entries[index], true
+}
+
+// readPasswordLine reads from reader until it finds \n or io.EOF.
+// The slice returned does not include the \n.
+// readPasswordLine also ignores any \r it finds.
+func readPasswordLine(reader io.Reader) ([]byte, error) {
+ var buf [1]byte
+ var ret []byte
+
+ for {
+ n, err := reader.Read(buf[:])
+ if n > 0 {
+ switch buf[0] {
+ case '\n':
+ return ret, nil
+ case '\r':
+ // remove \r from passwords on Windows
+ default:
+ ret = append(ret, buf[0])
+ }
+ continue
+ }
+ if err != nil {
+ if err == io.EOF && len(ret) > 0 {
+ return ret, nil
+ }
+ return ret, err
+ }
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go
new file mode 100644
index 0000000..02dad48
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util.go
@@ -0,0 +1,116 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// oldState, err := terminal.MakeRaw(0)
+// if err != nil {
+// panic(err)
+// }
+// defer terminal.Restore(0, oldState)
+package terminal // import "golang.org/x/crypto/ssh/terminal"
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+// State contains the state of a terminal.
+type State struct {
+ termios unix.Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ return err == nil
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
+ return nil, err
+ }
+
+ oldState := State{termios: *termios}
+
+ // This attempts to replicate the behaviour documented for cfmakeraw in
+ // the termios(3) manpage.
+ termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
+ termios.Oflag &^= unix.OPOST
+ termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
+ termios.Cflag &^= unix.CSIZE | unix.PARENB
+ termios.Cflag |= unix.CS8
+ termios.Cc[unix.VMIN] = 1
+ termios.Cc[unix.VTIME] = 0
+ if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
+ return nil, err
+ }
+
+ return &oldState, nil
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
+ return nil, err
+ }
+
+ return &State{termios: *termios}, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+ return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+ if err != nil {
+ return -1, -1, err
+ }
+ return int(ws.Col), int(ws.Row), nil
+}
+
+// passwordReader is an io.Reader that reads from a specific file descriptor.
+type passwordReader int
+
+func (r passwordReader) Read(buf []byte) (int, error) {
+ return unix.Read(int(r), buf)
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ if err != nil {
+ return nil, err
+ }
+
+ newState := *termios
+ newState.Lflag &^= unix.ECHO
+ newState.Lflag |= unix.ICANON | unix.ISIG
+ newState.Iflag |= unix.ICRNL
+ if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
+ return nil, err
+ }
+
+ defer func() {
+ unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
+ }()
+
+ return readPasswordLine(passwordReader(fd))
+}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
new file mode 100644
index 0000000..cb23a59
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
@@ -0,0 +1,12 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package terminal
+
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TIOCGETA
+const ioctlWriteTermios = unix.TIOCSETA
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
new file mode 100644
index 0000000..5fadfe8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package terminal
+
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TCGETS
+const ioctlWriteTermios = unix.TCSETS
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
new file mode 100644
index 0000000..799f049
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
@@ -0,0 +1,58 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// oldState, err := terminal.MakeRaw(0)
+// if err != nil {
+// panic(err)
+// }
+// defer terminal.Restore(0, oldState)
+package terminal
+
+import (
+ "fmt"
+ "runtime"
+)
+
+type State struct{}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ return false
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+ return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+ return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
new file mode 100644
index 0000000..a2e1b57
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
@@ -0,0 +1,128 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package terminal // import "golang.org/x/crypto/ssh/terminal"
+
+import (
+ "golang.org/x/sys/unix"
+ "io"
+ "syscall"
+)
+
+// State contains the state of a terminal.
+type State struct {
+ state *unix.Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ _, err := unix.IoctlGetTermio(fd, unix.TCGETA)
+ return err == nil
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
+ val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+ oldState := *val
+
+ newState := oldState
+ newState.Lflag &^= syscall.ECHO
+ newState.Lflag |= syscall.ICANON | syscall.ISIG
+ newState.Iflag |= syscall.ICRNL
+ err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
+ if err != nil {
+ return nil, err
+ }
+
+ defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
+
+ var buf [16]byte
+ var ret []byte
+ for {
+ n, err := syscall.Read(fd, buf[:])
+ if err != nil {
+ return nil, err
+ }
+ if n == 0 {
+ if len(ret) == 0 {
+ return nil, io.EOF
+ }
+ break
+ }
+ if buf[n-1] == '\n' {
+ n--
+ }
+ ret = append(ret, buf[:n]...)
+ if n < len(buf) {
+ break
+ }
+ }
+
+ return ret, nil
+}
+
+// MakeRaw puts the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+// see http://cr.illumos.org/~webrev/andy_js/1060/
+func MakeRaw(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+ oldTermios := *oldTermiosPtr
+
+ newTermios := oldTermios
+ newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
+ newTermios.Oflag &^= syscall.OPOST
+ newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
+ newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
+ newTermios.Cflag |= syscall.CS8
+ newTermios.Cc[unix.VMIN] = 1
+ newTermios.Cc[unix.VTIME] = 0
+
+ if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, oldState *State) error {
+ return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+ if err != nil {
+ return nil, err
+ }
+
+ return &State{
+ state: oldTermiosPtr,
+ }, nil
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
+ if err != nil {
+ return 0, 0, err
+ }
+ return int(ws.Col), int(ws.Row), nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
new file mode 100644
index 0000000..60979cc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
@@ -0,0 +1,102 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// oldState, err := terminal.MakeRaw(0)
+// if err != nil {
+// panic(err)
+// }
+// defer terminal.Restore(0, oldState)
+package terminal
+
+import (
+ "golang.org/x/sys/windows"
+)
+
+type State struct {
+ mode uint32
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ var st uint32
+ err := windows.GetConsoleMode(windows.Handle(fd), &st)
+ return err == nil
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+ var st uint32
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
+ }
+ raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
+ if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
+ return nil, err
+ }
+ return &State{st}, nil
+}
+
+// GetState returns the current state of a terminal which may be useful to
+// restore the terminal after a signal.
+func GetState(fd int) (*State, error) {
+ var st uint32
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
+ }
+ return &State{st}, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+ return windows.SetConsoleMode(windows.Handle(fd), state.mode)
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+ var info windows.ConsoleScreenBufferInfo
+ if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
+ return 0, 0, err
+ }
+ return int(info.Size.X), int(info.Size.Y), nil
+}
+
+// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
+type passwordReader int
+
+func (r passwordReader) Read(buf []byte) (int, error) {
+ return windows.Read(windows.Handle(r), buf)
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+ var st uint32
+ if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
+ return nil, err
+ }
+ old := st
+
+ st &^= (windows.ENABLE_ECHO_INPUT)
+ st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
+ if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
+ return nil, err
+ }
+
+ defer func() {
+ windows.SetConsoleMode(windows.Handle(fd), old)
+ }()
+
+ return readPasswordLine(passwordReader(fd))
+}
diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/net/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/net/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go
new file mode 100644
index 0000000..a3c021d
--- /dev/null
+++ b/vendor/golang.org/x/net/context/context.go
@@ -0,0 +1,56 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package context defines the Context type, which carries deadlines,
+// cancelation signals, and other request-scoped values across API boundaries
+// and between processes.
+// As of Go 1.7 this package is available in the standard library under the
+// name context. https://golang.org/pkg/context.
+//
+// Incoming requests to a server should create a Context, and outgoing calls to
+// servers should accept a Context. The chain of function calls between must
+// propagate the Context, optionally replacing it with a modified copy created
+// using WithDeadline, WithTimeout, WithCancel, or WithValue.
+//
+// Programs that use Contexts should follow these rules to keep interfaces
+// consistent across packages and enable static analysis tools to check context
+// propagation:
+//
+// Do not store Contexts inside a struct type; instead, pass a Context
+// explicitly to each function that needs it. The Context should be the first
+// parameter, typically named ctx:
+//
+// func DoSomething(ctx context.Context, arg Arg) error {
+// // ... use ctx ...
+// }
+//
+// Do not pass a nil Context, even if a function permits it. Pass context.TODO
+// if you are unsure about which Context to use.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+//
+// The same Context may be passed to functions running in different goroutines;
+// Contexts are safe for simultaneous use by multiple goroutines.
+//
+// See http://blog.golang.org/context for example code for a server that uses
+// Contexts.
+package context // import "golang.org/x/net/context"
+
+// Background returns a non-nil, empty Context. It is never canceled, has no
+// values, and has no deadline. It is typically used by the main function,
+// initialization, and tests, and as the top-level Context for incoming
+// requests.
+func Background() Context {
+ return background
+}
+
+// TODO returns a non-nil, empty Context. Code should use context.TODO when
+// it's unclear which Context to use or it is not yet available (because the
+// surrounding function has not yet been extended to accept a Context
+// parameter). TODO is recognized by static analysis tools that determine
+// whether Contexts are propagated correctly in a program.
+func TODO() Context {
+ return todo
+}
diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
new file mode 100644
index 0000000..606cf1f
--- /dev/null
+++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
@@ -0,0 +1,74 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+// Do sends an HTTP request with the provided http.Client and returns
+// an HTTP response.
+//
+// If the client is nil, http.DefaultClient is used.
+//
+// The provided ctx must be non-nil. If it is canceled or times out,
+// ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+ resp, err := client.Do(req.WithContext(ctx))
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ err = ctx.Err()
+ default:
+ }
+ }
+ return resp, err
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
new file mode 100644
index 0000000..926870c
--- /dev/null
+++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
@@ -0,0 +1,147 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+func nop() {}
+
+var (
+ testHookContextDoneBeforeHeaders = nop
+ testHookDoReturned = nop
+ testHookDidBodyClose = nop
+)
+
+// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
+// If the client is nil, http.DefaultClient is used.
+// If the context is canceled or times out, ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+
+ // TODO(djd): Respect any existing value of req.Cancel.
+ cancel := make(chan struct{})
+ req.Cancel = cancel
+
+ type responseAndError struct {
+ resp *http.Response
+ err error
+ }
+ result := make(chan responseAndError, 1)
+
+ // Make local copies of test hooks closed over by goroutines below.
+ // Prevents data races in tests.
+ testHookDoReturned := testHookDoReturned
+ testHookDidBodyClose := testHookDidBodyClose
+
+ go func() {
+ resp, err := client.Do(req)
+ testHookDoReturned()
+ result <- responseAndError{resp, err}
+ }()
+
+ var resp *http.Response
+
+ select {
+ case <-ctx.Done():
+ testHookContextDoneBeforeHeaders()
+ close(cancel)
+ // Clean up after the goroutine calling client.Do:
+ go func() {
+ if r := <-result; r.resp != nil {
+ testHookDidBodyClose()
+ r.resp.Body.Close()
+ }
+ }()
+ return nil, ctx.Err()
+ case r := <-result:
+ var err error
+ resp, err = r.resp, r.err
+ if err != nil {
+ return resp, err
+ }
+ }
+
+ c := make(chan struct{})
+ go func() {
+ select {
+ case <-ctx.Done():
+ close(cancel)
+ case <-c:
+ // The response's Body is closed.
+ }
+ }()
+ resp.Body = ¬ifyingReader{resp.Body, c}
+
+ return resp, nil
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
+
+// notifyingReader is an io.ReadCloser that closes the notify channel after
+// Close is called or a Read fails on the underlying ReadCloser.
+type notifyingReader struct {
+ io.ReadCloser
+ notify chan<- struct{}
+}
+
+func (r *notifyingReader) Read(p []byte) (int, error) {
+ n, err := r.ReadCloser.Read(p)
+ if err != nil && r.notify != nil {
+ close(r.notify)
+ r.notify = nil
+ }
+ return n, err
+}
+
+func (r *notifyingReader) Close() error {
+ err := r.ReadCloser.Close()
+ if r.notify != nil {
+ close(r.notify)
+ r.notify = nil
+ }
+ return err
+}
diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go
new file mode 100644
index 0000000..d20f52b
--- /dev/null
+++ b/vendor/golang.org/x/net/context/go17.go
@@ -0,0 +1,72 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+package context
+
+import (
+ "context" // standard library's context, as of Go 1.7
+ "time"
+)
+
+var (
+ todo = context.TODO()
+ background = context.Background()
+)
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = context.Canceled
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = context.DeadlineExceeded
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ ctx, f := context.WithCancel(parent)
+ return ctx, CancelFunc(f)
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ ctx, f := context.WithDeadline(parent, deadline)
+ return ctx, CancelFunc(f)
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return context.WithValue(parent, key, val)
+}
diff --git a/vendor/golang.org/x/net/context/go19.go b/vendor/golang.org/x/net/context/go19.go
new file mode 100644
index 0000000..d88bd1d
--- /dev/null
+++ b/vendor/golang.org/x/net/context/go19.go
@@ -0,0 +1,20 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package context
+
+import "context" // standard library's context, as of Go 1.7
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context = context.Context
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc = context.CancelFunc
diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go
new file mode 100644
index 0000000..0f35592
--- /dev/null
+++ b/vendor/golang.org/x/net/context/pre_go17.go
@@ -0,0 +1,300 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package context
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+ "time"
+)
+
+// An emptyCtx is never canceled, has no values, and has no deadline. It is not
+// struct{}, since vars of this type must have distinct addresses.
+type emptyCtx int
+
+func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
+ return
+}
+
+func (*emptyCtx) Done() <-chan struct{} {
+ return nil
+}
+
+func (*emptyCtx) Err() error {
+ return nil
+}
+
+func (*emptyCtx) Value(key interface{}) interface{} {
+ return nil
+}
+
+func (e *emptyCtx) String() string {
+ switch e {
+ case background:
+ return "context.Background"
+ case todo:
+ return "context.TODO"
+ }
+ return "unknown empty Context"
+}
+
+var (
+ background = new(emptyCtx)
+ todo = new(emptyCtx)
+)
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = errors.New("context canceled")
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = errors.New("context deadline exceeded")
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ c := newCancelCtx(parent)
+ propagateCancel(parent, c)
+ return c, func() { c.cancel(true, Canceled) }
+}
+
+// newCancelCtx returns an initialized cancelCtx.
+func newCancelCtx(parent Context) *cancelCtx {
+ return &cancelCtx{
+ Context: parent,
+ done: make(chan struct{}),
+ }
+}
+
+// propagateCancel arranges for child to be canceled when parent is.
+func propagateCancel(parent Context, child canceler) {
+ if parent.Done() == nil {
+ return // parent is never canceled
+ }
+ if p, ok := parentCancelCtx(parent); ok {
+ p.mu.Lock()
+ if p.err != nil {
+ // parent has already been canceled
+ child.cancel(false, p.err)
+ } else {
+ if p.children == nil {
+ p.children = make(map[canceler]bool)
+ }
+ p.children[child] = true
+ }
+ p.mu.Unlock()
+ } else {
+ go func() {
+ select {
+ case <-parent.Done():
+ child.cancel(false, parent.Err())
+ case <-child.Done():
+ }
+ }()
+ }
+}
+
+// parentCancelCtx follows a chain of parent references until it finds a
+// *cancelCtx. This function understands how each of the concrete types in this
+// package represents its parent.
+func parentCancelCtx(parent Context) (*cancelCtx, bool) {
+ for {
+ switch c := parent.(type) {
+ case *cancelCtx:
+ return c, true
+ case *timerCtx:
+ return c.cancelCtx, true
+ case *valueCtx:
+ parent = c.Context
+ default:
+ return nil, false
+ }
+ }
+}
+
+// removeChild removes a context from its parent.
+func removeChild(parent Context, child canceler) {
+ p, ok := parentCancelCtx(parent)
+ if !ok {
+ return
+ }
+ p.mu.Lock()
+ if p.children != nil {
+ delete(p.children, child)
+ }
+ p.mu.Unlock()
+}
+
+// A canceler is a context type that can be canceled directly. The
+// implementations are *cancelCtx and *timerCtx.
+type canceler interface {
+ cancel(removeFromParent bool, err error)
+ Done() <-chan struct{}
+}
+
+// A cancelCtx can be canceled. When canceled, it also cancels any children
+// that implement canceler.
+type cancelCtx struct {
+ Context
+
+ done chan struct{} // closed by the first cancel call.
+
+ mu sync.Mutex
+ children map[canceler]bool // set to nil by the first cancel call
+ err error // set to non-nil by the first cancel call
+}
+
+func (c *cancelCtx) Done() <-chan struct{} {
+ return c.done
+}
+
+func (c *cancelCtx) Err() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ return c.err
+}
+
+func (c *cancelCtx) String() string {
+ return fmt.Sprintf("%v.WithCancel", c.Context)
+}
+
+// cancel closes c.done, cancels each of c's children, and, if
+// removeFromParent is true, removes c from its parent's children.
+func (c *cancelCtx) cancel(removeFromParent bool, err error) {
+ if err == nil {
+ panic("context: internal error: missing cancel error")
+ }
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return // already canceled
+ }
+ c.err = err
+ close(c.done)
+ for child := range c.children {
+ // NOTE: acquiring the child's lock while holding parent's lock.
+ child.cancel(false, err)
+ }
+ c.children = nil
+ c.mu.Unlock()
+
+ if removeFromParent {
+ removeChild(c.Context, c)
+ }
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
+ // The current deadline is already sooner than the new one.
+ return WithCancel(parent)
+ }
+ c := &timerCtx{
+ cancelCtx: newCancelCtx(parent),
+ deadline: deadline,
+ }
+ propagateCancel(parent, c)
+ d := deadline.Sub(time.Now())
+ if d <= 0 {
+ c.cancel(true, DeadlineExceeded) // deadline has already passed
+ return c, func() { c.cancel(true, Canceled) }
+ }
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.err == nil {
+ c.timer = time.AfterFunc(d, func() {
+ c.cancel(true, DeadlineExceeded)
+ })
+ }
+ return c, func() { c.cancel(true, Canceled) }
+}
+
+// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
+// implement Done and Err. It implements cancel by stopping its timer then
+// delegating to cancelCtx.cancel.
+type timerCtx struct {
+ *cancelCtx
+ timer *time.Timer // Under cancelCtx.mu.
+
+ deadline time.Time
+}
+
+func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
+ return c.deadline, true
+}
+
+func (c *timerCtx) String() string {
+ return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
+}
+
+func (c *timerCtx) cancel(removeFromParent bool, err error) {
+ c.cancelCtx.cancel(false, err)
+ if removeFromParent {
+ // Remove this timerCtx from its parent cancelCtx's children.
+ removeChild(c.cancelCtx.Context, c)
+ }
+ c.mu.Lock()
+ if c.timer != nil {
+ c.timer.Stop()
+ c.timer = nil
+ }
+ c.mu.Unlock()
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return &valueCtx{parent, key, val}
+}
+
+// A valueCtx carries a key-value pair. It implements Value for that key and
+// delegates all other calls to the embedded Context.
+type valueCtx struct {
+ Context
+ key, val interface{}
+}
+
+func (c *valueCtx) String() string {
+ return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
+}
+
+func (c *valueCtx) Value(key interface{}) interface{} {
+ if c.key == key {
+ return c.val
+ }
+ return c.Context.Value(key)
+}
diff --git a/vendor/golang.org/x/net/context/pre_go19.go b/vendor/golang.org/x/net/context/pre_go19.go
new file mode 100644
index 0000000..b105f80
--- /dev/null
+++ b/vendor/golang.org/x/net/context/pre_go19.go
@@ -0,0 +1,109 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.9
+
+package context
+
+import "time"
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context interface {
+ // Deadline returns the time when work done on behalf of this context
+ // should be canceled. Deadline returns ok==false when no deadline is
+ // set. Successive calls to Deadline return the same results.
+ Deadline() (deadline time.Time, ok bool)
+
+ // Done returns a channel that's closed when work done on behalf of this
+ // context should be canceled. Done may return nil if this context can
+ // never be canceled. Successive calls to Done return the same value.
+ //
+ // WithCancel arranges for Done to be closed when cancel is called;
+ // WithDeadline arranges for Done to be closed when the deadline
+ // expires; WithTimeout arranges for Done to be closed when the timeout
+ // elapses.
+ //
+ // Done is provided for use in select statements:
+ //
+ // // Stream generates values with DoSomething and sends them to out
+ // // until DoSomething returns an error or ctx.Done is closed.
+ // func Stream(ctx context.Context, out chan<- Value) error {
+ // for {
+ // v, err := DoSomething(ctx)
+ // if err != nil {
+ // return err
+ // }
+ // select {
+ // case <-ctx.Done():
+ // return ctx.Err()
+ // case out <- v:
+ // }
+ // }
+ // }
+ //
+ // See http://blog.golang.org/pipelines for more examples of how to use
+ // a Done channel for cancelation.
+ Done() <-chan struct{}
+
+ // Err returns a non-nil error value after Done is closed. Err returns
+ // Canceled if the context was canceled or DeadlineExceeded if the
+ // context's deadline passed. No other values for Err are defined.
+ // After Done is closed, successive calls to Err return the same value.
+ Err() error
+
+ // Value returns the value associated with this context for key, or nil
+ // if no value is associated with key. Successive calls to Value with
+ // the same key returns the same result.
+ //
+ // Use context values only for request-scoped data that transits
+ // processes and API boundaries, not for passing optional parameters to
+ // functions.
+ //
+ // A key identifies a specific value in a Context. Functions that wish
+ // to store values in Context typically allocate a key in a global
+ // variable then use that key as the argument to context.WithValue and
+ // Context.Value. A key can be any type that supports equality;
+ // packages should define keys as an unexported type to avoid
+ // collisions.
+ //
+ // Packages that define a Context key should provide type-safe accessors
+ // for the values stores using that key:
+ //
+ // // Package user defines a User type that's stored in Contexts.
+ // package user
+ //
+ // import "golang.org/x/net/context"
+ //
+ // // User is the type of value stored in the Contexts.
+ // type User struct {...}
+ //
+ // // key is an unexported type for keys defined in this package.
+ // // This prevents collisions with keys defined in other packages.
+ // type key int
+ //
+ // // userKey is the key for user.User values in Contexts. It is
+ // // unexported; clients use user.NewContext and user.FromContext
+ // // instead of using this key directly.
+ // var userKey key = 0
+ //
+ // // NewContext returns a new Context that carries value u.
+ // func NewContext(ctx context.Context, u *User) context.Context {
+ // return context.WithValue(ctx, userKey, u)
+ // }
+ //
+ // // FromContext returns the User value stored in ctx, if any.
+ // func FromContext(ctx context.Context) (*User, bool) {
+ // u, ok := ctx.Value(userKey).(*User)
+ // return u, ok
+ // }
+ Value(key interface{}) interface{}
+}
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc func()
diff --git a/vendor/golang.org/x/net/http2/Dockerfile b/vendor/golang.org/x/net/http2/Dockerfile
new file mode 100644
index 0000000..53fc525
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/Dockerfile
@@ -0,0 +1,51 @@
+#
+# This Dockerfile builds a recent curl with HTTP/2 client support, using
+# a recent nghttp2 build.
+#
+# See the Makefile for how to tag it. If Docker and that image is found, the
+# Go tests use this curl binary for integration tests.
+#
+
+FROM ubuntu:trusty
+
+RUN apt-get update && \
+ apt-get upgrade -y && \
+ apt-get install -y git-core build-essential wget
+
+RUN apt-get install -y --no-install-recommends \
+ autotools-dev libtool pkg-config zlib1g-dev \
+ libcunit1-dev libssl-dev libxml2-dev libevent-dev \
+ automake autoconf
+
+# The list of packages nghttp2 recommends for h2load:
+RUN apt-get install -y --no-install-recommends make binutils \
+ autoconf automake autotools-dev \
+ libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \
+ libev-dev libevent-dev libjansson-dev libjemalloc-dev \
+ cython python3.4-dev python-setuptools
+
+# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached:
+ENV NGHTTP2_VER 895da9a
+RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git
+
+WORKDIR /root/nghttp2
+RUN git reset --hard $NGHTTP2_VER
+RUN autoreconf -i
+RUN automake
+RUN autoconf
+RUN ./configure
+RUN make
+RUN make install
+
+WORKDIR /root
+RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz
+RUN tar -zxvf curl-7.45.0.tar.gz
+WORKDIR /root/curl-7.45.0
+RUN ./configure --with-ssl --with-nghttp2=/usr/local
+RUN make
+RUN make install
+RUN ldconfig
+
+CMD ["-h"]
+ENTRYPOINT ["/usr/local/bin/curl"]
+
diff --git a/vendor/golang.org/x/net/http2/Makefile b/vendor/golang.org/x/net/http2/Makefile
new file mode 100644
index 0000000..55fd826
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/Makefile
@@ -0,0 +1,3 @@
+curlimage:
+ docker build -t gohttp2/curl .
+
diff --git a/vendor/golang.org/x/net/http2/README b/vendor/golang.org/x/net/http2/README
new file mode 100644
index 0000000..360d5aa
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/README
@@ -0,0 +1,20 @@
+This is a work-in-progress HTTP/2 implementation for Go.
+
+It will eventually live in the Go standard library and won't require
+any changes to your code to use. It will just be automatic.
+
+Status:
+
+* The server support is pretty good. A few things are missing
+ but are being worked on.
+* The client work has just started but shares a lot of code
+ is coming along much quicker.
+
+Docs are at https://godoc.org/golang.org/x/net/http2
+
+Demo test server at https://http2.golang.org/
+
+Help & bug reports welcome!
+
+Contributing: https://golang.org/doc/contribute.html
+Bugs: https://golang.org/issue/new?title=x/net/http2:+
diff --git a/vendor/golang.org/x/net/http2/ciphers.go b/vendor/golang.org/x/net/http2/ciphers.go
new file mode 100644
index 0000000..698860b
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/ciphers.go
@@ -0,0 +1,641 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt
+
+const (
+ cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
+ cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
+ cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
+ cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
+ cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
+ cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
+ // Reserved uint16 = 0x001C-1D
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
+ cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
+ cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
+ cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
+ cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
+ // Reserved uint16 = 0x0047-4F
+ // Reserved uint16 = 0x0050-58
+ // Reserved uint16 = 0x0059-5C
+ // Unassigned uint16 = 0x005D-5F
+ // Reserved uint16 = 0x0060-66
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
+ // Unassigned uint16 = 0x006E-83
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
+ cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
+ cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
+ cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
+ cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
+ cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
+ cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
+ cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
+ cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
+ cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
+ // Unassigned uint16 = 0x00C6-FE
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
+ // Unassigned uint16 = 0x01-55,*
+ cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
+ // Unassigned uint16 = 0x5601 - 0xC000
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
+ cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
+ cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
+ cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
+ cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
+ cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
+ cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
+ cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
+ cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
+ cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
+ cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
+ cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
+ cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
+ // Unassigned uint16 = 0xC0B0-FF
+ // Unassigned uint16 = 0xC1-CB,*
+ // Unassigned uint16 = 0xCC00-A7
+ cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
+ cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
+ cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
+ cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
+ cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
+ cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
+ cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
+)
+
+// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
+// References:
+// https://tools.ietf.org/html/rfc7540#appendix-A
+// Reject cipher suites from Appendix A.
+// "This list includes those cipher suites that do not
+// offer an ephemeral key exchange and those that are
+// based on the TLS null, stream or block cipher type"
+func isBadCipher(cipher uint16) bool {
+ switch cipher {
+ case cipher_TLS_NULL_WITH_NULL_NULL,
+ cipher_TLS_RSA_WITH_NULL_MD5,
+ cipher_TLS_RSA_WITH_NULL_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5,
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_RC4_128_SHA,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
+ cipher_TLS_KRB5_WITH_RC4_128_MD5,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_PSK_WITH_NULL_SHA,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_NULL_SHA256,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_NULL_SHA256,
+ cipher_TLS_PSK_WITH_NULL_SHA384,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA,
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_AES_128_CCM,
+ cipher_TLS_RSA_WITH_AES_256_CCM,
+ cipher_TLS_RSA_WITH_AES_128_CCM_8,
+ cipher_TLS_RSA_WITH_AES_256_CCM_8,
+ cipher_TLS_PSK_WITH_AES_128_CCM,
+ cipher_TLS_PSK_WITH_AES_256_CCM,
+ cipher_TLS_PSK_WITH_AES_128_CCM_8,
+ cipher_TLS_PSK_WITH_AES_256_CCM_8:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/vendor/golang.org/x/net/http2/client_conn_pool.go b/vendor/golang.org/x/net/http2/client_conn_pool.go
new file mode 100644
index 0000000..bdf5652
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/client_conn_pool.go
@@ -0,0 +1,256 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Transport code's client connection pooling.
+
+package http2
+
+import (
+ "crypto/tls"
+ "net/http"
+ "sync"
+)
+
+// ClientConnPool manages a pool of HTTP/2 client connections.
+type ClientConnPool interface {
+ GetClientConn(req *http.Request, addr string) (*ClientConn, error)
+ MarkDead(*ClientConn)
+}
+
+// clientConnPoolIdleCloser is the interface implemented by ClientConnPool
+// implementations which can close their idle connections.
+type clientConnPoolIdleCloser interface {
+ ClientConnPool
+ closeIdleConnections()
+}
+
+var (
+ _ clientConnPoolIdleCloser = (*clientConnPool)(nil)
+ _ clientConnPoolIdleCloser = noDialClientConnPool{}
+)
+
+// TODO: use singleflight for dialing and addConnCalls?
+type clientConnPool struct {
+ t *Transport
+
+ mu sync.Mutex // TODO: maybe switch to RWMutex
+ // TODO: add support for sharing conns based on cert names
+ // (e.g. share conn for googleapis.com and appspot.com)
+ conns map[string][]*ClientConn // key is host:port
+ dialing map[string]*dialCall // currently in-flight dials
+ keys map[*ClientConn][]string
+ addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
+}
+
+func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+ return p.getClientConn(req, addr, dialOnMiss)
+}
+
+const (
+ dialOnMiss = true
+ noDialOnMiss = false
+)
+
+func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
+ if isConnectionCloseRequest(req) && dialOnMiss {
+ // It gets its own connection.
+ const singleUse = true
+ cc, err := p.t.dialClientConn(addr, singleUse)
+ if err != nil {
+ return nil, err
+ }
+ return cc, nil
+ }
+ p.mu.Lock()
+ for _, cc := range p.conns[addr] {
+ if cc.CanTakeNewRequest() {
+ p.mu.Unlock()
+ return cc, nil
+ }
+ }
+ if !dialOnMiss {
+ p.mu.Unlock()
+ return nil, ErrNoCachedConn
+ }
+ call := p.getStartDialLocked(addr)
+ p.mu.Unlock()
+ <-call.done
+ return call.res, call.err
+}
+
+// dialCall is an in-flight Transport dial call to a host.
+type dialCall struct {
+ p *clientConnPool
+ done chan struct{} // closed when done
+ res *ClientConn // valid after done is closed
+ err error // valid after done is closed
+}
+
+// requires p.mu is held.
+func (p *clientConnPool) getStartDialLocked(addr string) *dialCall {
+ if call, ok := p.dialing[addr]; ok {
+ // A dial is already in-flight. Don't start another.
+ return call
+ }
+ call := &dialCall{p: p, done: make(chan struct{})}
+ if p.dialing == nil {
+ p.dialing = make(map[string]*dialCall)
+ }
+ p.dialing[addr] = call
+ go call.dial(addr)
+ return call
+}
+
+// run in its own goroutine.
+func (c *dialCall) dial(addr string) {
+ const singleUse = false // shared conn
+ c.res, c.err = c.p.t.dialClientConn(addr, singleUse)
+ close(c.done)
+
+ c.p.mu.Lock()
+ delete(c.p.dialing, addr)
+ if c.err == nil {
+ c.p.addConnLocked(addr, c.res)
+ }
+ c.p.mu.Unlock()
+}
+
+// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
+// already exist. It coalesces concurrent calls with the same key.
+// This is used by the http1 Transport code when it creates a new connection. Because
+// the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
+// the protocol), it can get into a situation where it has multiple TLS connections.
+// This code decides which ones live or die.
+// The return value used is whether c was used.
+// c is never closed.
+func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) {
+ p.mu.Lock()
+ for _, cc := range p.conns[key] {
+ if cc.CanTakeNewRequest() {
+ p.mu.Unlock()
+ return false, nil
+ }
+ }
+ call, dup := p.addConnCalls[key]
+ if !dup {
+ if p.addConnCalls == nil {
+ p.addConnCalls = make(map[string]*addConnCall)
+ }
+ call = &addConnCall{
+ p: p,
+ done: make(chan struct{}),
+ }
+ p.addConnCalls[key] = call
+ go call.run(t, key, c)
+ }
+ p.mu.Unlock()
+
+ <-call.done
+ if call.err != nil {
+ return false, call.err
+ }
+ return !dup, nil
+}
+
+type addConnCall struct {
+ p *clientConnPool
+ done chan struct{} // closed when done
+ err error
+}
+
+func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
+ cc, err := t.NewClientConn(tc)
+
+ p := c.p
+ p.mu.Lock()
+ if err != nil {
+ c.err = err
+ } else {
+ p.addConnLocked(key, cc)
+ }
+ delete(p.addConnCalls, key)
+ p.mu.Unlock()
+ close(c.done)
+}
+
+func (p *clientConnPool) addConn(key string, cc *ClientConn) {
+ p.mu.Lock()
+ p.addConnLocked(key, cc)
+ p.mu.Unlock()
+}
+
+// p.mu must be held
+func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) {
+ for _, v := range p.conns[key] {
+ if v == cc {
+ return
+ }
+ }
+ if p.conns == nil {
+ p.conns = make(map[string][]*ClientConn)
+ }
+ if p.keys == nil {
+ p.keys = make(map[*ClientConn][]string)
+ }
+ p.conns[key] = append(p.conns[key], cc)
+ p.keys[cc] = append(p.keys[cc], key)
+}
+
+func (p *clientConnPool) MarkDead(cc *ClientConn) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ for _, key := range p.keys[cc] {
+ vv, ok := p.conns[key]
+ if !ok {
+ continue
+ }
+ newList := filterOutClientConn(vv, cc)
+ if len(newList) > 0 {
+ p.conns[key] = newList
+ } else {
+ delete(p.conns, key)
+ }
+ }
+ delete(p.keys, cc)
+}
+
+func (p *clientConnPool) closeIdleConnections() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ // TODO: don't close a cc if it was just added to the pool
+ // milliseconds ago and has never been used. There's currently
+ // a small race window with the HTTP/1 Transport's integration
+ // where it can add an idle conn just before using it, and
+ // somebody else can concurrently call CloseIdleConns and
+ // break some caller's RoundTrip.
+ for _, vv := range p.conns {
+ for _, cc := range vv {
+ cc.closeIfIdle()
+ }
+ }
+}
+
+func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
+ out := in[:0]
+ for _, v := range in {
+ if v != exclude {
+ out = append(out, v)
+ }
+ }
+ // If we filtered it out, zero out the last item to prevent
+ // the GC from seeing it.
+ if len(in) != len(out) {
+ in[len(in)-1] = nil
+ }
+ return out
+}
+
+// noDialClientConnPool is an implementation of http2.ClientConnPool
+// which never dials. We let the HTTP/1.1 client dial and use its TLS
+// connection instead.
+type noDialClientConnPool struct{ *clientConnPool }
+
+func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+ return p.getClientConn(req, addr, noDialOnMiss)
+}
diff --git a/vendor/golang.org/x/net/http2/configure_transport.go b/vendor/golang.org/x/net/http2/configure_transport.go
new file mode 100644
index 0000000..b65fc6d
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/configure_transport.go
@@ -0,0 +1,80 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.6
+
+package http2
+
+import (
+ "crypto/tls"
+ "fmt"
+ "net/http"
+)
+
+func configureTransport(t1 *http.Transport) (*Transport, error) {
+ connPool := new(clientConnPool)
+ t2 := &Transport{
+ ConnPool: noDialClientConnPool{connPool},
+ t1: t1,
+ }
+ connPool.t = t2
+ if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
+ return nil, err
+ }
+ if t1.TLSClientConfig == nil {
+ t1.TLSClientConfig = new(tls.Config)
+ }
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
+ t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
+ }
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
+ t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
+ }
+ upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
+ addr := authorityAddr("https", authority)
+ if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
+ go c.Close()
+ return erringRoundTripper{err}
+ } else if !used {
+ // Turns out we don't need this c.
+ // For example, two goroutines made requests to the same host
+ // at the same time, both kicking off TCP dials. (since protocol
+ // was unknown)
+ go c.Close()
+ }
+ return t2
+ }
+ if m := t1.TLSNextProto; len(m) == 0 {
+ t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
+ "h2": upgradeFn,
+ }
+ } else {
+ m["h2"] = upgradeFn
+ }
+ return t2, nil
+}
+
+// registerHTTPSProtocol calls Transport.RegisterProtocol but
+// converting panics into errors.
+func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = fmt.Errorf("%v", e)
+ }
+ }()
+ t.RegisterProtocol("https", rt)
+ return nil
+}
+
+// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
+// if there's already has a cached connection to the host.
+type noDialH2RoundTripper struct{ t *Transport }
+
+func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ res, err := rt.t.RoundTrip(req)
+ if err == ErrNoCachedConn {
+ return nil, http.ErrSkipAltProtocol
+ }
+ return res, err
+}
diff --git a/vendor/golang.org/x/net/http2/databuffer.go b/vendor/golang.org/x/net/http2/databuffer.go
new file mode 100644
index 0000000..a3067f8
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/databuffer.go
@@ -0,0 +1,146 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+)
+
+// Buffer chunks are allocated from a pool to reduce pressure on GC.
+// The maximum wasted space per dataBuffer is 2x the largest size class,
+// which happens when the dataBuffer has multiple chunks and there is
+// one unread byte in both the first and last chunks. We use a few size
+// classes to minimize overheads for servers that typically receive very
+// small request bodies.
+//
+// TODO: Benchmark to determine if the pools are necessary. The GC may have
+// improved enough that we can instead allocate chunks like this:
+// make([]byte, max(16<<10, expectedBytesRemaining))
+var (
+ dataChunkSizeClasses = []int{
+ 1 << 10,
+ 2 << 10,
+ 4 << 10,
+ 8 << 10,
+ 16 << 10,
+ }
+ dataChunkPools = [...]sync.Pool{
+ {New: func() interface{} { return make([]byte, 1<<10) }},
+ {New: func() interface{} { return make([]byte, 2<<10) }},
+ {New: func() interface{} { return make([]byte, 4<<10) }},
+ {New: func() interface{} { return make([]byte, 8<<10) }},
+ {New: func() interface{} { return make([]byte, 16<<10) }},
+ }
+)
+
+func getDataBufferChunk(size int64) []byte {
+ i := 0
+ for ; i < len(dataChunkSizeClasses)-1; i++ {
+ if size <= int64(dataChunkSizeClasses[i]) {
+ break
+ }
+ }
+ return dataChunkPools[i].Get().([]byte)
+}
+
+func putDataBufferChunk(p []byte) {
+ for i, n := range dataChunkSizeClasses {
+ if len(p) == n {
+ dataChunkPools[i].Put(p)
+ return
+ }
+ }
+ panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
+}
+
+// dataBuffer is an io.ReadWriter backed by a list of data chunks.
+// Each dataBuffer is used to read DATA frames on a single stream.
+// The buffer is divided into chunks so the server can limit the
+// total memory used by a single connection without limiting the
+// request body size on any single stream.
+type dataBuffer struct {
+ chunks [][]byte
+ r int // next byte to read is chunks[0][r]
+ w int // next byte to write is chunks[len(chunks)-1][w]
+ size int // total buffered bytes
+ expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
+}
+
+var errReadEmpty = errors.New("read from empty dataBuffer")
+
+// Read copies bytes from the buffer into p.
+// It is an error to read when no data is available.
+func (b *dataBuffer) Read(p []byte) (int, error) {
+ if b.size == 0 {
+ return 0, errReadEmpty
+ }
+ var ntotal int
+ for len(p) > 0 && b.size > 0 {
+ readFrom := b.bytesFromFirstChunk()
+ n := copy(p, readFrom)
+ p = p[n:]
+ ntotal += n
+ b.r += n
+ b.size -= n
+ // If the first chunk has been consumed, advance to the next chunk.
+ if b.r == len(b.chunks[0]) {
+ putDataBufferChunk(b.chunks[0])
+ end := len(b.chunks) - 1
+ copy(b.chunks[:end], b.chunks[1:])
+ b.chunks[end] = nil
+ b.chunks = b.chunks[:end]
+ b.r = 0
+ }
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) bytesFromFirstChunk() []byte {
+ if len(b.chunks) == 1 {
+ return b.chunks[0][b.r:b.w]
+ }
+ return b.chunks[0][b.r:]
+}
+
+// Len returns the number of bytes of the unread portion of the buffer.
+func (b *dataBuffer) Len() int {
+ return b.size
+}
+
+// Write appends p to the buffer.
+func (b *dataBuffer) Write(p []byte) (int, error) {
+ ntotal := len(p)
+ for len(p) > 0 {
+ // If the last chunk is empty, allocate a new chunk. Try to allocate
+ // enough to fully copy p plus any additional bytes we expect to
+ // receive. However, this may allocate less than len(p).
+ want := int64(len(p))
+ if b.expected > want {
+ want = b.expected
+ }
+ chunk := b.lastChunkOrAlloc(want)
+ n := copy(chunk[b.w:], p)
+ p = p[n:]
+ b.w += n
+ b.size += n
+ b.expected -= int64(n)
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte {
+ if len(b.chunks) != 0 {
+ last := b.chunks[len(b.chunks)-1]
+ if b.w < len(last) {
+ return last
+ }
+ }
+ chunk := getDataBufferChunk(want)
+ b.chunks = append(b.chunks, chunk)
+ b.w = 0
+ return chunk
+}
diff --git a/vendor/golang.org/x/net/http2/errors.go b/vendor/golang.org/x/net/http2/errors.go
new file mode 100644
index 0000000..71f2c46
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/errors.go
@@ -0,0 +1,133 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "errors"
+ "fmt"
+)
+
+// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
+type ErrCode uint32
+
+const (
+ ErrCodeNo ErrCode = 0x0
+ ErrCodeProtocol ErrCode = 0x1
+ ErrCodeInternal ErrCode = 0x2
+ ErrCodeFlowControl ErrCode = 0x3
+ ErrCodeSettingsTimeout ErrCode = 0x4
+ ErrCodeStreamClosed ErrCode = 0x5
+ ErrCodeFrameSize ErrCode = 0x6
+ ErrCodeRefusedStream ErrCode = 0x7
+ ErrCodeCancel ErrCode = 0x8
+ ErrCodeCompression ErrCode = 0x9
+ ErrCodeConnect ErrCode = 0xa
+ ErrCodeEnhanceYourCalm ErrCode = 0xb
+ ErrCodeInadequateSecurity ErrCode = 0xc
+ ErrCodeHTTP11Required ErrCode = 0xd
+)
+
+var errCodeName = map[ErrCode]string{
+ ErrCodeNo: "NO_ERROR",
+ ErrCodeProtocol: "PROTOCOL_ERROR",
+ ErrCodeInternal: "INTERNAL_ERROR",
+ ErrCodeFlowControl: "FLOW_CONTROL_ERROR",
+ ErrCodeSettingsTimeout: "SETTINGS_TIMEOUT",
+ ErrCodeStreamClosed: "STREAM_CLOSED",
+ ErrCodeFrameSize: "FRAME_SIZE_ERROR",
+ ErrCodeRefusedStream: "REFUSED_STREAM",
+ ErrCodeCancel: "CANCEL",
+ ErrCodeCompression: "COMPRESSION_ERROR",
+ ErrCodeConnect: "CONNECT_ERROR",
+ ErrCodeEnhanceYourCalm: "ENHANCE_YOUR_CALM",
+ ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
+ ErrCodeHTTP11Required: "HTTP_1_1_REQUIRED",
+}
+
+func (e ErrCode) String() string {
+ if s, ok := errCodeName[e]; ok {
+ return s
+ }
+ return fmt.Sprintf("unknown error code 0x%x", uint32(e))
+}
+
+// ConnectionError is an error that results in the termination of the
+// entire connection.
+type ConnectionError ErrCode
+
+func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) }
+
+// StreamError is an error that only affects one stream within an
+// HTTP/2 connection.
+type StreamError struct {
+ StreamID uint32
+ Code ErrCode
+ Cause error // optional additional detail
+}
+
+func streamError(id uint32, code ErrCode) StreamError {
+ return StreamError{StreamID: id, Code: code}
+}
+
+func (e StreamError) Error() string {
+ if e.Cause != nil {
+ return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
+ }
+ return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
+}
+
+// 6.9.1 The Flow Control Window
+// "If a sender receives a WINDOW_UPDATE that causes a flow control
+// window to exceed this maximum it MUST terminate either the stream
+// or the connection, as appropriate. For streams, [...]; for the
+// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
+type goAwayFlowError struct{}
+
+func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
+
+// connError represents an HTTP/2 ConnectionError error code, along
+// with a string (for debugging) explaining why.
+//
+// Errors of this type are only returned by the frame parser functions
+// and converted into ConnectionError(Code), after stashing away
+// the Reason into the Framer's errDetail field, accessible via
+// the (*Framer).ErrorDetail method.
+type connError struct {
+ Code ErrCode // the ConnectionError error code
+ Reason string // additional reason
+}
+
+func (e connError) Error() string {
+ return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
+}
+
+type pseudoHeaderError string
+
+func (e pseudoHeaderError) Error() string {
+ return fmt.Sprintf("invalid pseudo-header %q", string(e))
+}
+
+type duplicatePseudoHeaderError string
+
+func (e duplicatePseudoHeaderError) Error() string {
+ return fmt.Sprintf("duplicate pseudo-header %q", string(e))
+}
+
+type headerFieldNameError string
+
+func (e headerFieldNameError) Error() string {
+ return fmt.Sprintf("invalid header field name %q", string(e))
+}
+
+type headerFieldValueError string
+
+func (e headerFieldValueError) Error() string {
+ return fmt.Sprintf("invalid header field value %q", string(e))
+}
+
+var (
+ errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
+ errPseudoAfterRegular = errors.New("pseudo header field after regular")
+)
diff --git a/vendor/golang.org/x/net/http2/flow.go b/vendor/golang.org/x/net/http2/flow.go
new file mode 100644
index 0000000..957de25
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/flow.go
@@ -0,0 +1,50 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Flow control
+
+package http2
+
+// flow is the flow control window's size.
+type flow struct {
+ // n is the number of DATA bytes we're allowed to send.
+ // A flow is kept both on a conn and a per-stream.
+ n int32
+
+ // conn points to the shared connection-level flow that is
+ // shared by all streams on that conn. It is nil for the flow
+ // that's on the conn directly.
+ conn *flow
+}
+
+func (f *flow) setConnFlow(cf *flow) { f.conn = cf }
+
+func (f *flow) available() int32 {
+ n := f.n
+ if f.conn != nil && f.conn.n < n {
+ n = f.conn.n
+ }
+ return n
+}
+
+func (f *flow) take(n int32) {
+ if n > f.available() {
+ panic("internal error: took too much")
+ }
+ f.n -= n
+ if f.conn != nil {
+ f.conn.n -= n
+ }
+}
+
+// add adds n bytes (positive or negative) to the flow control window.
+// It returns false if the sum would exceed 2^31-1.
+func (f *flow) add(n int32) bool {
+ remain := (1<<31 - 1) - f.n
+ if n > remain {
+ return false
+ }
+ f.n += n
+ return true
+}
diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go
new file mode 100644
index 0000000..3b14890
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/frame.go
@@ -0,0 +1,1579 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/http2/hpack"
+ "golang.org/x/net/lex/httplex"
+)
+
+const frameHeaderLen = 9
+
+var padZeros = make([]byte, 255) // zeros for padding
+
+// A FrameType is a registered frame type as defined in
+// http://http2.github.io/http2-spec/#rfc.section.11.2
+type FrameType uint8
+
+const (
+ FrameData FrameType = 0x0
+ FrameHeaders FrameType = 0x1
+ FramePriority FrameType = 0x2
+ FrameRSTStream FrameType = 0x3
+ FrameSettings FrameType = 0x4
+ FramePushPromise FrameType = 0x5
+ FramePing FrameType = 0x6
+ FrameGoAway FrameType = 0x7
+ FrameWindowUpdate FrameType = 0x8
+ FrameContinuation FrameType = 0x9
+)
+
+var frameName = map[FrameType]string{
+ FrameData: "DATA",
+ FrameHeaders: "HEADERS",
+ FramePriority: "PRIORITY",
+ FrameRSTStream: "RST_STREAM",
+ FrameSettings: "SETTINGS",
+ FramePushPromise: "PUSH_PROMISE",
+ FramePing: "PING",
+ FrameGoAway: "GOAWAY",
+ FrameWindowUpdate: "WINDOW_UPDATE",
+ FrameContinuation: "CONTINUATION",
+}
+
+func (t FrameType) String() string {
+ if s, ok := frameName[t]; ok {
+ return s
+ }
+ return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t))
+}
+
+// Flags is a bitmask of HTTP/2 flags.
+// The meaning of flags varies depending on the frame type.
+type Flags uint8
+
+// Has reports whether f contains all (0 or more) flags in v.
+func (f Flags) Has(v Flags) bool {
+ return (f & v) == v
+}
+
+// Frame-specific FrameHeader flag bits.
+const (
+ // Data Frame
+ FlagDataEndStream Flags = 0x1
+ FlagDataPadded Flags = 0x8
+
+ // Headers Frame
+ FlagHeadersEndStream Flags = 0x1
+ FlagHeadersEndHeaders Flags = 0x4
+ FlagHeadersPadded Flags = 0x8
+ FlagHeadersPriority Flags = 0x20
+
+ // Settings Frame
+ FlagSettingsAck Flags = 0x1
+
+ // Ping Frame
+ FlagPingAck Flags = 0x1
+
+ // Continuation Frame
+ FlagContinuationEndHeaders Flags = 0x4
+
+ FlagPushPromiseEndHeaders Flags = 0x4
+ FlagPushPromisePadded Flags = 0x8
+)
+
+var flagName = map[FrameType]map[Flags]string{
+ FrameData: {
+ FlagDataEndStream: "END_STREAM",
+ FlagDataPadded: "PADDED",
+ },
+ FrameHeaders: {
+ FlagHeadersEndStream: "END_STREAM",
+ FlagHeadersEndHeaders: "END_HEADERS",
+ FlagHeadersPadded: "PADDED",
+ FlagHeadersPriority: "PRIORITY",
+ },
+ FrameSettings: {
+ FlagSettingsAck: "ACK",
+ },
+ FramePing: {
+ FlagPingAck: "ACK",
+ },
+ FrameContinuation: {
+ FlagContinuationEndHeaders: "END_HEADERS",
+ },
+ FramePushPromise: {
+ FlagPushPromiseEndHeaders: "END_HEADERS",
+ FlagPushPromisePadded: "PADDED",
+ },
+}
+
+// a frameParser parses a frame given its FrameHeader and payload
+// bytes. The length of payload will always equal fh.Length (which
+// might be 0).
+type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
+
+var frameParsers = map[FrameType]frameParser{
+ FrameData: parseDataFrame,
+ FrameHeaders: parseHeadersFrame,
+ FramePriority: parsePriorityFrame,
+ FrameRSTStream: parseRSTStreamFrame,
+ FrameSettings: parseSettingsFrame,
+ FramePushPromise: parsePushPromise,
+ FramePing: parsePingFrame,
+ FrameGoAway: parseGoAwayFrame,
+ FrameWindowUpdate: parseWindowUpdateFrame,
+ FrameContinuation: parseContinuationFrame,
+}
+
+func typeFrameParser(t FrameType) frameParser {
+ if f := frameParsers[t]; f != nil {
+ return f
+ }
+ return parseUnknownFrame
+}
+
+// A FrameHeader is the 9 byte header of all HTTP/2 frames.
+//
+// See http://http2.github.io/http2-spec/#FrameHeader
+type FrameHeader struct {
+ valid bool // caller can access []byte fields in the Frame
+
+ // Type is the 1 byte frame type. There are ten standard frame
+ // types, but extension frame types may be written by WriteRawFrame
+ // and will be returned by ReadFrame (as UnknownFrame).
+ Type FrameType
+
+ // Flags are the 1 byte of 8 potential bit flags per frame.
+ // They are specific to the frame type.
+ Flags Flags
+
+ // Length is the length of the frame, not including the 9 byte header.
+ // The maximum size is one byte less than 16MB (uint24), but only
+ // frames up to 16KB are allowed without peer agreement.
+ Length uint32
+
+ // StreamID is which stream this frame is for. Certain frames
+ // are not stream-specific, in which case this field is 0.
+ StreamID uint32
+}
+
+// Header returns h. It exists so FrameHeaders can be embedded in other
+// specific frame types and implement the Frame interface.
+func (h FrameHeader) Header() FrameHeader { return h }
+
+func (h FrameHeader) String() string {
+ var buf bytes.Buffer
+ buf.WriteString("[FrameHeader ")
+ h.writeDebug(&buf)
+ buf.WriteByte(']')
+ return buf.String()
+}
+
+func (h FrameHeader) writeDebug(buf *bytes.Buffer) {
+ buf.WriteString(h.Type.String())
+ if h.Flags != 0 {
+ buf.WriteString(" flags=")
+ set := 0
+ for i := uint8(0); i < 8; i++ {
+ if h.Flags&(1< 1 {
+ buf.WriteByte('|')
+ }
+ name := flagName[h.Type][Flags(1<>24),
+ byte(streamID>>16),
+ byte(streamID>>8),
+ byte(streamID))
+}
+
+func (f *Framer) endWrite() error {
+ // Now that we know the final size, fill in the FrameHeader in
+ // the space previously reserved for it. Abuse append.
+ length := len(f.wbuf) - frameHeaderLen
+ if length >= (1 << 24) {
+ return ErrFrameTooLarge
+ }
+ _ = append(f.wbuf[:0],
+ byte(length>>16),
+ byte(length>>8),
+ byte(length))
+ if f.logWrites {
+ f.logWrite()
+ }
+
+ n, err := f.w.Write(f.wbuf)
+ if err == nil && n != len(f.wbuf) {
+ err = io.ErrShortWrite
+ }
+ return err
+}
+
+func (f *Framer) logWrite() {
+ if f.debugFramer == nil {
+ f.debugFramerBuf = new(bytes.Buffer)
+ f.debugFramer = NewFramer(nil, f.debugFramerBuf)
+ f.debugFramer.logReads = false // we log it ourselves, saying "wrote" below
+ // Let us read anything, even if we accidentally wrote it
+ // in the wrong order:
+ f.debugFramer.AllowIllegalReads = true
+ }
+ f.debugFramerBuf.Write(f.wbuf)
+ fr, err := f.debugFramer.ReadFrame()
+ if err != nil {
+ f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f)
+ return
+ }
+ f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, summarizeFrame(fr))
+}
+
+func (f *Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
+func (f *Framer) writeBytes(v []byte) { f.wbuf = append(f.wbuf, v...) }
+func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
+func (f *Framer) writeUint32(v uint32) {
+ f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+const (
+ minMaxFrameSize = 1 << 14
+ maxFrameSize = 1<<24 - 1
+)
+
+// SetReuseFrames allows the Framer to reuse Frames.
+// If called on a Framer, Frames returned by calls to ReadFrame are only
+// valid until the next call to ReadFrame.
+func (fr *Framer) SetReuseFrames() {
+ if fr.frameCache != nil {
+ return
+ }
+ fr.frameCache = &frameCache{}
+}
+
+type frameCache struct {
+ dataFrame DataFrame
+}
+
+func (fc *frameCache) getDataFrame() *DataFrame {
+ if fc == nil {
+ return &DataFrame{}
+ }
+ return &fc.dataFrame
+}
+
+// NewFramer returns a Framer that writes frames to w and reads them from r.
+func NewFramer(w io.Writer, r io.Reader) *Framer {
+ fr := &Framer{
+ w: w,
+ r: r,
+ logReads: logFrameReads,
+ logWrites: logFrameWrites,
+ debugReadLoggerf: log.Printf,
+ debugWriteLoggerf: log.Printf,
+ }
+ fr.getReadBuf = func(size uint32) []byte {
+ if cap(fr.readBuf) >= int(size) {
+ return fr.readBuf[:size]
+ }
+ fr.readBuf = make([]byte, size)
+ return fr.readBuf
+ }
+ fr.SetMaxReadFrameSize(maxFrameSize)
+ return fr
+}
+
+// SetMaxReadFrameSize sets the maximum size of a frame
+// that will be read by a subsequent call to ReadFrame.
+// It is the caller's responsibility to advertise this
+// limit with a SETTINGS frame.
+func (fr *Framer) SetMaxReadFrameSize(v uint32) {
+ if v > maxFrameSize {
+ v = maxFrameSize
+ }
+ fr.maxReadSize = v
+}
+
+// ErrorDetail returns a more detailed error of the last error
+// returned by Framer.ReadFrame. For instance, if ReadFrame
+// returns a StreamError with code PROTOCOL_ERROR, ErrorDetail
+// will say exactly what was invalid. ErrorDetail is not guaranteed
+// to return a non-nil value and like the rest of the http2 package,
+// its return value is not protected by an API compatibility promise.
+// ErrorDetail is reset after the next call to ReadFrame.
+func (fr *Framer) ErrorDetail() error {
+ return fr.errDetail
+}
+
+// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
+// sends a frame that is larger than declared with SetMaxReadFrameSize.
+var ErrFrameTooLarge = errors.New("http2: frame too large")
+
+// terminalReadFrameError reports whether err is an unrecoverable
+// error from ReadFrame and no other frames should be read.
+func terminalReadFrameError(err error) bool {
+ if _, ok := err.(StreamError); ok {
+ return false
+ }
+ return err != nil
+}
+
+// ReadFrame reads a single frame. The returned Frame is only valid
+// until the next call to ReadFrame.
+//
+// If the frame is larger than previously set with SetMaxReadFrameSize, the
+// returned error is ErrFrameTooLarge. Other errors may be of type
+// ConnectionError, StreamError, or anything else from the underlying
+// reader.
+func (fr *Framer) ReadFrame() (Frame, error) {
+ fr.errDetail = nil
+ if fr.lastFrame != nil {
+ fr.lastFrame.invalidate()
+ }
+ fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
+ if err != nil {
+ return nil, err
+ }
+ if fh.Length > fr.maxReadSize {
+ return nil, ErrFrameTooLarge
+ }
+ payload := fr.getReadBuf(fh.Length)
+ if _, err := io.ReadFull(fr.r, payload); err != nil {
+ return nil, err
+ }
+ f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
+ if err != nil {
+ if ce, ok := err.(connError); ok {
+ return nil, fr.connError(ce.Code, ce.Reason)
+ }
+ return nil, err
+ }
+ if err := fr.checkFrameOrder(f); err != nil {
+ return nil, err
+ }
+ if fr.logReads {
+ fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
+ }
+ if fh.Type == FrameHeaders && fr.ReadMetaHeaders != nil {
+ return fr.readMetaFrame(f.(*HeadersFrame))
+ }
+ return f, nil
+}
+
+// connError returns ConnectionError(code) but first
+// stashes away a public reason to the caller can optionally relay it
+// to the peer before hanging up on them. This might help others debug
+// their implementations.
+func (fr *Framer) connError(code ErrCode, reason string) error {
+ fr.errDetail = errors.New(reason)
+ return ConnectionError(code)
+}
+
+// checkFrameOrder reports an error if f is an invalid frame to return
+// next from ReadFrame. Mostly it checks whether HEADERS and
+// CONTINUATION frames are contiguous.
+func (fr *Framer) checkFrameOrder(f Frame) error {
+ last := fr.lastFrame
+ fr.lastFrame = f
+ if fr.AllowIllegalReads {
+ return nil
+ }
+
+ fh := f.Header()
+ if fr.lastHeaderStream != 0 {
+ if fh.Type != FrameContinuation {
+ return fr.connError(ErrCodeProtocol,
+ fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
+ fh.Type, fh.StreamID,
+ last.Header().Type, fr.lastHeaderStream))
+ }
+ if fh.StreamID != fr.lastHeaderStream {
+ return fr.connError(ErrCodeProtocol,
+ fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
+ fh.StreamID, fr.lastHeaderStream))
+ }
+ } else if fh.Type == FrameContinuation {
+ return fr.connError(ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID))
+ }
+
+ switch fh.Type {
+ case FrameHeaders, FrameContinuation:
+ if fh.Flags.Has(FlagHeadersEndHeaders) {
+ fr.lastHeaderStream = 0
+ } else {
+ fr.lastHeaderStream = fh.StreamID
+ }
+ }
+
+ return nil
+}
+
+// A DataFrame conveys arbitrary, variable-length sequences of octets
+// associated with a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.1
+type DataFrame struct {
+ FrameHeader
+ data []byte
+}
+
+func (f *DataFrame) StreamEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagDataEndStream)
+}
+
+// Data returns the frame's data octets, not including any padding
+// size byte or padding suffix bytes.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *DataFrame) Data() []byte {
+ f.checkValid()
+ return f.data
+}
+
+func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ // DATA frames MUST be associated with a stream. If a
+ // DATA frame is received whose stream identifier
+ // field is 0x0, the recipient MUST respond with a
+ // connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR.
+ return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
+ }
+ f := fc.getDataFrame()
+ f.FrameHeader = fh
+
+ var padSize byte
+ if fh.Flags.Has(FlagDataPadded) {
+ var err error
+ payload, padSize, err = readByte(payload)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if int(padSize) > len(payload) {
+ // If the length of the padding is greater than the
+ // length of the frame payload, the recipient MUST
+ // treat this as a connection error.
+ // Filed: https://github.com/http2/http2-spec/issues/610
+ return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
+ }
+ f.data = payload[:len(payload)-int(padSize)]
+ return f, nil
+}
+
+var (
+ errStreamID = errors.New("invalid stream ID")
+ errDepStreamID = errors.New("invalid dependent stream ID")
+ errPadLength = errors.New("pad length too large")
+ errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
+)
+
+func validStreamIDOrZero(streamID uint32) bool {
+ return streamID&(1<<31) == 0
+}
+
+func validStreamID(streamID uint32) bool {
+ return streamID != 0 && streamID&(1<<31) == 0
+}
+
+// WriteData writes a DATA frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility not to violate the maximum frame size
+// and to not call other Write methods concurrently.
+func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
+ return f.WriteDataPadded(streamID, endStream, data, nil)
+}
+
+// WriteData writes a DATA frame with optional padding.
+//
+// If pad is nil, the padding bit is not sent.
+// The length of pad must not exceed 255 bytes.
+// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility not to violate the maximum frame size
+// and to not call other Write methods concurrently.
+func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ if len(pad) > 0 {
+ if len(pad) > 255 {
+ return errPadLength
+ }
+ if !f.AllowIllegalWrites {
+ for _, b := range pad {
+ if b != 0 {
+ // "Padding octets MUST be set to zero when sending."
+ return errPadBytes
+ }
+ }
+ }
+ }
+ var flags Flags
+ if endStream {
+ flags |= FlagDataEndStream
+ }
+ if pad != nil {
+ flags |= FlagDataPadded
+ }
+ f.startWrite(FrameData, flags, streamID)
+ if pad != nil {
+ f.wbuf = append(f.wbuf, byte(len(pad)))
+ }
+ f.wbuf = append(f.wbuf, data...)
+ f.wbuf = append(f.wbuf, pad...)
+ return f.endWrite()
+}
+
+// A SettingsFrame conveys configuration parameters that affect how
+// endpoints communicate, such as preferences and constraints on peer
+// behavior.
+//
+// See http://http2.github.io/http2-spec/#SETTINGS
+type SettingsFrame struct {
+ FrameHeader
+ p []byte
+}
+
+func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
+ // When this (ACK 0x1) bit is set, the payload of the
+ // SETTINGS frame MUST be empty. Receipt of a
+ // SETTINGS frame with the ACK flag set and a length
+ // field value other than 0 MUST be treated as a
+ // connection error (Section 5.4.1) of type
+ // FRAME_SIZE_ERROR.
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID != 0 {
+ // SETTINGS frames always apply to a connection,
+ // never a single stream. The stream identifier for a
+ // SETTINGS frame MUST be zero (0x0). If an endpoint
+ // receives a SETTINGS frame whose stream identifier
+ // field is anything other than 0x0, the endpoint MUST
+ // respond with a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ if len(p)%6 != 0 {
+ // Expecting even number of 6 byte settings.
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ f := &SettingsFrame{FrameHeader: fh, p: p}
+ if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
+ // Values above the maximum flow control window size of 2^31 - 1 MUST
+ // be treated as a connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR.
+ return nil, ConnectionError(ErrCodeFlowControl)
+ }
+ return f, nil
+}
+
+func (f *SettingsFrame) IsAck() bool {
+ return f.FrameHeader.Flags.Has(FlagSettingsAck)
+}
+
+func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
+ f.checkValid()
+ buf := f.p
+ for len(buf) > 0 {
+ settingID := SettingID(binary.BigEndian.Uint16(buf[:2]))
+ if settingID == s {
+ return binary.BigEndian.Uint32(buf[2:6]), true
+ }
+ buf = buf[6:]
+ }
+ return 0, false
+}
+
+// ForeachSetting runs fn for each setting.
+// It stops and returns the first error.
+func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
+ f.checkValid()
+ buf := f.p
+ for len(buf) > 0 {
+ if err := fn(Setting{
+ SettingID(binary.BigEndian.Uint16(buf[:2])),
+ binary.BigEndian.Uint32(buf[2:6]),
+ }); err != nil {
+ return err
+ }
+ buf = buf[6:]
+ }
+ return nil
+}
+
+// WriteSettings writes a SETTINGS frame with zero or more settings
+// specified and the ACK bit not set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettings(settings ...Setting) error {
+ f.startWrite(FrameSettings, 0, 0)
+ for _, s := range settings {
+ f.writeUint16(uint16(s.ID))
+ f.writeUint32(s.Val)
+ }
+ return f.endWrite()
+}
+
+// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettingsAck() error {
+ f.startWrite(FrameSettings, FlagSettingsAck, 0)
+ return f.endWrite()
+}
+
+// A PingFrame is a mechanism for measuring a minimal round trip time
+// from the sender, as well as determining whether an idle connection
+// is still functional.
+// See http://http2.github.io/http2-spec/#rfc.section.6.7
+type PingFrame struct {
+ FrameHeader
+ Data [8]byte
+}
+
+func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
+
+func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if len(payload) != 8 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID != 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ f := &PingFrame{FrameHeader: fh}
+ copy(f.Data[:], payload)
+ return f, nil
+}
+
+func (f *Framer) WritePing(ack bool, data [8]byte) error {
+ var flags Flags
+ if ack {
+ flags = FlagPingAck
+ }
+ f.startWrite(FramePing, flags, 0)
+ f.writeBytes(data[:])
+ return f.endWrite()
+}
+
+// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
+// See http://http2.github.io/http2-spec/#rfc.section.6.8
+type GoAwayFrame struct {
+ FrameHeader
+ LastStreamID uint32
+ ErrCode ErrCode
+ debugData []byte
+}
+
+// DebugData returns any debug data in the GOAWAY frame. Its contents
+// are not defined.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *GoAwayFrame) DebugData() []byte {
+ f.checkValid()
+ return f.debugData
+}
+
+func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.StreamID != 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ if len(p) < 8 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ return &GoAwayFrame{
+ FrameHeader: fh,
+ LastStreamID: binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1),
+ ErrCode: ErrCode(binary.BigEndian.Uint32(p[4:8])),
+ debugData: p[8:],
+ }, nil
+}
+
+func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error {
+ f.startWrite(FrameGoAway, 0, 0)
+ f.writeUint32(maxStreamID & (1<<31 - 1))
+ f.writeUint32(uint32(code))
+ f.writeBytes(debugData)
+ return f.endWrite()
+}
+
+// An UnknownFrame is the frame type returned when the frame type is unknown
+// or no specific frame type parser exists.
+type UnknownFrame struct {
+ FrameHeader
+ p []byte
+}
+
+// Payload returns the frame's payload (after the header). It is not
+// valid to call this method after a subsequent call to
+// Framer.ReadFrame, nor is it valid to retain the returned slice.
+// The memory is owned by the Framer and is invalidated when the next
+// frame is read.
+func (f *UnknownFrame) Payload() []byte {
+ f.checkValid()
+ return f.p
+}
+
+func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ return &UnknownFrame{fh, p}, nil
+}
+
+// A WindowUpdateFrame is used to implement flow control.
+// See http://http2.github.io/http2-spec/#rfc.section.6.9
+type WindowUpdateFrame struct {
+ FrameHeader
+ Increment uint32 // never read with high bit set
+}
+
+func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if len(p) != 4 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
+ if inc == 0 {
+ // A receiver MUST treat the receipt of a
+ // WINDOW_UPDATE frame with an flow control window
+ // increment of 0 as a stream error (Section 5.4.2) of
+ // type PROTOCOL_ERROR; errors on the connection flow
+ // control window MUST be treated as a connection
+ // error (Section 5.4.1).
+ if fh.StreamID == 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ return nil, streamError(fh.StreamID, ErrCodeProtocol)
+ }
+ return &WindowUpdateFrame{
+ FrameHeader: fh,
+ Increment: inc,
+ }, nil
+}
+
+// WriteWindowUpdate writes a WINDOW_UPDATE frame.
+// The increment value must be between 1 and 2,147,483,647, inclusive.
+// If the Stream ID is zero, the window update applies to the
+// connection as a whole.
+func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error {
+ // "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets."
+ if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites {
+ return errors.New("illegal window increment value")
+ }
+ f.startWrite(FrameWindowUpdate, 0, streamID)
+ f.writeUint32(incr)
+ return f.endWrite()
+}
+
+// A HeadersFrame is used to open a stream and additionally carries a
+// header block fragment.
+type HeadersFrame struct {
+ FrameHeader
+
+ // Priority is set if FlagHeadersPriority is set in the FrameHeader.
+ Priority PriorityParam
+
+ headerFragBuf []byte // not owned
+}
+
+func (f *HeadersFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *HeadersFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersEndHeaders)
+}
+
+func (f *HeadersFrame) StreamEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersEndStream)
+}
+
+func (f *HeadersFrame) HasPriority() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersPriority)
+}
+
+func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
+ hf := &HeadersFrame{
+ FrameHeader: fh,
+ }
+ if fh.StreamID == 0 {
+ // HEADERS frames MUST be associated with a stream. If a HEADERS frame
+ // is received whose stream identifier field is 0x0, the recipient MUST
+ // respond with a connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR.
+ return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
+ }
+ var padLength uint8
+ if fh.Flags.Has(FlagHeadersPadded) {
+ if p, padLength, err = readByte(p); err != nil {
+ return
+ }
+ }
+ if fh.Flags.Has(FlagHeadersPriority) {
+ var v uint32
+ p, v, err = readUint32(p)
+ if err != nil {
+ return nil, err
+ }
+ hf.Priority.StreamDep = v & 0x7fffffff
+ hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
+ p, hf.Priority.Weight, err = readByte(p)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if len(p)-int(padLength) <= 0 {
+ return nil, streamError(fh.StreamID, ErrCodeProtocol)
+ }
+ hf.headerFragBuf = p[:len(p)-int(padLength)]
+ return hf, nil
+}
+
+// HeadersFrameParam are the parameters for writing a HEADERS frame.
+type HeadersFrameParam struct {
+ // StreamID is the required Stream ID to initiate.
+ StreamID uint32
+ // BlockFragment is part (or all) of a Header Block.
+ BlockFragment []byte
+
+ // EndStream indicates that the header block is the last that
+ // the endpoint will send for the identified stream. Setting
+ // this flag causes the stream to enter one of "half closed"
+ // states.
+ EndStream bool
+
+ // EndHeaders indicates that this frame contains an entire
+ // header block and is not followed by any
+ // CONTINUATION frames.
+ EndHeaders bool
+
+ // PadLength is the optional number of bytes of zeros to add
+ // to this frame.
+ PadLength uint8
+
+ // Priority, if non-zero, includes stream priority information
+ // in the HEADER frame.
+ Priority PriorityParam
+}
+
+// WriteHeaders writes a single HEADERS frame.
+//
+// This is a low-level header writing method. Encoding headers and
+// splitting them into any necessary CONTINUATION frames is handled
+// elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
+ if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if p.PadLength != 0 {
+ flags |= FlagHeadersPadded
+ }
+ if p.EndStream {
+ flags |= FlagHeadersEndStream
+ }
+ if p.EndHeaders {
+ flags |= FlagHeadersEndHeaders
+ }
+ if !p.Priority.IsZero() {
+ flags |= FlagHeadersPriority
+ }
+ f.startWrite(FrameHeaders, flags, p.StreamID)
+ if p.PadLength != 0 {
+ f.writeByte(p.PadLength)
+ }
+ if !p.Priority.IsZero() {
+ v := p.Priority.StreamDep
+ if !validStreamIDOrZero(v) && !f.AllowIllegalWrites {
+ return errDepStreamID
+ }
+ if p.Priority.Exclusive {
+ v |= 1 << 31
+ }
+ f.writeUint32(v)
+ f.writeByte(p.Priority.Weight)
+ }
+ f.wbuf = append(f.wbuf, p.BlockFragment...)
+ f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
+ return f.endWrite()
+}
+
+// A PriorityFrame specifies the sender-advised priority of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.3
+type PriorityFrame struct {
+ FrameHeader
+ PriorityParam
+}
+
+// PriorityParam are the stream prioritzation parameters.
+type PriorityParam struct {
+ // StreamDep is a 31-bit stream identifier for the
+ // stream that this stream depends on. Zero means no
+ // dependency.
+ StreamDep uint32
+
+ // Exclusive is whether the dependency is exclusive.
+ Exclusive bool
+
+ // Weight is the stream's zero-indexed weight. It should be
+ // set together with StreamDep, or neither should be set. Per
+ // the spec, "Add one to the value to obtain a weight between
+ // 1 and 256."
+ Weight uint8
+}
+
+func (p PriorityParam) IsZero() bool {
+ return p == PriorityParam{}
+}
+
+func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
+ }
+ if len(payload) != 5 {
+ return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
+ }
+ v := binary.BigEndian.Uint32(payload[:4])
+ streamID := v & 0x7fffffff // mask off high bit
+ return &PriorityFrame{
+ FrameHeader: fh,
+ PriorityParam: PriorityParam{
+ Weight: payload[4],
+ StreamDep: streamID,
+ Exclusive: streamID != v, // was high bit set?
+ },
+ }, nil
+}
+
+// WritePriority writes a PRIORITY frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ if !validStreamIDOrZero(p.StreamDep) {
+ return errDepStreamID
+ }
+ f.startWrite(FramePriority, 0, streamID)
+ v := p.StreamDep
+ if p.Exclusive {
+ v |= 1 << 31
+ }
+ f.writeUint32(v)
+ f.writeByte(p.Weight)
+ return f.endWrite()
+}
+
+// A RSTStreamFrame allows for abnormal termination of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.4
+type RSTStreamFrame struct {
+ FrameHeader
+ ErrCode ErrCode
+}
+
+func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if len(p) != 4 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID == 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
+}
+
+// WriteRSTStream writes a RST_STREAM frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ f.startWrite(FrameRSTStream, 0, streamID)
+ f.writeUint32(uint32(code))
+ return f.endWrite()
+}
+
+// A ContinuationFrame is used to continue a sequence of header block fragments.
+// See http://http2.github.io/http2-spec/#rfc.section.6.10
+type ContinuationFrame struct {
+ FrameHeader
+ headerFragBuf []byte
+}
+
+func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
+ }
+ return &ContinuationFrame{fh, p}, nil
+}
+
+func (f *ContinuationFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *ContinuationFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagContinuationEndHeaders)
+}
+
+// WriteContinuation writes a CONTINUATION frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if endHeaders {
+ flags |= FlagContinuationEndHeaders
+ }
+ f.startWrite(FrameContinuation, flags, streamID)
+ f.wbuf = append(f.wbuf, headerBlockFragment...)
+ return f.endWrite()
+}
+
+// A PushPromiseFrame is used to initiate a server stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.6
+type PushPromiseFrame struct {
+ FrameHeader
+ PromiseID uint32
+ headerFragBuf []byte // not owned
+}
+
+func (f *PushPromiseFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *PushPromiseFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
+}
+
+func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
+ pp := &PushPromiseFrame{
+ FrameHeader: fh,
+ }
+ if pp.StreamID == 0 {
+ // PUSH_PROMISE frames MUST be associated with an existing,
+ // peer-initiated stream. The stream identifier of a
+ // PUSH_PROMISE frame indicates the stream it is associated
+ // with. If the stream identifier field specifies the value
+ // 0x0, a recipient MUST respond with a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ // The PUSH_PROMISE frame includes optional padding.
+ // Padding fields and flags are identical to those defined for DATA frames
+ var padLength uint8
+ if fh.Flags.Has(FlagPushPromisePadded) {
+ if p, padLength, err = readByte(p); err != nil {
+ return
+ }
+ }
+
+ p, pp.PromiseID, err = readUint32(p)
+ if err != nil {
+ return
+ }
+ pp.PromiseID = pp.PromiseID & (1<<31 - 1)
+
+ if int(padLength) > len(p) {
+ // like the DATA frame, error out if padding is longer than the body.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ pp.headerFragBuf = p[:len(p)-int(padLength)]
+ return pp, nil
+}
+
+// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
+type PushPromiseParam struct {
+ // StreamID is the required Stream ID to initiate.
+ StreamID uint32
+
+ // PromiseID is the required Stream ID which this
+ // Push Promises
+ PromiseID uint32
+
+ // BlockFragment is part (or all) of a Header Block.
+ BlockFragment []byte
+
+ // EndHeaders indicates that this frame contains an entire
+ // header block and is not followed by any
+ // CONTINUATION frames.
+ EndHeaders bool
+
+ // PadLength is the optional number of bytes of zeros to add
+ // to this frame.
+ PadLength uint8
+}
+
+// WritePushPromise writes a single PushPromise Frame.
+//
+// As with Header Frames, This is the low level call for writing
+// individual frames. Continuation frames are handled elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WritePushPromise(p PushPromiseParam) error {
+ if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if p.PadLength != 0 {
+ flags |= FlagPushPromisePadded
+ }
+ if p.EndHeaders {
+ flags |= FlagPushPromiseEndHeaders
+ }
+ f.startWrite(FramePushPromise, flags, p.StreamID)
+ if p.PadLength != 0 {
+ f.writeByte(p.PadLength)
+ }
+ if !validStreamID(p.PromiseID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ f.writeUint32(p.PromiseID)
+ f.wbuf = append(f.wbuf, p.BlockFragment...)
+ f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
+ return f.endWrite()
+}
+
+// WriteRawFrame writes a raw frame. This can be used to write
+// extension frames unknown to this package.
+func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint32, payload []byte) error {
+ f.startWrite(t, flags, streamID)
+ f.writeBytes(payload)
+ return f.endWrite()
+}
+
+func readByte(p []byte) (remain []byte, b byte, err error) {
+ if len(p) == 0 {
+ return nil, 0, io.ErrUnexpectedEOF
+ }
+ return p[1:], p[0], nil
+}
+
+func readUint32(p []byte) (remain []byte, v uint32, err error) {
+ if len(p) < 4 {
+ return nil, 0, io.ErrUnexpectedEOF
+ }
+ return p[4:], binary.BigEndian.Uint32(p[:4]), nil
+}
+
+type streamEnder interface {
+ StreamEnded() bool
+}
+
+type headersEnder interface {
+ HeadersEnded() bool
+}
+
+type headersOrContinuation interface {
+ headersEnder
+ HeaderBlockFragment() []byte
+}
+
+// A MetaHeadersFrame is the representation of one HEADERS frame and
+// zero or more contiguous CONTINUATION frames and the decoding of
+// their HPACK-encoded contents.
+//
+// This type of frame does not appear on the wire and is only returned
+// by the Framer when Framer.ReadMetaHeaders is set.
+type MetaHeadersFrame struct {
+ *HeadersFrame
+
+ // Fields are the fields contained in the HEADERS and
+ // CONTINUATION frames. The underlying slice is owned by the
+ // Framer and must not be retained after the next call to
+ // ReadFrame.
+ //
+ // Fields are guaranteed to be in the correct http2 order and
+ // not have unknown pseudo header fields or invalid header
+ // field names or values. Required pseudo header fields may be
+ // missing, however. Use the MetaHeadersFrame.Pseudo accessor
+ // method access pseudo headers.
+ Fields []hpack.HeaderField
+
+ // Truncated is whether the max header list size limit was hit
+ // and Fields is incomplete. The hpack decoder state is still
+ // valid, however.
+ Truncated bool
+}
+
+// PseudoValue returns the given pseudo header field's value.
+// The provided pseudo field should not contain the leading colon.
+func (mh *MetaHeadersFrame) PseudoValue(pseudo string) string {
+ for _, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return ""
+ }
+ if hf.Name[1:] == pseudo {
+ return hf.Value
+ }
+ }
+ return ""
+}
+
+// RegularFields returns the regular (non-pseudo) header fields of mh.
+// The caller does not own the returned slice.
+func (mh *MetaHeadersFrame) RegularFields() []hpack.HeaderField {
+ for i, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return mh.Fields[i:]
+ }
+ }
+ return nil
+}
+
+// PseudoFields returns the pseudo header fields of mh.
+// The caller does not own the returned slice.
+func (mh *MetaHeadersFrame) PseudoFields() []hpack.HeaderField {
+ for i, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return mh.Fields[:i]
+ }
+ }
+ return mh.Fields
+}
+
+func (mh *MetaHeadersFrame) checkPseudos() error {
+ var isRequest, isResponse bool
+ pf := mh.PseudoFields()
+ for i, hf := range pf {
+ switch hf.Name {
+ case ":method", ":path", ":scheme", ":authority":
+ isRequest = true
+ case ":status":
+ isResponse = true
+ default:
+ return pseudoHeaderError(hf.Name)
+ }
+ // Check for duplicates.
+ // This would be a bad algorithm, but N is 4.
+ // And this doesn't allocate.
+ for _, hf2 := range pf[:i] {
+ if hf.Name == hf2.Name {
+ return duplicatePseudoHeaderError(hf.Name)
+ }
+ }
+ }
+ if isRequest && isResponse {
+ return errMixPseudoHeaderTypes
+ }
+ return nil
+}
+
+func (fr *Framer) maxHeaderStringLen() int {
+ v := fr.maxHeaderListSize()
+ if uint32(int(v)) == v {
+ return int(v)
+ }
+ // They had a crazy big number for MaxHeaderBytes anyway,
+ // so give them unlimited header lengths:
+ return 0
+}
+
+// readMetaFrame returns 0 or more CONTINUATION frames from fr and
+// merge them into into the provided hf and returns a MetaHeadersFrame
+// with the decoded hpack values.
+func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
+ if fr.AllowIllegalReads {
+ return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
+ }
+ mh := &MetaHeadersFrame{
+ HeadersFrame: hf,
+ }
+ var remainSize = fr.maxHeaderListSize()
+ var sawRegular bool
+
+ var invalid error // pseudo header field errors
+ hdec := fr.ReadMetaHeaders
+ hdec.SetEmitEnabled(true)
+ hdec.SetMaxStringLength(fr.maxHeaderStringLen())
+ hdec.SetEmitFunc(func(hf hpack.HeaderField) {
+ if VerboseLogs && fr.logReads {
+ fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
+ }
+ if !httplex.ValidHeaderFieldValue(hf.Value) {
+ invalid = headerFieldValueError(hf.Value)
+ }
+ isPseudo := strings.HasPrefix(hf.Name, ":")
+ if isPseudo {
+ if sawRegular {
+ invalid = errPseudoAfterRegular
+ }
+ } else {
+ sawRegular = true
+ if !validWireHeaderFieldName(hf.Name) {
+ invalid = headerFieldNameError(hf.Name)
+ }
+ }
+
+ if invalid != nil {
+ hdec.SetEmitEnabled(false)
+ return
+ }
+
+ size := hf.Size()
+ if size > remainSize {
+ hdec.SetEmitEnabled(false)
+ mh.Truncated = true
+ return
+ }
+ remainSize -= size
+
+ mh.Fields = append(mh.Fields, hf)
+ })
+ // Lose reference to MetaHeadersFrame:
+ defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {})
+
+ var hc headersOrContinuation = hf
+ for {
+ frag := hc.HeaderBlockFragment()
+ if _, err := hdec.Write(frag); err != nil {
+ return nil, ConnectionError(ErrCodeCompression)
+ }
+
+ if hc.HeadersEnded() {
+ break
+ }
+ if f, err := fr.ReadFrame(); err != nil {
+ return nil, err
+ } else {
+ hc = f.(*ContinuationFrame) // guaranteed by checkFrameOrder
+ }
+ }
+
+ mh.HeadersFrame.headerFragBuf = nil
+ mh.HeadersFrame.invalidate()
+
+ if err := hdec.Close(); err != nil {
+ return nil, ConnectionError(ErrCodeCompression)
+ }
+ if invalid != nil {
+ fr.errDetail = invalid
+ if VerboseLogs {
+ log.Printf("http2: invalid header: %v", invalid)
+ }
+ return nil, StreamError{mh.StreamID, ErrCodeProtocol, invalid}
+ }
+ if err := mh.checkPseudos(); err != nil {
+ fr.errDetail = err
+ if VerboseLogs {
+ log.Printf("http2: invalid pseudo headers: %v", err)
+ }
+ return nil, StreamError{mh.StreamID, ErrCodeProtocol, err}
+ }
+ return mh, nil
+}
+
+func summarizeFrame(f Frame) string {
+ var buf bytes.Buffer
+ f.Header().writeDebug(&buf)
+ switch f := f.(type) {
+ case *SettingsFrame:
+ n := 0
+ f.ForeachSetting(func(s Setting) error {
+ n++
+ if n == 1 {
+ buf.WriteString(", settings:")
+ }
+ fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val)
+ return nil
+ })
+ if n > 0 {
+ buf.Truncate(buf.Len() - 1) // remove trailing comma
+ }
+ case *DataFrame:
+ data := f.Data()
+ const max = 256
+ if len(data) > max {
+ data = data[:max]
+ }
+ fmt.Fprintf(&buf, " data=%q", data)
+ if len(f.Data()) > max {
+ fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max)
+ }
+ case *WindowUpdateFrame:
+ if f.StreamID == 0 {
+ buf.WriteString(" (conn)")
+ }
+ fmt.Fprintf(&buf, " incr=%v", f.Increment)
+ case *PingFrame:
+ fmt.Fprintf(&buf, " ping=%q", f.Data[:])
+ case *GoAwayFrame:
+ fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q",
+ f.LastStreamID, f.ErrCode, f.debugData)
+ case *RSTStreamFrame:
+ fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode)
+ }
+ return buf.String()
+}
diff --git a/vendor/golang.org/x/net/http2/go16.go b/vendor/golang.org/x/net/http2/go16.go
new file mode 100644
index 0000000..00b2e9e
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/go16.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.6
+
+package http2
+
+import (
+ "net/http"
+ "time"
+)
+
+func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
+ return t1.ExpectContinueTimeout
+}
diff --git a/vendor/golang.org/x/net/http2/go17.go b/vendor/golang.org/x/net/http2/go17.go
new file mode 100644
index 0000000..47b7fae
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/go17.go
@@ -0,0 +1,106 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+package http2
+
+import (
+ "context"
+ "net"
+ "net/http"
+ "net/http/httptrace"
+ "time"
+)
+
+type contextContext interface {
+ context.Context
+}
+
+func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
+ ctx, cancel = context.WithCancel(context.Background())
+ ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
+ if hs := opts.baseConfig(); hs != nil {
+ ctx = context.WithValue(ctx, http.ServerContextKey, hs)
+ }
+ return
+}
+
+func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
+ return context.WithCancel(ctx)
+}
+
+func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
+ return req.WithContext(ctx)
+}
+
+type clientTrace httptrace.ClientTrace
+
+func reqContext(r *http.Request) context.Context { return r.Context() }
+
+func (t *Transport) idleConnTimeout() time.Duration {
+ if t.t1 != nil {
+ return t.t1.IdleConnTimeout
+ }
+ return 0
+}
+
+func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }
+
+func traceGotConn(req *http.Request, cc *ClientConn) {
+ trace := httptrace.ContextClientTrace(req.Context())
+ if trace == nil || trace.GotConn == nil {
+ return
+ }
+ ci := httptrace.GotConnInfo{Conn: cc.tconn}
+ cc.mu.Lock()
+ ci.Reused = cc.nextStreamID > 1
+ ci.WasIdle = len(cc.streams) == 0 && ci.Reused
+ if ci.WasIdle && !cc.lastActive.IsZero() {
+ ci.IdleTime = time.Now().Sub(cc.lastActive)
+ }
+ cc.mu.Unlock()
+
+ trace.GotConn(ci)
+}
+
+func traceWroteHeaders(trace *clientTrace) {
+ if trace != nil && trace.WroteHeaders != nil {
+ trace.WroteHeaders()
+ }
+}
+
+func traceGot100Continue(trace *clientTrace) {
+ if trace != nil && trace.Got100Continue != nil {
+ trace.Got100Continue()
+ }
+}
+
+func traceWait100Continue(trace *clientTrace) {
+ if trace != nil && trace.Wait100Continue != nil {
+ trace.Wait100Continue()
+ }
+}
+
+func traceWroteRequest(trace *clientTrace, err error) {
+ if trace != nil && trace.WroteRequest != nil {
+ trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
+ }
+}
+
+func traceFirstResponseByte(trace *clientTrace) {
+ if trace != nil && trace.GotFirstResponseByte != nil {
+ trace.GotFirstResponseByte()
+ }
+}
+
+func requestTrace(req *http.Request) *clientTrace {
+ trace := httptrace.ContextClientTrace(req.Context())
+ return (*clientTrace)(trace)
+}
+
+// Ping sends a PING frame to the server and waits for the ack.
+func (cc *ClientConn) Ping(ctx context.Context) error {
+ return cc.ping(ctx)
+}
diff --git a/vendor/golang.org/x/net/http2/go17_not18.go b/vendor/golang.org/x/net/http2/go17_not18.go
new file mode 100644
index 0000000..b4c52ec
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/go17_not18.go
@@ -0,0 +1,36 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7,!go1.8
+
+package http2
+
+import "crypto/tls"
+
+// temporary copy of Go 1.7's private tls.Config.clone:
+func cloneTLSConfig(c *tls.Config) *tls.Config {
+ return &tls.Config{
+ Rand: c.Rand,
+ Time: c.Time,
+ Certificates: c.Certificates,
+ NameToCertificate: c.NameToCertificate,
+ GetCertificate: c.GetCertificate,
+ RootCAs: c.RootCAs,
+ NextProtos: c.NextProtos,
+ ServerName: c.ServerName,
+ ClientAuth: c.ClientAuth,
+ ClientCAs: c.ClientCAs,
+ InsecureSkipVerify: c.InsecureSkipVerify,
+ CipherSuites: c.CipherSuites,
+ PreferServerCipherSuites: c.PreferServerCipherSuites,
+ SessionTicketsDisabled: c.SessionTicketsDisabled,
+ SessionTicketKey: c.SessionTicketKey,
+ ClientSessionCache: c.ClientSessionCache,
+ MinVersion: c.MinVersion,
+ MaxVersion: c.MaxVersion,
+ CurvePreferences: c.CurvePreferences,
+ DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
+ Renegotiation: c.Renegotiation,
+ }
+}
diff --git a/vendor/golang.org/x/net/http2/go18.go b/vendor/golang.org/x/net/http2/go18.go
new file mode 100644
index 0000000..4f30d22
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/go18.go
@@ -0,0 +1,56 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.8
+
+package http2
+
+import (
+ "crypto/tls"
+ "io"
+ "net/http"
+)
+
+func cloneTLSConfig(c *tls.Config) *tls.Config {
+ c2 := c.Clone()
+ c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264
+ return c2
+}
+
+var _ http.Pusher = (*responseWriter)(nil)
+
+// Push implements http.Pusher.
+func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
+ internalOpts := pushOptions{}
+ if opts != nil {
+ internalOpts.Method = opts.Method
+ internalOpts.Header = opts.Header
+ }
+ return w.push(target, internalOpts)
+}
+
+func configureServer18(h1 *http.Server, h2 *Server) error {
+ if h2.IdleTimeout == 0 {
+ if h1.IdleTimeout != 0 {
+ h2.IdleTimeout = h1.IdleTimeout
+ } else {
+ h2.IdleTimeout = h1.ReadTimeout
+ }
+ }
+ return nil
+}
+
+func shouldLogPanic(panicValue interface{}) bool {
+ return panicValue != nil && panicValue != http.ErrAbortHandler
+}
+
+func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
+ return req.GetBody
+}
+
+func reqBodyIsNoBody(body io.ReadCloser) bool {
+ return body == http.NoBody
+}
+
+func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only
diff --git a/vendor/golang.org/x/net/http2/go19.go b/vendor/golang.org/x/net/http2/go19.go
new file mode 100644
index 0000000..38124ba
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/go19.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package http2
+
+import (
+ "net/http"
+)
+
+func configureServer19(s *http.Server, conf *Server) error {
+ s.RegisterOnShutdown(conf.state.startGracefulShutdown)
+ return nil
+}
diff --git a/vendor/golang.org/x/net/http2/gotrack.go b/vendor/golang.org/x/net/http2/gotrack.go
new file mode 100644
index 0000000..9933c9f
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/gotrack.go
@@ -0,0 +1,170 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Defensive debug-only utility to track that functions run on the
+// goroutine that they're supposed to.
+
+package http2
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "os"
+ "runtime"
+ "strconv"
+ "sync"
+)
+
+var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
+
+type goroutineLock uint64
+
+func newGoroutineLock() goroutineLock {
+ if !DebugGoroutines {
+ return 0
+ }
+ return goroutineLock(curGoroutineID())
+}
+
+func (g goroutineLock) check() {
+ if !DebugGoroutines {
+ return
+ }
+ if curGoroutineID() != uint64(g) {
+ panic("running on the wrong goroutine")
+ }
+}
+
+func (g goroutineLock) checkNotOn() {
+ if !DebugGoroutines {
+ return
+ }
+ if curGoroutineID() == uint64(g) {
+ panic("running on the wrong goroutine")
+ }
+}
+
+var goroutineSpace = []byte("goroutine ")
+
+func curGoroutineID() uint64 {
+ bp := littleBuf.Get().(*[]byte)
+ defer littleBuf.Put(bp)
+ b := *bp
+ b = b[:runtime.Stack(b, false)]
+ // Parse the 4707 out of "goroutine 4707 ["
+ b = bytes.TrimPrefix(b, goroutineSpace)
+ i := bytes.IndexByte(b, ' ')
+ if i < 0 {
+ panic(fmt.Sprintf("No space found in %q", b))
+ }
+ b = b[:i]
+ n, err := parseUintBytes(b, 10, 64)
+ if err != nil {
+ panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
+ }
+ return n
+}
+
+var littleBuf = sync.Pool{
+ New: func() interface{} {
+ buf := make([]byte, 64)
+ return &buf
+ },
+}
+
+// parseUintBytes is like strconv.ParseUint, but using a []byte.
+func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
+ var cutoff, maxVal uint64
+
+ if bitSize == 0 {
+ bitSize = int(strconv.IntSize)
+ }
+
+ s0 := s
+ switch {
+ case len(s) < 1:
+ err = strconv.ErrSyntax
+ goto Error
+
+ case 2 <= base && base <= 36:
+ // valid base; nothing to do
+
+ case base == 0:
+ // Look for octal, hex prefix.
+ switch {
+ case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
+ base = 16
+ s = s[2:]
+ if len(s) < 1 {
+ err = strconv.ErrSyntax
+ goto Error
+ }
+ case s[0] == '0':
+ base = 8
+ default:
+ base = 10
+ }
+
+ default:
+ err = errors.New("invalid base " + strconv.Itoa(base))
+ goto Error
+ }
+
+ n = 0
+ cutoff = cutoff64(base)
+ maxVal = 1<= base {
+ n = 0
+ err = strconv.ErrSyntax
+ goto Error
+ }
+
+ if n >= cutoff {
+ // n*base overflows
+ n = 1<<64 - 1
+ err = strconv.ErrRange
+ goto Error
+ }
+ n *= uint64(base)
+
+ n1 := n + uint64(v)
+ if n1 < n || n1 > maxVal {
+ // n+v overflows
+ n = 1<<64 - 1
+ err = strconv.ErrRange
+ goto Error
+ }
+ n = n1
+ }
+
+ return n, nil
+
+Error:
+ return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
+}
+
+// Return the first number n such that n*base >= 1<<64.
+func cutoff64(base int) uint64 {
+ if base < 2 {
+ return 0
+ }
+ return (1<<64-1)/uint64(base) + 1
+}
diff --git a/vendor/golang.org/x/net/http2/h2demo/Makefile b/vendor/golang.org/x/net/http2/h2demo/Makefile
new file mode 100644
index 0000000..f5c31ef
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/h2demo/Makefile
@@ -0,0 +1,8 @@
+h2demo.linux: h2demo.go
+ GOOS=linux go build --tags=h2demo -o h2demo.linux .
+
+FORCE:
+
+upload: FORCE
+ go install golang.org/x/build/cmd/upload
+ upload --verbose --osarch=linux-amd64 --tags=h2demo --file=go:golang.org/x/net/http2/h2demo --public http2-demo-server-tls/h2demo
diff --git a/vendor/golang.org/x/net/http2/h2demo/README b/vendor/golang.org/x/net/http2/h2demo/README
new file mode 100644
index 0000000..212a96f
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/h2demo/README
@@ -0,0 +1,16 @@
+
+Client:
+ -- Firefox nightly with about:config network.http.spdy.enabled.http2draft set true
+ -- Chrome: go to chrome://flags/#enable-spdy4, save and restart (button at bottom)
+
+Make CA:
+$ openssl genrsa -out rootCA.key 2048
+$ openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem
+... install that to Firefox
+
+Make cert:
+$ openssl genrsa -out server.key 2048
+$ openssl req -new -key server.key -out server.csr
+$ openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500
+
+
diff --git a/vendor/golang.org/x/net/http2/h2demo/h2demo.go b/vendor/golang.org/x/net/http2/h2demo/h2demo.go
new file mode 100644
index 0000000..9853107
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/h2demo/h2demo.go
@@ -0,0 +1,538 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build h2demo
+
+package main
+
+import (
+ "bytes"
+ "crypto/tls"
+ "flag"
+ "fmt"
+ "hash/crc32"
+ "image"
+ "image/jpeg"
+ "io"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/http"
+ "os"
+ "path"
+ "regexp"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "go4.org/syncutil/singleflight"
+ "golang.org/x/crypto/acme/autocert"
+ "golang.org/x/net/http2"
+)
+
+var (
+ prod = flag.Bool("prod", false, "Whether to configure itself to be the production http2.golang.org server.")
+
+ httpsAddr = flag.String("https_addr", "localhost:4430", "TLS address to listen on ('host:port' or ':port'). Required.")
+ httpAddr = flag.String("http_addr", "", "Plain HTTP address to listen on ('host:port', or ':port'). Empty means no HTTP.")
+
+ hostHTTP = flag.String("http_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -http_addr.")
+ hostHTTPS = flag.String("https_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -https_addr.")
+)
+
+func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, `
+
+
build compile packages and dependencies
+clean remove object files
+doc show documentation for package or symbol
+env print Go environment information
+bug start a bug report
+fix run go tool fix on packages
+fmt run gofmt on package sources
+generate generate Go files by processing source
+get download and install packages and dependencies
+install compile and install packages and dependencies
+list list packages
+run compile and run Go program
+test test packages
+tool run specified go tool
+version print Go version
+vet run go tool vet on packages
+
+
+Use "go help [command]" for more information about a command.
+
+
+Additional help topics:
+
+
c calling between Go and C
+buildmode description of build modes
+filetype file types
+gopath GOPATH environment variable
+environment environment variables
+importpath import path syntax
+packages description of package lists
+testflag description of testing flags
+testfunc description of testing functions
+
+
+Use "go help [topic]" for more information about that topic.
+
+
Compile packages and dependencies
+
+Usage:
+
+
go build [-o output] [-i] [build flags] [packages]
+
+
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+
+If the arguments to build are a list of .go files, build treats
+them as a list of source files specifying a single package.
+
+
+When compiling a single main package, build writes
+the resulting executable to an output file named after
+the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
+or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').
+The '.exe' suffix is added when writing a Windows executable.
+
+
+When compiling multiple packages or a single non-main package,
+build compiles the packages but discards the resulting object,
+serving only as a check that the packages can be built.
+
+
+When compiling packages, build ignores files that end in '_test.go'.
+
+
+The -o flag, only allowed when compiling a single package,
+forces build to write the resulting executable or object
+to the named output file, instead of the default behavior described
+in the last two paragraphs.
+
+
+The -i flag installs the packages that are dependencies of the target.
+
+
+The build flags are shared by the build, clean, get, install, list, run,
+and test commands:
+
+
-a
+ force rebuilding of packages that are already up-to-date.
+-n
+ print the commands but do not run them.
+-p n
+ the number of programs, such as build commands or
+ test binaries, that can be run in parallel.
+ The default is the number of CPUs available.
+-race
+ enable data race detection.
+ Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
+-msan
+ enable interoperation with memory sanitizer.
+ Supported only on linux/amd64,
+ and only with Clang/LLVM as the host C compiler.
+-v
+ print the names of packages as they are compiled.
+-work
+ print the name of the temporary work directory and
+ do not delete it when exiting.
+-x
+ print the commands.
+
+-asmflags 'flag list'
+ arguments to pass on each go tool asm invocation.
+-buildmode mode
+ build mode to use. See 'go help buildmode' for more.
+-compiler name
+ name of compiler to use, as in runtime.Compiler (gccgo or gc).
+-gccgoflags 'arg list'
+ arguments to pass on each gccgo compiler/linker invocation.
+-gcflags 'arg list'
+ arguments to pass on each go tool compile invocation.
+-installsuffix suffix
+ a suffix to use in the name of the package installation directory,
+ in order to keep output separate from default builds.
+ If using the -race flag, the install suffix is automatically set to race
+ or, if set explicitly, has _race appended to it. Likewise for the -msan
+ flag. Using a -buildmode option that requires non-default compile flags
+ has a similar effect.
+-ldflags 'flag list'
+ arguments to pass on each go tool link invocation.
+-linkshared
+ link against shared libraries previously created with
+ -buildmode=shared.
+-pkgdir dir
+ install and load all packages from dir instead of the usual locations.
+ For example, when building with a non-standard configuration,
+ use -pkgdir to keep generated packages in a separate location.
+-tags 'tag list'
+ a list of build tags to consider satisfied during the build.
+ For more information about build tags, see the description of
+ build constraints in the documentation for the go/build package.
+-toolexec 'cmd args'
+ a program to use to invoke toolchain programs like vet and asm.
+ For example, instead of running asm, the go command will run
+ 'cmd args /path/to/asm <arguments for asm>'.
+
+
+The list flags accept a space-separated list of strings. To embed spaces
+in an element in the list, surround it with either single or double quotes.
+
+
+For more about specifying packages, see 'go help packages'.
+For more about where packages and binaries are installed,
+run 'go help gopath'.
+For more about calling between Go and C/C++, run 'go help c'.
+
+
+Note: Build adheres to certain conventions such as those described
+by 'go help gopath'. Not all projects can follow these conventions,
+however. Installations that have their own conventions or that use
+a separate software build system may choose to use lower-level
+invocations such as 'go tool compile' and 'go tool link' to avoid
+some of the overheads and design decisions of the build tool.
+
+
+See also: go install, go get, go clean.
+
+
Remove object files
+
+Usage:
+
+
go clean [-i] [-r] [-n] [-x] [build flags] [packages]
+
+
+Clean removes object files from package source directories.
+The go command builds most objects in a temporary directory,
+so go clean is mainly concerned with object files left by other
+tools or by manual invocations of go build.
+
+
+Specifically, clean removes the following files from each of the
+source directories corresponding to the import paths:
+
+
_obj/ old object directory, left from Makefiles
+_test/ old test directory, left from Makefiles
+_testmain.go old gotest file, left from Makefiles
+test.out old test log, left from Makefiles
+build.out old test log, left from Makefiles
+*.[568ao] object files, left from Makefiles
+
+DIR(.exe) from go build
+DIR.test(.exe) from go test -c
+MAINFILE(.exe) from go build MAINFILE.go
+*.so from SWIG
+
+
+In the list, DIR represents the final path element of the
+directory, and MAINFILE is the base name of any Go source
+file in the directory that is not included when building
+the package.
+
+
+The -i flag causes clean to remove the corresponding installed
+archive or binary (what 'go install' would create).
+
+
+The -n flag causes clean to print the remove commands it would execute,
+but not run them.
+
+
+The -r flag causes clean to be applied recursively to all the
+dependencies of the packages named by the import paths.
+
+
+The -x flag causes clean to print remove commands as it executes them.
+
+
+For more about build flags, see 'go help build'.
+
+
+For more about specifying packages, see 'go help packages'.
+
+
Show documentation for package or symbol
+
+Usage:
+
+
go doc [-u] [-c] [package|[package.]symbol[.method]]
+
+
+Doc prints the documentation comments associated with the item identified by its
+arguments (a package, const, func, type, var, or method) followed by a one-line
+summary of each of the first-level items "under" that item (package-level
+declarations for a package, methods for a type, etc.).
+
+
+Doc accepts zero, one, or two arguments.
+
+
+Given no arguments, that is, when run as
+
+
go doc
+
+
+it prints the package documentation for the package in the current directory.
+If the package is a command (package main), the exported symbols of the package
+are elided from the presentation unless the -cmd flag is provided.
+
+
+When run with one argument, the argument is treated as a Go-syntax-like
+representation of the item to be documented. What the argument selects depends
+on what is installed in GOROOT and GOPATH, as well as the form of the argument,
+which is schematically one of these:
+
+The first item in this list matched by the argument is the one whose documentation
+is printed. (See the examples below.) However, if the argument starts with a capital
+letter it is assumed to identify a symbol or method in the current directory.
+
+
+For packages, the order of scanning is determined lexically in breadth-first order.
+That is, the package presented is the one that matches the search and is nearest
+the root and lexically first at its level of the hierarchy. The GOROOT tree is
+always scanned in its entirety before GOPATH.
+
+
+If there is no package specified or matched, the package in the current
+directory is selected, so "go doc Foo" shows the documentation for symbol Foo in
+the current package.
+
+
+The package path must be either a qualified path or a proper suffix of a
+path. The go tool's usual package mechanism does not apply: package path
+elements like . and ... are not implemented by go doc.
+
+
+When run with two arguments, the first must be a full package path (not just a
+suffix), and the second is a symbol or symbol and method; this is similar to the
+syntax accepted by godoc:
+
+
go doc <pkg> <sym>[.<method>]
+
+
+In all forms, when matching symbols, lower-case letters in the argument match
+either case but upper-case letters match exactly. This means that there may be
+multiple matches of a lower-case argument in a package if different symbols have
+different cases. If this occurs, documentation for all matches is printed.
+
+
+Examples:
+
+
go doc
+ Show documentation for current package.
+go doc Foo
+ Show documentation for Foo in the current package.
+ (Foo starts with a capital letter so it cannot match
+ a package path.)
+go doc encoding/json
+ Show documentation for the encoding/json package.
+go doc json
+ Shorthand for encoding/json.
+go doc json.Number (or go doc json.number)
+ Show documentation and method summary for json.Number.
+go doc json.Number.Int64 (or go doc json.number.int64)
+ Show documentation for json.Number's Int64 method.
+go doc cmd/doc
+ Show package docs for the doc command.
+go doc -cmd cmd/doc
+ Show package docs and exported symbols within the doc command.
+go doc template.new
+ Show documentation for html/template's New function.
+ (html/template is lexically before text/template)
+go doc text/template.new # One argument
+ Show documentation for text/template's New function.
+go doc text/template new # Two arguments
+ Show documentation for text/template's New function.
+
+At least in the current tree, these invocations all print the
+documentation for json.Decoder's Decode method:
+
+go doc json.Decoder.Decode
+go doc json.decoder.decode
+go doc json.decode
+cd go/src/encoding/json; go doc decode
+
+
+Flags:
+
+
-c
+ Respect case when matching symbols.
+-cmd
+ Treat a command (package main) like a regular package.
+ Otherwise package main's exported symbols are hidden
+ when showing the package's top-level documentation.
+-u
+ Show documentation for unexported as well as exported
+ symbols and methods.
+
+
Print Go environment information
+
+Usage:
+
+
go env [var ...]
+
+
+Env prints Go environment information.
+
+
+By default env prints information as a shell script
+(on Windows, a batch file). If one or more variable
+names is given as arguments, env prints the value of
+each named variable on its own line.
+
+
Start a bug report
+
+Usage:
+
+
go bug
+
+
+Bug opens the default browser and starts a new bug report.
+The report includes useful system information.
+
+
Run go tool fix on packages
+
+Usage:
+
+
go fix [packages]
+
+
+Fix runs the Go fix command on the packages named by the import paths.
+
+
+For more about fix, see 'go doc cmd/fix'.
+For more about specifying packages, see 'go help packages'.
+
+
+To run fix with specific options, run 'go tool fix'.
+
+
+See also: go fmt, go vet.
+
+
Run gofmt on package sources
+
+Usage:
+
+
go fmt [-n] [-x] [packages]
+
+
+Fmt runs the command 'gofmt -l -w' on the packages named
+by the import paths. It prints the names of the files that are modified.
+
+
+For more about gofmt, see 'go doc cmd/gofmt'.
+For more about specifying packages, see 'go help packages'.
+
+
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+
+To run gofmt with specific options, run gofmt itself.
+
+Generate runs commands described by directives within existing
+files. Those commands can run any process but the intent is to
+create or update Go source files.
+
+
+Go generate is never run automatically by go build, go get, go test,
+and so on. It must be run explicitly.
+
+
+Go generate scans the file for directives, which are lines of
+the form,
+
+
//go:generate command argument...
+
+
+(note: no leading spaces and no space in "//go") where command
+is the generator to be run, corresponding to an executable file
+that can be run locally. It must either be in the shell path
+(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
+command alias, described below.
+
+
+Note that go generate does not parse the file, so lines that look
+like directives in comments or multiline strings will be treated
+as directives.
+
+
+The arguments to the directive are space-separated tokens or
+double-quoted strings passed to the generator as individual
+arguments when it is run.
+
+
+Quoted strings use Go syntax and are evaluated before execution; a
+quoted string appears as a single argument to the generator.
+
+
+Go generate sets several variables when it runs the generator:
+
+
$GOARCH
+ The execution architecture (arm, amd64, etc.)
+$GOOS
+ The execution operating system (linux, windows, etc.)
+$GOFILE
+ The base name of the file.
+$GOLINE
+ The line number of the directive in the source file.
+$GOPACKAGE
+ The name of the package of the file containing the directive.
+$DOLLAR
+ A dollar sign.
+
+
+Other than variable substitution and quoted-string evaluation, no
+special processing such as "globbing" is performed on the command
+line.
+
+
+As a last step before running the command, any invocations of any
+environment variables with alphanumeric names, such as $GOFILE or
+$HOME, are expanded throughout the command line. The syntax for
+variable expansion is $NAME on all operating systems. Due to the
+order of evaluation, variables are expanded even inside quoted
+strings. If the variable NAME is not set, $NAME expands to the
+empty string.
+
+
+A directive of the form,
+
+
//go:generate -command xxx args...
+
+
+specifies, for the remainder of this source file only, that the
+string xxx represents the command identified by the arguments. This
+can be used to create aliases or to handle multiword generators.
+For example,
+
+
//go:generate -command foo go tool foo
+
+
+specifies that the command "foo" represents the generator
+"go tool foo".
+
+
+Generate processes packages in the order given on the command line,
+one at a time. If the command line lists .go files, they are treated
+as a single package. Within a package, generate processes the
+source files in a package in file name order, one at a time. Within
+a source file, generate runs generators in the order they appear
+in the file, one at a time.
+
+
+If any generator returns an error exit status, "go generate" skips
+all further processing for that package.
+
+
+The generator is run in the package's source directory.
+
+
+Go generate accepts one specific flag:
+
+
-run=""
+ if non-empty, specifies a regular expression to select
+ directives whose full original source text (excluding
+ any trailing spaces and final newline) matches the
+ expression.
+
+
+It also accepts the standard build flags including -v, -n, and -x.
+The -v flag prints the names of packages and files as they are
+processed.
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+
+For more about build flags, see 'go help build'.
+
+
+For more about specifying packages, see 'go help packages'.
+
+
Download and install packages and dependencies
+
+Usage:
+
+
go get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]
+
+
+Get downloads the packages named by the import paths, along with their
+dependencies. It then installs the named packages, like 'go install'.
+
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+
+The -f flag, valid only when -u is set, forces get -u not to verify that
+each package has been checked out from the source control repository
+implied by its import path. This can be useful if the source is a local fork
+of the original.
+
+
+The -fix flag instructs get to run the fix tool on the downloaded packages
+before resolving dependencies or building the code.
+
+
+The -insecure flag permits fetching from repositories and resolving
+custom domains using insecure schemes such as HTTP. Use with caution.
+
+
+The -t flag instructs get to also download the packages required to build
+the tests for the specified packages.
+
+
+The -u flag instructs get to use the network to update the named packages
+and their dependencies. By default, get uses the network to check out
+missing packages but does not use it to look for updates to existing packages.
+
+
+The -v flag enables verbose progress and debug output.
+
+
+Get also accepts build flags to control the installation. See 'go help build'.
+
+
+When checking out a new package, get creates the target directory
+GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
+get uses the first one. For more details see: 'go help gopath'.
+
+
+When checking out or updating a package, get looks for a branch or tag
+that matches the locally installed version of Go. The most important
+rule is that if the local installation is running version "go1", get
+searches for a branch or tag named "go1". If no such version exists it
+retrieves the most recent version of the package.
+
+
+When go get checks out or updates a Git repository,
+it also updates any git submodules referenced by the repository.
+
+
+Get never checks out or updates code stored in vendor directories.
+
+
+For more about specifying packages, see 'go help packages'.
+
+
+For more about how 'go get' finds source code to
+download, see 'go help importpath'.
+
+
+See also: go build, go install, go clean.
+
+
Compile and install packages and dependencies
+
+Usage:
+
+
go install [build flags] [packages]
+
+
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+
+For more about the build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
+
+
+See also: go build, go get, go clean.
+
+
List packages
+
+Usage:
+
+
go list [-e] [-f format] [-json] [build flags] [packages]
+
+
+List lists the packages named by the import paths, one per line.
+
+
+The default output shows the package import path:
+
+The -f flag specifies an alternate format for the list, using the
+syntax of package template. The default output is equivalent to -f
+''. The struct being passed to the template is:
+
+
type Package struct {
+ Dir string // directory containing package sources
+ ImportPath string // import path of package in dir
+ ImportComment string // path in import comment on package statement
+ Name string // package name
+ Doc string // package documentation string
+ Target string // install path
+ Shlib string // the shared library that contains this package (only set when -linkshared)
+ Goroot bool // is this package in the Go root?
+ Standard bool // is this package part of the standard Go library?
+ Stale bool // would 'go install' do anything for this package?
+ StaleReason string // explanation for Stale==true
+ Root string // Go root or Go path dir containing this package
+ ConflictDir string // this directory shadows Dir in $GOPATH
+ BinaryOnly bool // binary-only package: cannot be recompiled from sources
+
+ // Source files
+ GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+ CgoFiles []string // .go sources files that import "C"
+ IgnoredGoFiles []string // .go sources ignored due to build constraints
+ CFiles []string // .c source files
+ CXXFiles []string // .cc, .cxx and .cpp source files
+ MFiles []string // .m source files
+ HFiles []string // .h, .hh, .hpp and .hxx source files
+ FFiles []string // .f, .F, .for and .f90 Fortran source files
+ SFiles []string // .s source files
+ SwigFiles []string // .swig files
+ SwigCXXFiles []string // .swigcxx files
+ SysoFiles []string // .syso object files to add to archive
+ TestGoFiles []string // _test.go files in package
+ XTestGoFiles []string // _test.go files outside package
+
+ // Cgo directives
+ CgoCFLAGS []string // cgo: flags for C compiler
+ CgoCPPFLAGS []string // cgo: flags for C preprocessor
+ CgoCXXFLAGS []string // cgo: flags for C++ compiler
+ CgoFFLAGS []string // cgo: flags for Fortran compiler
+ CgoLDFLAGS []string // cgo: flags for linker
+ CgoPkgConfig []string // cgo: pkg-config names
+
+ // Dependency information
+ Imports []string // import paths used by this package
+ Deps []string // all (recursively) imported dependencies
+ TestImports []string // imports from TestGoFiles
+ XTestImports []string // imports from XTestGoFiles
+
+ // Error information
+ Incomplete bool // this package or a dependency has an error
+ Error *PackageError // error loading package
+ DepsErrors []*PackageError // errors loading dependencies
+}
+
+
+Packages stored in vendor directories report an ImportPath that includes the
+path to the vendor directory (for example, "d/vendor/p" instead of "p"),
+so that the ImportPath uniquely identifies a given copy of a package.
+The Imports, Deps, TestImports, and XTestImports lists also contain these
+expanded imports paths. See golang.org/s/go15vendor for more about vendoring.
+
+
+The error information, if any, is
+
+
type PackageError struct {
+ ImportStack []string // shortest path from package named on command line to this one
+ Pos string // position of error (if present, file:line:col)
+ Err string // the error itself
+}
+
+
+The template function "join" calls strings.Join.
+
+
+The template function "context" returns the build context, defined as:
+
+
type Context struct {
+ GOARCH string // target architecture
+ GOOS string // target operating system
+ GOROOT string // Go root
+ GOPATH string // Go path
+ CgoEnabled bool // whether cgo can be used
+ UseAllFiles bool // use files regardless of +build lines, file names
+ Compiler string // compiler to assume when computing target paths
+ BuildTags []string // build constraints to match in +build lines
+ ReleaseTags []string // releases the current release is compatible with
+ InstallSuffix string // suffix to use in the name of the install dir
+}
+
+
+For more information about the meaning of these fields see the documentation
+for the go/build package's Context type.
+
+
+The -json flag causes the package data to be printed in JSON format
+instead of using the template format.
+
+
+The -e flag changes the handling of erroneous packages, those that
+cannot be found or are malformed. By default, the list command
+prints an error to standard error for each erroneous package and
+omits the packages from consideration during the usual printing.
+With the -e flag, the list command never prints errors to standard
+error and instead processes the erroneous packages with the usual
+printing. Erroneous packages will have a non-empty ImportPath and
+a non-nil Error field; other information may or may not be missing
+(zeroed).
+
+
+For more about build flags, see 'go help build'.
+
+
+For more about specifying packages, see 'go help packages'.
+
+
Compile and run Go program
+
+Usage:
+
+
go run [build flags] [-exec xprog] gofiles... [arguments...]
+
+
+Run compiles and runs the main package comprising the named Go source files.
+A Go source file is defined to be a file ending in a literal ".go" suffix.
+
+
+By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
+If the -exec flag is given, 'go run' invokes the binary using xprog:
+
+
'xprog a.out arguments...'.
+
+
+If the -exec flag is not given, GOOS or GOARCH is different from the system
+default, and a program named go_$GOOS_$GOARCH_exec can be found
+on the current search path, 'go run' invokes the binary using that program,
+for example 'go_nacl_386_exec a.out arguments...'. This allows execution of
+cross-compiled programs when a simulator or other execution method is
+available.
+
+
+For more about build flags, see 'go help build'.
+
+
+See also: go build.
+
+
Test packages
+
+Usage:
+
+
go test [build/test flags] [packages] [build/test flags & test binary flags]
+
+
+'Go test' automates testing the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+followed by detailed output for each failed package.
+
+
+'Go test' recompiles each package along with any files with names matching
+the file pattern "*_test.go".
+Files whose names begin with "_" (including "_test.go") or "." are ignored.
+These additional files can contain test functions, benchmark functions, and
+example functions. See 'go help testfunc' for more.
+Each listed package causes the execution of a separate test binary.
+
+
+Test files that declare a package with the suffix "_test" will be compiled as a
+separate package, and then linked and run with the main test binary.
+
+
+The go tool will ignore a directory named "testdata", making it available
+to hold ancillary data needed by the tests.
+
+
+By default, go test needs no arguments. It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+
+In addition to the build flags, the flags handled by 'go test' itself are:
+
+
-args
+ Pass the remainder of the command line (everything after -args)
+ to the test binary, uninterpreted and unchanged.
+ Because this flag consumes the remainder of the command line,
+ the package list (if present) must appear before this flag.
+
+-c
+ Compile the test binary to pkg.test but do not run it
+ (where pkg is the last element of the package's import path).
+ The file name can be changed with the -o flag.
+
+-exec xprog
+ Run the test binary using xprog. The behavior is the same as
+ in 'go run'. See 'go help run' for details.
+
+-i
+ Install packages that are dependencies of the test.
+ Do not run the test.
+
+-o file
+ Compile the test binary to the named file.
+ The test still runs (unless -c or -i is specified).
+
+
+The test binary also accepts flags that control execution of the test; these
+flags are also accessible by 'go test'. See 'go help testflag' for details.
+
+
+For more about build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
+
+
+See also: go build, go vet.
+
+
Run specified go tool
+
+Usage:
+
+
go tool [-n] command [args...]
+
+
+Tool runs the go tool command identified by the arguments.
+With no arguments it prints the list of known tools.
+
+
+The -n flag causes tool to print the command that would be
+executed but not execute it.
+
+
+For more about each tool command, see 'go tool command -h'.
+
+
Print Go version
+
+Usage:
+
+
go version
+
+
+Version prints the Go version, as reported by runtime.Version.
+
+
Run go tool vet on packages
+
+Usage:
+
+
go vet [-n] [-x] [build flags] [packages]
+
+
+Vet runs the Go vet command on the packages named by the import paths.
+
+
+For more about vet, see 'go doc cmd/vet'.
+For more about specifying packages, see 'go help packages'.
+
+
+To run the vet tool with specific options, run 'go tool vet'.
+
+
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+
+For more about build flags, see 'go help build'.
+
+
+See also: go fmt, go fix.
+
+
Calling between Go and C
+
+There are two different ways to call between Go and C/C++ code.
+
+
+The first is the cgo tool, which is part of the Go distribution. For
+information on how to use it see the cgo documentation (go doc cmd/cgo).
+
+
+The second is the SWIG program, which is a general tool for
+interfacing between languages. For information on SWIG see
+http://swig.org/. When running go build, any file with a .swig
+extension will be passed to SWIG. Any file with a .swigcxx extension
+will be passed to SWIG with the -c++ option.
+
+
+When either cgo or SWIG is used, go build will pass any .c, .m, .s,
+or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++
+compiler. The CC or CXX environment variables may be set to determine
+the C or C++ compiler, respectively, to use.
+
+
Description of build modes
+
+The 'go build' and 'go install' commands take a -buildmode argument which
+indicates which kind of object file is to be built. Currently supported values
+are:
+
+
-buildmode=archive
+ Build the listed non-main packages into .a files. Packages named
+ main are ignored.
+
+-buildmode=c-archive
+ Build the listed main package, plus all packages it imports,
+ into a C archive file. The only callable symbols will be those
+ functions exported using a cgo //export comment. Requires
+ exactly one main package to be listed.
+
+-buildmode=c-shared
+ Build the listed main packages, plus all packages that they
+ import, into C shared libraries. The only callable symbols will
+ be those functions exported using a cgo //export comment.
+ Non-main packages are ignored.
+
+-buildmode=default
+ Listed main packages are built into executables and listed
+ non-main packages are built into .a files (the default
+ behavior).
+
+-buildmode=shared
+ Combine all the listed non-main packages into a single shared
+ library that will be used when building with the -linkshared
+ option. Packages named main are ignored.
+
+-buildmode=exe
+ Build the listed main packages and everything they import into
+ executables. Packages not named main are ignored.
+
+-buildmode=pie
+ Build the listed main packages and everything they import into
+ position independent executables (PIE). Packages not named
+ main are ignored.
+
+-buildmode=plugin
+ Build the listed main packages, plus all packages that they
+ import, into a Go plugin. Packages not named main are ignored.
+
+
File types
+
+The go command examines the contents of a restricted set of files
+in each directory. It identifies which files to examine based on
+the extension of the file name. These extensions are:
+
+
.go
+ Go source files.
+.c, .h
+ C source files.
+ If the package uses cgo or SWIG, these will be compiled with the
+ OS-native compiler (typically gcc); otherwise they will
+ trigger an error.
+.cc, .cpp, .cxx, .hh, .hpp, .hxx
+ C++ source files. Only useful with cgo or SWIG, and always
+ compiled with the OS-native compiler.
+.m
+ Objective-C source files. Only useful with cgo, and always
+ compiled with the OS-native compiler.
+.s, .S
+ Assembler source files.
+ If the package uses cgo or SWIG, these will be assembled with the
+ OS-native assembler (typically gcc (sic)); otherwise they
+ will be assembled with the Go assembler.
+.swig, .swigcxx
+ SWIG definition files.
+.syso
+ System object files.
+
+
+Files of each of these types except .syso may contain build
+constraints, but the go command stops scanning for build constraints
+at the first item in the file that is not a blank line or //-style
+line comment. See the go/build package documentation for
+more details.
+
+
+Non-test Go source files can also include a //go:binary-only-package
+comment, indicating that the package sources are included
+for documentation only and must not be used to build the
+package binary. This enables distribution of Go packages in
+their compiled form alone. See the go/build package documentation
+for more details.
+
+
GOPATH environment variable
+
+The Go path is used to resolve import statements.
+It is implemented by and documented in the go/build package.
+
+
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+
+
+If the environment variable is unset, GOPATH defaults
+to a subdirectory named "go" in the user's home directory
+($HOME/go on Unix, %USERPROFILE%\go on Windows),
+unless that directory holds a Go distribution.
+Run "go env GOPATH" to see the current GOPATH.
+
+Each directory listed in GOPATH must have a prescribed structure:
+
+
+The src directory holds source code. The path below src
+determines the import path or executable name.
+
+
+The pkg directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+
+
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as "foo/bar" and
+has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
+
+
+The bin directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path. That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands. If the GOBIN environment variable is
+set, commands are installed to the directory it names instead
+of DIR/bin. GOBIN must be an absolute path.
+
+Code in or below a directory named "internal" is importable only
+by code in the directory tree rooted at the parent of "internal".
+Here's an extended version of the directory layout above:
+
+The code in z.go is imported as "foo/internal/baz", but that
+import statement can only appear in source files in the subtree
+rooted at foo. The source files foo/f.go, foo/bar/x.go, and
+foo/quux/y.go can all import "foo/internal/baz", but the source file
+crash/bang/b.go cannot.
+
+Go 1.6 includes support for using local copies of external dependencies
+to satisfy imports of those dependencies, often referred to as vendoring.
+
+
+Code below a directory named "vendor" is importable only
+by code in the directory tree rooted at the parent of "vendor",
+and only using an import path that omits the prefix up to and
+including the vendor element.
+
+
+Here's the example from the previous section,
+but with the "internal" directory renamed to "vendor"
+and a new foo/vendor/crash/bang directory added:
+
+The same visibility rules apply as for internal, but the code
+in z.go is imported as "baz", not as "foo/vendor/baz".
+
+
+Code in vendor directories deeper in the source tree shadows
+code in higher directories. Within the subtree rooted at foo, an import
+of "crash/bang" resolves to "foo/vendor/crash/bang", not the
+top-level "crash/bang".
+
+
+Code in vendor directories is not subject to import path
+checking (see 'go help importpath').
+
+
+When 'go get' checks out or updates a git repository, it now also
+updates submodules.
+
+
+Vendor directories do not affect the placement of new repositories
+being checked out for the first time by 'go get': those are always
+placed in the main GOPATH, never in a vendor subtree.
+
+The go command, and the tools it invokes, examine a few different
+environment variables. For many of these, you can see the default
+value of on your system by running 'go env NAME', where NAME is the
+name of the variable.
+
+
+General-purpose environment variables:
+
+
GCCGO
+ The gccgo command to run for 'go build -compiler=gccgo'.
+GOARCH
+ The architecture, or processor, for which to compile code.
+ Examples are amd64, 386, arm, ppc64.
+GOBIN
+ The directory where 'go install' will install a command.
+GOOS
+ The operating system for which to compile code.
+ Examples are linux, darwin, windows, netbsd.
+GOPATH
+ For more details see: 'go help gopath'.
+GORACE
+ Options for the race detector.
+ See https://golang.org/doc/articles/race_detector.html.
+GOROOT
+ The root of the go tree.
+
+
+Environment variables for use with cgo:
+
+
CC
+ The command to use to compile C code.
+CGO_ENABLED
+ Whether the cgo command is supported. Either 0 or 1.
+CGO_CFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ C code.
+CGO_CPPFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ C or C++ code.
+CGO_CXXFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ C++ code.
+CGO_FFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ Fortran code.
+CGO_LDFLAGS
+ Flags that cgo will pass to the compiler when linking.
+CXX
+ The command to use to compile C++ code.
+PKG_CONFIG
+ Path to pkg-config tool.
+
+
+Architecture-specific environment variables:
+
+
GOARM
+ For GOARCH=arm, the ARM architecture for which to compile.
+ Valid values are 5, 6, 7.
+GO386
+ For GOARCH=386, the floating point instruction set.
+ Valid values are 387, sse2.
+
+
+Special-purpose environment variables:
+
+
GOROOT_FINAL
+ The root of the installed Go tree, when it is
+ installed in a location other than where it is built.
+ File names in stack traces are rewritten from GOROOT to
+ GOROOT_FINAL.
+GO_EXTLINK_ENABLED
+ Whether the linker should use external linking mode
+ when using -linkmode=auto with code that uses cgo.
+ Set to 0 to disable external linking mode, 1 to enable it.
+GIT_ALLOW_PROTOCOL
+ Defined by Git. A colon-separated list of schemes that are allowed to be used
+ with git fetch/clone. If set, any scheme not explicitly mentioned will be
+ considered insecure by 'go get'.
+
+
Import path syntax
+
+An import path (see 'go help packages') denotes a package stored in the local
+file system. In general, an import path denotes either a standard package (such
+as "unicode/utf8") or a package found in one of the work spaces (For more
+details see: 'go help gopath').
+
+
Relative import paths
+
+An import path beginning with ./ or ../ is called a relative path.
+The toolchain supports relative import paths as a shortcut in two ways.
+
+
+First, a relative path can be used as a shorthand on the command line.
+If you are working in the directory containing the code imported as
+"unicode" and want to run the tests for "unicode/utf8", you can type
+"go test ./utf8" instead of needing to specify the full path.
+Similarly, in the reverse situation, "go test .." will test "unicode" from
+the "unicode/utf8" directory. Relative patterns are also allowed, like
+"go test ./..." to test all subdirectories. See 'go help packages' for details
+on the pattern syntax.
+
+
+Second, if you are compiling a Go program not in a work space,
+you can use a relative path in an import statement in that program
+to refer to nearby code also not in a work space.
+This makes it easy to experiment with small multipackage programs
+outside of the usual work spaces, but such programs cannot be
+installed with "go install" (there is no work space in which to install them),
+so they are rebuilt from scratch each time they are built.
+To avoid ambiguity, Go programs cannot use relative import paths
+within a work space.
+
+
Remote import paths
+
+Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+
+
+A few common code hosting sites have special syntax:
+
+For code hosted on other servers, import paths may either be qualified
+with the version control type, or the go tool can dynamically fetch
+the import path over https/http and discover where the code resides
+from a <meta> tag in the HTML.
+
+
+To declare the code location, an import path of the form
+
+
repository.vcs/path
+
+
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository. The supported version control systems are:
+
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+
+
import "example.org/repo.git/foo/bar"
+
+
+denotes the foo/bar directory of the Git repository at
+example.org/repo or repo.git.
+
+
+When a version control system supports multiple protocols,
+each is tried in turn when downloading. For example, a Git
+download tries https://, then git+ssh://.
+
+
+By default, downloads are restricted to known secure protocols
+(e.g. https, ssh). To override this setting for Git downloads, the
+GIT_ALLOW_PROTOCOL environment variable can be set (For more details see:
+'go help environment').
+
+
+If the import path is not a known code hosting site and also lacks a
+version control qualifier, the go tool attempts to fetch the import
+over https/http and looks for a <meta> tag in the document's HTML
+<head>.
+
+The import-prefix is the import path corresponding to the repository
+root. It must be a prefix or an exact match of the package being
+fetched with "go get". If it's not an exact match, another http
+request is made at the prefix to verify the <meta> tags match.
+
+
+The meta tag should appear as early in the file as possible.
+In particular, it should appear before any raw JavaScript or CSS,
+to avoid confusing the go command's restricted parser.
+
+
+The vcs is one of "git", "hg", "svn", etc,
+
+
+The repo-root is the root of the version control system
+containing a scheme and not containing a .vcs qualifier.
+
+New downloaded packages are written to the first directory listed in the GOPATH
+environment variable (For more details see: 'go help gopath').
+
+
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run 'go help get' for more.
+
+
Import path checking
+
+When the custom import path feature described above redirects to a
+known code hosting site, each of the resulting packages has two possible
+import paths, using the custom domain or the known hosting site.
+
+
+A package statement is said to have an "import comment" if it is immediately
+followed (before the next newline) by a comment of one of these two forms:
+
+
package math // import "path"
+package math /* import "path" */
+
+
+The go command will refuse to install a package with an import comment
+unless it is being referred to by that import path. In this way, import comments
+let package authors make sure the custom import path is used and not a
+direct path to the underlying code hosting site.
+
+
+Import path checking is disabled for code found within vendor trees.
+This makes it possible to copy code into alternate locations in vendor trees
+without needing to update import comments.
+
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+
+
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (For more details see: 'go help gopath').
+
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+
+There are four reserved names for paths that should not be used
+for packages to be built with the go tool:
+
+
+- "main" denotes the top-level package in a stand-alone executable.
+
+
+- "all" expands to all package directories found in all the GOPATH
+trees. For example, 'go list all' lists all the packages on the local
+system.
+
+
+- "std" is like all but expands to just the packages in the standard
+Go library.
+
+
+- "cmd" expands to the Go repository's commands and their
+internal libraries.
+
+
+Import paths beginning with "cmd/" only match source code in
+the Go repository.
+
+
+An import path is a pattern if it includes one or more "..." wildcards,
+each of which can match any string, including the empty string and
+strings containing slashes. Such a pattern expands to all package
+directories found in the GOPATH trees with names matching the
+patterns. As a special case, x/... matches x as well as x's subdirectories.
+For example, net/... expands to net and packages in its subdirectories.
+
+
+An import path can also name a package to be downloaded from
+a remote repository. Run 'go help importpath' for details.
+
+
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you. For example, paths used
+internally at Google all begin with 'google', and paths
+denoting remote repositories begin with the path to the code,
+such as 'github.com/user/repo'.
+
+
+Packages in a program need not have unique package names,
+but there are two reserved package names with special meaning.
+The name main indicates a command, not a library.
+Commands are built into binaries and cannot be imported.
+The name documentation indicates documentation for
+a non-Go program in the directory. Files in package documentation
+are ignored by the go command.
+
+
+As a special case, if the package list is a list of .go files from a
+single directory, the command is applied to a single synthesized
+package made up of exactly those files, ignoring any build constraints
+in those files and ignoring any other files in the directory.
+
+
+Directory and file names that begin with "." or "_" are ignored
+by the go tool, as are directories named "testdata".
+
+
Description of testing flags
+
+The 'go test' command takes both flags that apply to 'go test' itself
+and flags that apply to the resulting test binary.
+
+
+Several of the flags control profiling and write an execution profile
+suitable for "go tool pprof"; run "go tool pprof -h" for more
+information. The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+
+
+The following flags are recognized by the 'go test' command and
+control the execution of any test:
+
+
-bench regexp
+ Run (sub)benchmarks matching a regular expression.
+ The given regular expression is split into smaller ones by
+ top-level '/', where each must match the corresponding part of a
+ benchmark's identifier.
+ By default, no benchmarks run. To run all benchmarks,
+ use '-bench .' or '-bench=.'.
+
+-benchtime t
+ Run enough iterations of each benchmark to take t, specified
+ as a time.Duration (for example, -benchtime 1h30s).
+ The default is 1 second (1s).
+
+-count n
+ Run each test and benchmark n times (default 1).
+ If -cpu is set, run n times for each GOMAXPROCS value.
+ Examples are always run once.
+
+-cover
+ Enable coverage analysis.
+
+-covermode set,count,atomic
+ Set the mode for coverage analysis for the package[s]
+ being tested. The default is "set" unless -race is enabled,
+ in which case it is "atomic".
+ The values:
+ set: bool: does this statement run?
+ count: int: how many times does this statement run?
+ atomic: int: count, but correct in multithreaded tests;
+ significantly more expensive.
+ Sets -cover.
+
+-coverpkg pkg1,pkg2,pkg3
+ Apply coverage analysis in each test to the given list of packages.
+ The default is for each test to analyze only the package being tested.
+ Packages are specified as import paths.
+ Sets -cover.
+
+-cpu 1,2,4
+ Specify a list of GOMAXPROCS values for which the tests or
+ benchmarks should be executed. The default is the current value
+ of GOMAXPROCS.
+
+-parallel n
+ Allow parallel execution of test functions that call t.Parallel.
+ The value of this flag is the maximum number of tests to run
+ simultaneously; by default, it is set to the value of GOMAXPROCS.
+ Note that -parallel only applies within a single test binary.
+ The 'go test' command may run tests for different packages
+ in parallel as well, according to the setting of the -p flag
+ (see 'go help build').
+
+-run regexp
+ Run only those tests and examples matching the regular expression.
+ For tests the regular expression is split into smaller ones by
+ top-level '/', where each must match the corresponding part of a
+ test's identifier.
+
+-short
+ Tell long-running tests to shorten their run time.
+ It is off by default but set during all.bash so that installing
+ the Go tree can run a sanity check but not spend time running
+ exhaustive tests.
+
+-timeout t
+ If a test runs longer than t, panic.
+ The default is 10 minutes (10m).
+
+-v
+ Verbose output: log all tests as they are run. Also print all
+ text from Log and Logf calls even if the test succeeds.
+
+
+The following flags are also recognized by 'go test' and can be used to
+profile the tests during execution:
+
+
-benchmem
+ Print memory allocation statistics for benchmarks.
+
+-blockprofile block.out
+ Write a goroutine blocking profile to the specified file
+ when all tests are complete.
+ Writes test binary as -c would.
+
+-blockprofilerate n
+ Control the detail provided in goroutine blocking profiles by
+ calling runtime.SetBlockProfileRate with n.
+ See 'go doc runtime.SetBlockProfileRate'.
+ The profiler aims to sample, on average, one blocking event every
+ n nanoseconds the program spends blocked. By default,
+ if -test.blockprofile is set without this flag, all blocking events
+ are recorded, equivalent to -test.blockprofilerate=1.
+
+-coverprofile cover.out
+ Write a coverage profile to the file after all tests have passed.
+ Sets -cover.
+
+-cpuprofile cpu.out
+ Write a CPU profile to the specified file before exiting.
+ Writes test binary as -c would.
+
+-memprofile mem.out
+ Write a memory profile to the file after all tests have passed.
+ Writes test binary as -c would.
+
+-memprofilerate n
+ Enable more precise (and expensive) memory profiles by setting
+ runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
+ To profile all memory allocations, use -test.memprofilerate=1
+ and pass --alloc_space flag to the pprof tool.
+
+-mutexprofile mutex.out
+ Write a mutex contention profile to the specified file
+ when all tests are complete.
+ Writes test binary as -c would.
+
+-mutexprofilefraction n
+ Sample 1 in n stack traces of goroutines holding a
+ contended mutex.
+
+-outputdir directory
+ Place output files from profiling in the specified directory,
+ by default the directory in which "go test" is running.
+
+-trace trace.out
+ Write an execution trace to the specified file before exiting.
+
+
+Each of these flags is also recognized with an optional 'test.' prefix,
+as in -test.v. When invoking the generated test binary (the result of
+'go test -c') directly, however, the prefix is mandatory.
+
+
+The 'go test' command rewrites or removes recognized flags,
+as appropriate, both before and after the optional package list,
+before invoking the test binary.
+
+
+For instance, the command
+
+
go test -v -myflag testdata -cpuprofile=prof.out -x
+
+
+will compile the test binary and then run it as
+
+(The -x flag is removed because it applies only to the go command's
+execution, not to the test itself.)
+
+
+The test flags that generate profiles (other than for coverage) also
+leave the test binary in pkg.test for use when analyzing the profiles.
+
+
+When 'go test' runs a test binary, it does so from within the
+corresponding package's source code directory. Depending on the test,
+it may be necessary to do the same when invoking a generated test
+binary directly.
+
+
+The command-line package list, if present, must appear before any
+flag not known to the go test command. Continuing the example above,
+the package list would have to appear before -myflag, but could appear
+on either side of -v.
+
+
+To keep an argument for a test binary from being interpreted as a
+known flag or a package name, use -args (see 'go help test') which
+passes the remainder of the command line through to the test binary
+uninterpreted and unaltered.
+
+
+For instance, the command
+
+
go test -v -args -x -v
+
+
+will compile the test binary and then run it as
+
+
pkg.test -test.v -x -v
+
+
+Similarly,
+
+
go test -args math
+
+
+will compile the test binary and then run it as
+
+
pkg.test math
+
+
+In the first example, the -x and the second -v are passed through to the
+test binary unchanged and with no effect on the go command itself.
+In the second example, the argument math is passed through to the test
+binary, instead of being interpreted as the package list.
+
+
Description of testing functions
+
+The 'go test' command expects to find test, benchmark, and example functions
+in the "*_test.go" files corresponding to the package under test.
+
+
+A test function is one named TestXXX (where XXX is any alphanumeric string
+not starting with a lower case letter) and should have the signature,
+
+
func TestXXX(t *testing.T) { ... }
+
+
+A benchmark function is one named BenchmarkXXX and should have the signature,
+
+
func BenchmarkXXX(b *testing.B) { ... }
+
+
+An example function is similar to a test function but, instead of using
+*testing.T to report success or failure, prints output to os.Stdout.
+If the last comment in the function starts with "Output:" then the output
+is compared exactly against the comment (see examples below). If the last
+comment begins with "Unordered output:" then the output is compared to the
+comment, however the order of the lines is ignored. An example with no such
+comment is compiled but not executed. An example with no text after
+"Output:" is compiled, executed, and expected to produce no output.
+
+
+Godoc displays the body of ExampleXXX to demonstrate the use
+of the function, constant, or variable XXX. An example of a method M with
+receiver type T or *T is named ExampleT_M. There may be multiple examples
+for a given function, constant, or variable, distinguished by a trailing _xxx,
+where xxx is a suffix not beginning with an upper case letter.
+
+
+Here is an example of an example:
+
+
func ExamplePrintln() {
+ Println("The output of\nthis example.")
+ // Output: The output of
+ // this example.
+}
+
+
+Here is another example where the ordering of the output is ignored:
+
+The entire test file is presented as the example when it contains a single
+example function, at least one other function, type, variable, or constant
+declaration, and no test or benchmark functions.
+
+
+See the documentation of the testing package for more information.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`))
diff --git a/vendor/golang.org/x/net/http2/h2i/README.md b/vendor/golang.org/x/net/http2/h2i/README.md
new file mode 100644
index 0000000..fb5c5ef
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/h2i/README.md
@@ -0,0 +1,97 @@
+# h2i
+
+**h2i** is an interactive HTTP/2 ("h2") console debugger. Miss the good ol'
+days of telnetting to your HTTP/1.n servers? We're bringing you
+back.
+
+Features:
+- send raw HTTP/2 frames
+ - PING
+ - SETTINGS
+ - HEADERS
+ - etc
+- type in HTTP/1.n and have it auto-HPACK/frame-ify it for HTTP/2
+- pretty print all received HTTP/2 frames from the peer (including HPACK decoding)
+- tab completion of commands, options
+
+Not yet features, but soon:
+- unnecessary CONTINUATION frames on short boundaries, to test peer implementations
+- request bodies (DATA frames)
+- send invalid frames for testing server implementations (supported by underlying Framer)
+
+Later:
+- act like a server
+
+## Installation
+
+```
+$ go get golang.org/x/net/http2/h2i
+$ h2i
+```
+
+## Demo
+
+```
+$ h2i
+Usage: h2i
+
+ -insecure
+ Whether to skip TLS cert validation
+ -nextproto string
+ Comma-separated list of NPN/ALPN protocol names to negotiate. (default "h2,h2-14")
+
+$ h2i google.com
+Connecting to google.com:443 ...
+Connected to 74.125.224.41:443
+Negotiated protocol "h2-14"
+[FrameHeader SETTINGS len=18]
+ [MAX_CONCURRENT_STREAMS = 100]
+ [INITIAL_WINDOW_SIZE = 1048576]
+ [MAX_FRAME_SIZE = 16384]
+[FrameHeader WINDOW_UPDATE len=4]
+ Window-Increment = 983041
+
+h2i> PING h2iSayHI
+[FrameHeader PING flags=ACK len=8]
+ Data = "h2iSayHI"
+h2i> headers
+(as HTTP/1.1)> GET / HTTP/1.1
+(as HTTP/1.1)> Host: ip.appspot.com
+(as HTTP/1.1)> User-Agent: h2i/brad-n-blake
+(as HTTP/1.1)>
+Opening Stream-ID 1:
+ :authority = ip.appspot.com
+ :method = GET
+ :path = /
+ :scheme = https
+ user-agent = h2i/brad-n-blake
+[FrameHeader HEADERS flags=END_HEADERS stream=1 len=77]
+ :status = "200"
+ alternate-protocol = "443:quic,p=1"
+ content-length = "15"
+ content-type = "text/html"
+ date = "Fri, 01 May 2015 23:06:56 GMT"
+ server = "Google Frontend"
+[FrameHeader DATA flags=END_STREAM stream=1 len=15]
+ "173.164.155.78\n"
+[FrameHeader PING len=8]
+ Data = "\x00\x00\x00\x00\x00\x00\x00\x00"
+h2i> ping
+[FrameHeader PING flags=ACK len=8]
+ Data = "h2i_ping"
+h2i> ping
+[FrameHeader PING flags=ACK len=8]
+ Data = "h2i_ping"
+h2i> ping
+[FrameHeader GOAWAY len=22]
+ Last-Stream-ID = 1; Error-Code = PROTOCOL_ERROR (1)
+
+ReadFrame: EOF
+```
+
+## Status
+
+Quick few hour hack. So much yet to do. Feel free to file issues for
+bugs or wishlist items, but [@bmizerany](https://github.com/bmizerany/)
+and I aren't yet accepting pull requests until things settle down.
+
diff --git a/vendor/golang.org/x/net/http2/h2i/h2i.go b/vendor/golang.org/x/net/http2/h2i/h2i.go
new file mode 100644
index 0000000..62e5752
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/h2i/h2i.go
@@ -0,0 +1,522 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !plan9,!solaris
+
+/*
+The h2i command is an interactive HTTP/2 console.
+
+Usage:
+ $ h2i [flags]
+
+Interactive commands in the console: (all parts case-insensitive)
+
+ ping [data]
+ settings ack
+ settings FOO=n BAR=z
+ headers (open a new stream by typing HTTP/1.1)
+*/
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "os"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "golang.org/x/crypto/ssh/terminal"
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+)
+
+// Flags
+var (
+ flagNextProto = flag.String("nextproto", "h2,h2-14", "Comma-separated list of NPN/ALPN protocol names to negotiate.")
+ flagInsecure = flag.Bool("insecure", false, "Whether to skip TLS cert validation")
+ flagSettings = flag.String("settings", "empty", "comma-separated list of KEY=value settings for the initial SETTINGS frame. The magic value 'empty' sends an empty initial settings frame, and the magic value 'omit' causes no initial settings frame to be sent.")
+ flagDial = flag.String("dial", "", "optional ip:port to dial, to connect to a host:port but use a different SNI name (including a SNI name without DNS)")
+)
+
+type command struct {
+ run func(*h2i, []string) error // required
+
+ // complete optionally specifies tokens (case-insensitive) which are
+ // valid for this subcommand.
+ complete func() []string
+}
+
+var commands = map[string]command{
+ "ping": {run: (*h2i).cmdPing},
+ "settings": {
+ run: (*h2i).cmdSettings,
+ complete: func() []string {
+ return []string{
+ "ACK",
+ http2.SettingHeaderTableSize.String(),
+ http2.SettingEnablePush.String(),
+ http2.SettingMaxConcurrentStreams.String(),
+ http2.SettingInitialWindowSize.String(),
+ http2.SettingMaxFrameSize.String(),
+ http2.SettingMaxHeaderListSize.String(),
+ }
+ },
+ },
+ "quit": {run: (*h2i).cmdQuit},
+ "headers": {run: (*h2i).cmdHeaders},
+}
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "Usage: h2i \n\n")
+ flag.PrintDefaults()
+}
+
+// withPort adds ":443" if another port isn't already present.
+func withPort(host string) string {
+ if _, _, err := net.SplitHostPort(host); err != nil {
+ return net.JoinHostPort(host, "443")
+ }
+ return host
+}
+
+// withoutPort strips the port from addr if present.
+func withoutPort(addr string) string {
+ if h, _, err := net.SplitHostPort(addr); err == nil {
+ return h
+ }
+ return addr
+}
+
+// h2i is the app's state.
+type h2i struct {
+ host string
+ tc *tls.Conn
+ framer *http2.Framer
+ term *terminal.Terminal
+
+ // owned by the command loop:
+ streamID uint32
+ hbuf bytes.Buffer
+ henc *hpack.Encoder
+
+ // owned by the readFrames loop:
+ peerSetting map[http2.SettingID]uint32
+ hdec *hpack.Decoder
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ if flag.NArg() != 1 {
+ usage()
+ os.Exit(2)
+ }
+ log.SetFlags(0)
+
+ host := flag.Arg(0)
+ app := &h2i{
+ host: host,
+ peerSetting: make(map[http2.SettingID]uint32),
+ }
+ app.henc = hpack.NewEncoder(&app.hbuf)
+
+ if err := app.Main(); err != nil {
+ if app.term != nil {
+ app.logf("%v\n", err)
+ } else {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ }
+ os.Exit(1)
+ }
+ fmt.Fprintf(os.Stdout, "\n")
+}
+
+func (app *h2i) Main() error {
+ cfg := &tls.Config{
+ ServerName: withoutPort(app.host),
+ NextProtos: strings.Split(*flagNextProto, ","),
+ InsecureSkipVerify: *flagInsecure,
+ }
+
+ hostAndPort := *flagDial
+ if hostAndPort == "" {
+ hostAndPort = withPort(app.host)
+ }
+ log.Printf("Connecting to %s ...", hostAndPort)
+ tc, err := tls.Dial("tcp", hostAndPort, cfg)
+ if err != nil {
+ return fmt.Errorf("Error dialing %s: %v", hostAndPort, err)
+ }
+ log.Printf("Connected to %v", tc.RemoteAddr())
+ defer tc.Close()
+
+ if err := tc.Handshake(); err != nil {
+ return fmt.Errorf("TLS handshake: %v", err)
+ }
+ if !*flagInsecure {
+ if err := tc.VerifyHostname(app.host); err != nil {
+ return fmt.Errorf("VerifyHostname: %v", err)
+ }
+ }
+ state := tc.ConnectionState()
+ log.Printf("Negotiated protocol %q", state.NegotiatedProtocol)
+ if !state.NegotiatedProtocolIsMutual || state.NegotiatedProtocol == "" {
+ return fmt.Errorf("Could not negotiate protocol mutually")
+ }
+
+ if _, err := io.WriteString(tc, http2.ClientPreface); err != nil {
+ return err
+ }
+
+ app.framer = http2.NewFramer(tc, tc)
+
+ oldState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
+ if err != nil {
+ return err
+ }
+ defer terminal.Restore(0, oldState)
+
+ var screen = struct {
+ io.Reader
+ io.Writer
+ }{os.Stdin, os.Stdout}
+
+ app.term = terminal.NewTerminal(screen, "h2i> ")
+ lastWord := regexp.MustCompile(`.+\W(\w+)$`)
+ app.term.AutoCompleteCallback = func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
+ if key != '\t' {
+ return
+ }
+ if pos != len(line) {
+ // TODO: we're being lazy for now, only supporting tab completion at the end.
+ return
+ }
+ // Auto-complete for the command itself.
+ if !strings.Contains(line, " ") {
+ var name string
+ name, _, ok = lookupCommand(line)
+ if !ok {
+ return
+ }
+ return name, len(name), true
+ }
+ _, c, ok := lookupCommand(line[:strings.IndexByte(line, ' ')])
+ if !ok || c.complete == nil {
+ return
+ }
+ if strings.HasSuffix(line, " ") {
+ app.logf("%s", strings.Join(c.complete(), " "))
+ return line, pos, true
+ }
+ m := lastWord.FindStringSubmatch(line)
+ if m == nil {
+ return line, len(line), true
+ }
+ soFar := m[1]
+ var match []string
+ for _, cand := range c.complete() {
+ if len(soFar) > len(cand) || !strings.EqualFold(cand[:len(soFar)], soFar) {
+ continue
+ }
+ match = append(match, cand)
+ }
+ if len(match) == 0 {
+ return
+ }
+ if len(match) > 1 {
+ // TODO: auto-complete any common prefix
+ app.logf("%s", strings.Join(match, " "))
+ return line, pos, true
+ }
+ newLine = line[:len(line)-len(soFar)] + match[0]
+ return newLine, len(newLine), true
+
+ }
+
+ errc := make(chan error, 2)
+ go func() { errc <- app.readFrames() }()
+ go func() { errc <- app.readConsole() }()
+ return <-errc
+}
+
+func (app *h2i) logf(format string, args ...interface{}) {
+ fmt.Fprintf(app.term, format+"\r\n", args...)
+}
+
+func (app *h2i) readConsole() error {
+ if s := *flagSettings; s != "omit" {
+ var args []string
+ if s != "empty" {
+ args = strings.Split(s, ",")
+ }
+ _, c, ok := lookupCommand("settings")
+ if !ok {
+ panic("settings command not found")
+ }
+ c.run(app, args)
+ }
+
+ for {
+ line, err := app.term.ReadLine()
+ if err == io.EOF {
+ return nil
+ }
+ if err != nil {
+ return fmt.Errorf("terminal.ReadLine: %v", err)
+ }
+ f := strings.Fields(line)
+ if len(f) == 0 {
+ continue
+ }
+ cmd, args := f[0], f[1:]
+ if _, c, ok := lookupCommand(cmd); ok {
+ err = c.run(app, args)
+ } else {
+ app.logf("Unknown command %q", line)
+ }
+ if err == errExitApp {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ }
+}
+
+func lookupCommand(prefix string) (name string, c command, ok bool) {
+ prefix = strings.ToLower(prefix)
+ if c, ok = commands[prefix]; ok {
+ return prefix, c, ok
+ }
+
+ for full, candidate := range commands {
+ if strings.HasPrefix(full, prefix) {
+ if c.run != nil {
+ return "", command{}, false // ambiguous
+ }
+ c = candidate
+ name = full
+ }
+ }
+ return name, c, c.run != nil
+}
+
+var errExitApp = errors.New("internal sentinel error value to quit the console reading loop")
+
+func (a *h2i) cmdQuit(args []string) error {
+ if len(args) > 0 {
+ a.logf("the QUIT command takes no argument")
+ return nil
+ }
+ return errExitApp
+}
+
+func (a *h2i) cmdSettings(args []string) error {
+ if len(args) == 1 && strings.EqualFold(args[0], "ACK") {
+ return a.framer.WriteSettingsAck()
+ }
+ var settings []http2.Setting
+ for _, arg := range args {
+ if strings.EqualFold(arg, "ACK") {
+ a.logf("Error: ACK must be only argument with the SETTINGS command")
+ return nil
+ }
+ eq := strings.Index(arg, "=")
+ if eq == -1 {
+ a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
+ return nil
+ }
+ sid, ok := settingByName(arg[:eq])
+ if !ok {
+ a.logf("Error: unknown setting name %q", arg[:eq])
+ return nil
+ }
+ val, err := strconv.ParseUint(arg[eq+1:], 10, 32)
+ if err != nil {
+ a.logf("Error: invalid argument %q (expected SETTING_NAME=nnnn)", arg)
+ return nil
+ }
+ settings = append(settings, http2.Setting{
+ ID: sid,
+ Val: uint32(val),
+ })
+ }
+ a.logf("Sending: %v", settings)
+ return a.framer.WriteSettings(settings...)
+}
+
+func settingByName(name string) (http2.SettingID, bool) {
+ for _, sid := range [...]http2.SettingID{
+ http2.SettingHeaderTableSize,
+ http2.SettingEnablePush,
+ http2.SettingMaxConcurrentStreams,
+ http2.SettingInitialWindowSize,
+ http2.SettingMaxFrameSize,
+ http2.SettingMaxHeaderListSize,
+ } {
+ if strings.EqualFold(sid.String(), name) {
+ return sid, true
+ }
+ }
+ return 0, false
+}
+
+func (app *h2i) cmdPing(args []string) error {
+ if len(args) > 1 {
+ app.logf("invalid PING usage: only accepts 0 or 1 args")
+ return nil // nil means don't end the program
+ }
+ var data [8]byte
+ if len(args) == 1 {
+ copy(data[:], args[0])
+ } else {
+ copy(data[:], "h2i_ping")
+ }
+ return app.framer.WritePing(false, data)
+}
+
+func (app *h2i) cmdHeaders(args []string) error {
+ if len(args) > 0 {
+ app.logf("Error: HEADERS doesn't yet take arguments.")
+ // TODO: flags for restricting window size, to force CONTINUATION
+ // frames.
+ return nil
+ }
+ var h1req bytes.Buffer
+ app.term.SetPrompt("(as HTTP/1.1)> ")
+ defer app.term.SetPrompt("h2i> ")
+ for {
+ line, err := app.term.ReadLine()
+ if err != nil {
+ return err
+ }
+ h1req.WriteString(line)
+ h1req.WriteString("\r\n")
+ if line == "" {
+ break
+ }
+ }
+ req, err := http.ReadRequest(bufio.NewReader(&h1req))
+ if err != nil {
+ app.logf("Invalid HTTP/1.1 request: %v", err)
+ return nil
+ }
+ if app.streamID == 0 {
+ app.streamID = 1
+ } else {
+ app.streamID += 2
+ }
+ app.logf("Opening Stream-ID %d:", app.streamID)
+ hbf := app.encodeHeaders(req)
+ if len(hbf) > 16<<10 {
+ app.logf("TODO: h2i doesn't yet write CONTINUATION frames. Copy it from transport.go")
+ return nil
+ }
+ return app.framer.WriteHeaders(http2.HeadersFrameParam{
+ StreamID: app.streamID,
+ BlockFragment: hbf,
+ EndStream: req.Method == "GET" || req.Method == "HEAD", // good enough for now
+ EndHeaders: true, // for now
+ })
+}
+
+func (app *h2i) readFrames() error {
+ for {
+ f, err := app.framer.ReadFrame()
+ if err != nil {
+ return fmt.Errorf("ReadFrame: %v", err)
+ }
+ app.logf("%v", f)
+ switch f := f.(type) {
+ case *http2.PingFrame:
+ app.logf(" Data = %q", f.Data)
+ case *http2.SettingsFrame:
+ f.ForeachSetting(func(s http2.Setting) error {
+ app.logf(" %v", s)
+ app.peerSetting[s.ID] = s.Val
+ return nil
+ })
+ case *http2.WindowUpdateFrame:
+ app.logf(" Window-Increment = %v", f.Increment)
+ case *http2.GoAwayFrame:
+ app.logf(" Last-Stream-ID = %d; Error-Code = %v (%d)", f.LastStreamID, f.ErrCode, f.ErrCode)
+ case *http2.DataFrame:
+ app.logf(" %q", f.Data())
+ case *http2.HeadersFrame:
+ if f.HasPriority() {
+ app.logf(" PRIORITY = %v", f.Priority)
+ }
+ if app.hdec == nil {
+ // TODO: if the user uses h2i to send a SETTINGS frame advertising
+ // something larger, we'll need to respect SETTINGS_HEADER_TABLE_SIZE
+ // and stuff here instead of using the 4k default. But for now:
+ tableSize := uint32(4 << 10)
+ app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
+ }
+ app.hdec.Write(f.HeaderBlockFragment())
+ case *http2.PushPromiseFrame:
+ if app.hdec == nil {
+ // TODO: if the user uses h2i to send a SETTINGS frame advertising
+ // something larger, we'll need to respect SETTINGS_HEADER_TABLE_SIZE
+ // and stuff here instead of using the 4k default. But for now:
+ tableSize := uint32(4 << 10)
+ app.hdec = hpack.NewDecoder(tableSize, app.onNewHeaderField)
+ }
+ app.hdec.Write(f.HeaderBlockFragment())
+ }
+ }
+}
+
+// called from readLoop
+func (app *h2i) onNewHeaderField(f hpack.HeaderField) {
+ if f.Sensitive {
+ app.logf(" %s = %q (SENSITIVE)", f.Name, f.Value)
+ }
+ app.logf(" %s = %q", f.Name, f.Value)
+}
+
+func (app *h2i) encodeHeaders(req *http.Request) []byte {
+ app.hbuf.Reset()
+
+ // TODO(bradfitz): figure out :authority-vs-Host stuff between http2 and Go
+ host := req.Host
+ if host == "" {
+ host = req.URL.Host
+ }
+
+ path := req.RequestURI
+ if path == "" {
+ path = "/"
+ }
+
+ app.writeHeader(":authority", host) // probably not right for all sites
+ app.writeHeader(":method", req.Method)
+ app.writeHeader(":path", path)
+ app.writeHeader(":scheme", "https")
+
+ for k, vv := range req.Header {
+ lowKey := strings.ToLower(k)
+ if lowKey == "host" {
+ continue
+ }
+ for _, v := range vv {
+ app.writeHeader(lowKey, v)
+ }
+ }
+ return app.hbuf.Bytes()
+}
+
+func (app *h2i) writeHeader(name, value string) {
+ app.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
+ app.logf(" %s = %s", name, value)
+}
diff --git a/vendor/golang.org/x/net/http2/headermap.go b/vendor/golang.org/x/net/http2/headermap.go
new file mode 100644
index 0000000..c2805f6
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/headermap.go
@@ -0,0 +1,78 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "net/http"
+ "strings"
+)
+
+var (
+ commonLowerHeader = map[string]string{} // Go-Canonical-Case -> lower-case
+ commonCanonHeader = map[string]string{} // lower-case -> Go-Canonical-Case
+)
+
+func init() {
+ for _, v := range []string{
+ "accept",
+ "accept-charset",
+ "accept-encoding",
+ "accept-language",
+ "accept-ranges",
+ "age",
+ "access-control-allow-origin",
+ "allow",
+ "authorization",
+ "cache-control",
+ "content-disposition",
+ "content-encoding",
+ "content-language",
+ "content-length",
+ "content-location",
+ "content-range",
+ "content-type",
+ "cookie",
+ "date",
+ "etag",
+ "expect",
+ "expires",
+ "from",
+ "host",
+ "if-match",
+ "if-modified-since",
+ "if-none-match",
+ "if-unmodified-since",
+ "last-modified",
+ "link",
+ "location",
+ "max-forwards",
+ "proxy-authenticate",
+ "proxy-authorization",
+ "range",
+ "referer",
+ "refresh",
+ "retry-after",
+ "server",
+ "set-cookie",
+ "strict-transport-security",
+ "trailer",
+ "transfer-encoding",
+ "user-agent",
+ "vary",
+ "via",
+ "www-authenticate",
+ } {
+ chk := http.CanonicalHeaderKey(v)
+ commonLowerHeader[chk] = v
+ commonCanonHeader[v] = chk
+ }
+}
+
+func lowerHeader(v string) string {
+ if s, ok := commonLowerHeader[v]; ok {
+ return s
+ }
+ return strings.ToLower(v)
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/golang.org/x/net/http2/hpack/encode.go
new file mode 100644
index 0000000..54726c2
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/encode.go
@@ -0,0 +1,240 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hpack
+
+import (
+ "io"
+)
+
+const (
+ uint32Max = ^uint32(0)
+ initialHeaderTableSize = 4096
+)
+
+type Encoder struct {
+ dynTab dynamicTable
+ // minSize is the minimum table size set by
+ // SetMaxDynamicTableSize after the previous Header Table Size
+ // Update.
+ minSize uint32
+ // maxSizeLimit is the maximum table size this encoder
+ // supports. This will protect the encoder from too large
+ // size.
+ maxSizeLimit uint32
+ // tableSizeUpdate indicates whether "Header Table Size
+ // Update" is required.
+ tableSizeUpdate bool
+ w io.Writer
+ buf []byte
+}
+
+// NewEncoder returns a new Encoder which performs HPACK encoding. An
+// encoded data is written to w.
+func NewEncoder(w io.Writer) *Encoder {
+ e := &Encoder{
+ minSize: uint32Max,
+ maxSizeLimit: initialHeaderTableSize,
+ tableSizeUpdate: false,
+ w: w,
+ }
+ e.dynTab.table.init()
+ e.dynTab.setMaxSize(initialHeaderTableSize)
+ return e
+}
+
+// WriteField encodes f into a single Write to e's underlying Writer.
+// This function may also produce bytes for "Header Table Size Update"
+// if necessary. If produced, it is done before encoding f.
+func (e *Encoder) WriteField(f HeaderField) error {
+ e.buf = e.buf[:0]
+
+ if e.tableSizeUpdate {
+ e.tableSizeUpdate = false
+ if e.minSize < e.dynTab.maxSize {
+ e.buf = appendTableSize(e.buf, e.minSize)
+ }
+ e.minSize = uint32Max
+ e.buf = appendTableSize(e.buf, e.dynTab.maxSize)
+ }
+
+ idx, nameValueMatch := e.searchTable(f)
+ if nameValueMatch {
+ e.buf = appendIndexed(e.buf, idx)
+ } else {
+ indexing := e.shouldIndex(f)
+ if indexing {
+ e.dynTab.add(f)
+ }
+
+ if idx == 0 {
+ e.buf = appendNewName(e.buf, f, indexing)
+ } else {
+ e.buf = appendIndexedName(e.buf, f, idx, indexing)
+ }
+ }
+ n, err := e.w.Write(e.buf)
+ if err == nil && n != len(e.buf) {
+ err = io.ErrShortWrite
+ }
+ return err
+}
+
+// searchTable searches f in both stable and dynamic header tables.
+// The static header table is searched first. Only when there is no
+// exact match for both name and value, the dynamic header table is
+// then searched. If there is no match, i is 0. If both name and value
+// match, i is the matched index and nameValueMatch becomes true. If
+// only name matches, i points to that index and nameValueMatch
+// becomes false.
+func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
+ i, nameValueMatch = staticTable.search(f)
+ if nameValueMatch {
+ return i, true
+ }
+
+ j, nameValueMatch := e.dynTab.table.search(f)
+ if nameValueMatch || (i == 0 && j != 0) {
+ return j + uint64(staticTable.len()), nameValueMatch
+ }
+
+ return i, false
+}
+
+// SetMaxDynamicTableSize changes the dynamic header table size to v.
+// The actual size is bounded by the value passed to
+// SetMaxDynamicTableSizeLimit.
+func (e *Encoder) SetMaxDynamicTableSize(v uint32) {
+ if v > e.maxSizeLimit {
+ v = e.maxSizeLimit
+ }
+ if v < e.minSize {
+ e.minSize = v
+ }
+ e.tableSizeUpdate = true
+ e.dynTab.setMaxSize(v)
+}
+
+// SetMaxDynamicTableSizeLimit changes the maximum value that can be
+// specified in SetMaxDynamicTableSize to v. By default, it is set to
+// 4096, which is the same size of the default dynamic header table
+// size described in HPACK specification. If the current maximum
+// dynamic header table size is strictly greater than v, "Header Table
+// Size Update" will be done in the next WriteField call and the
+// maximum dynamic header table size is truncated to v.
+func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32) {
+ e.maxSizeLimit = v
+ if e.dynTab.maxSize > v {
+ e.tableSizeUpdate = true
+ e.dynTab.setMaxSize(v)
+ }
+}
+
+// shouldIndex reports whether f should be indexed.
+func (e *Encoder) shouldIndex(f HeaderField) bool {
+ return !f.Sensitive && f.Size() <= e.dynTab.maxSize
+}
+
+// appendIndexed appends index i, as encoded in "Indexed Header Field"
+// representation, to dst and returns the extended buffer.
+func appendIndexed(dst []byte, i uint64) []byte {
+ first := len(dst)
+ dst = appendVarInt(dst, 7, i)
+ dst[first] |= 0x80
+ return dst
+}
+
+// appendNewName appends f, as encoded in one of "Literal Header field
+// - New Name" representation variants, to dst and returns the
+// extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Inremental Indexing"
+// representation is used.
+func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
+ dst = append(dst, encodeTypeByte(indexing, f.Sensitive))
+ dst = appendHpackString(dst, f.Name)
+ return appendHpackString(dst, f.Value)
+}
+
+// appendIndexedName appends f and index i referring indexed name
+// entry, as encoded in one of "Literal Header field - Indexed Name"
+// representation variants, to dst and returns the extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Incremental Indexing"
+// representation is used.
+func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte {
+ first := len(dst)
+ var n byte
+ if indexing {
+ n = 6
+ } else {
+ n = 4
+ }
+ dst = appendVarInt(dst, n, i)
+ dst[first] |= encodeTypeByte(indexing, f.Sensitive)
+ return appendHpackString(dst, f.Value)
+}
+
+// appendTableSize appends v, as encoded in "Header Table Size Update"
+// representation, to dst and returns the extended buffer.
+func appendTableSize(dst []byte, v uint32) []byte {
+ first := len(dst)
+ dst = appendVarInt(dst, 5, uint64(v))
+ dst[first] |= 0x20
+ return dst
+}
+
+// appendVarInt appends i, as encoded in variable integer form using n
+// bit prefix, to dst and returns the extended buffer.
+//
+// See
+// http://http2.github.io/http2-spec/compression.html#integer.representation
+func appendVarInt(dst []byte, n byte, i uint64) []byte {
+ k := uint64((1 << n) - 1)
+ if i < k {
+ return append(dst, byte(i))
+ }
+ dst = append(dst, byte(k))
+ i -= k
+ for ; i >= 128; i >>= 7 {
+ dst = append(dst, byte(0x80|(i&0x7f)))
+ }
+ return append(dst, byte(i))
+}
+
+// appendHpackString appends s, as encoded in "String Literal"
+// representation, to dst and returns the the extended buffer.
+//
+// s will be encoded in Huffman codes only when it produces strictly
+// shorter byte string.
+func appendHpackString(dst []byte, s string) []byte {
+ huffmanLength := HuffmanEncodeLength(s)
+ if huffmanLength < uint64(len(s)) {
+ first := len(dst)
+ dst = appendVarInt(dst, 7, huffmanLength)
+ dst = AppendHuffmanString(dst, s)
+ dst[first] |= 0x80
+ } else {
+ dst = appendVarInt(dst, 7, uint64(len(s)))
+ dst = append(dst, s...)
+ }
+ return dst
+}
+
+// encodeTypeByte returns type byte. If sensitive is true, type byte
+// for "Never Indexed" representation is returned. If sensitive is
+// false and indexing is true, type byte for "Incremental Indexing"
+// representation is returned. Otherwise, type byte for "Without
+// Indexing" is returned.
+func encodeTypeByte(indexing, sensitive bool) byte {
+ if sensitive {
+ return 0x10
+ }
+ if indexing {
+ return 0x40
+ }
+ return 0
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/golang.org/x/net/http2/hpack/hpack.go
new file mode 100644
index 0000000..176644a
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/hpack.go
@@ -0,0 +1,490 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package hpack implements HPACK, a compression format for
+// efficiently representing HTTP header fields in the context of HTTP/2.
+//
+// See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
+package hpack
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+)
+
+// A DecodingError is something the spec defines as a decoding error.
+type DecodingError struct {
+ Err error
+}
+
+func (de DecodingError) Error() string {
+ return fmt.Sprintf("decoding error: %v", de.Err)
+}
+
+// An InvalidIndexError is returned when an encoder references a table
+// entry before the static table or after the end of the dynamic table.
+type InvalidIndexError int
+
+func (e InvalidIndexError) Error() string {
+ return fmt.Sprintf("invalid indexed representation index %d", int(e))
+}
+
+// A HeaderField is a name-value pair. Both the name and value are
+// treated as opaque sequences of octets.
+type HeaderField struct {
+ Name, Value string
+
+ // Sensitive means that this header field should never be
+ // indexed.
+ Sensitive bool
+}
+
+// IsPseudo reports whether the header field is an http2 pseudo header.
+// That is, it reports whether it starts with a colon.
+// It is not otherwise guaranteed to be a valid pseudo header field,
+// though.
+func (hf HeaderField) IsPseudo() bool {
+ return len(hf.Name) != 0 && hf.Name[0] == ':'
+}
+
+func (hf HeaderField) String() string {
+ var suffix string
+ if hf.Sensitive {
+ suffix = " (sensitive)"
+ }
+ return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix)
+}
+
+// Size returns the size of an entry per RFC 7541 section 4.1.
+func (hf HeaderField) Size() uint32 {
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
+ // "The size of the dynamic table is the sum of the size of
+ // its entries. The size of an entry is the sum of its name's
+ // length in octets (as defined in Section 5.2), its value's
+ // length in octets (see Section 5.2), plus 32. The size of
+ // an entry is calculated using the length of the name and
+ // value without any Huffman encoding applied."
+
+ // This can overflow if somebody makes a large HeaderField
+ // Name and/or Value by hand, but we don't care, because that
+ // won't happen on the wire because the encoding doesn't allow
+ // it.
+ return uint32(len(hf.Name) + len(hf.Value) + 32)
+}
+
+// A Decoder is the decoding context for incremental processing of
+// header blocks.
+type Decoder struct {
+ dynTab dynamicTable
+ emit func(f HeaderField)
+
+ emitEnabled bool // whether calls to emit are enabled
+ maxStrLen int // 0 means unlimited
+
+ // buf is the unparsed buffer. It's only written to
+ // saveBuf if it was truncated in the middle of a header
+ // block. Because it's usually not owned, we can only
+ // process it under Write.
+ buf []byte // not owned; only valid during Write
+
+ // saveBuf is previous data passed to Write which we weren't able
+ // to fully parse before. Unlike buf, we own this data.
+ saveBuf bytes.Buffer
+}
+
+// NewDecoder returns a new decoder with the provided maximum dynamic
+// table size. The emitFunc will be called for each valid field
+// parsed, in the same goroutine as calls to Write, before Write returns.
+func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder {
+ d := &Decoder{
+ emit: emitFunc,
+ emitEnabled: true,
+ }
+ d.dynTab.table.init()
+ d.dynTab.allowedMaxSize = maxDynamicTableSize
+ d.dynTab.setMaxSize(maxDynamicTableSize)
+ return d
+}
+
+// ErrStringLength is returned by Decoder.Write when the max string length
+// (as configured by Decoder.SetMaxStringLength) would be violated.
+var ErrStringLength = errors.New("hpack: string too long")
+
+// SetMaxStringLength sets the maximum size of a HeaderField name or
+// value string. If a string exceeds this length (even after any
+// decompression), Write will return ErrStringLength.
+// A value of 0 means unlimited and is the default from NewDecoder.
+func (d *Decoder) SetMaxStringLength(n int) {
+ d.maxStrLen = n
+}
+
+// SetEmitFunc changes the callback used when new header fields
+// are decoded.
+// It must be non-nil. It does not affect EmitEnabled.
+func (d *Decoder) SetEmitFunc(emitFunc func(f HeaderField)) {
+ d.emit = emitFunc
+}
+
+// SetEmitEnabled controls whether the emitFunc provided to NewDecoder
+// should be called. The default is true.
+//
+// This facility exists to let servers enforce MAX_HEADER_LIST_SIZE
+// while still decoding and keeping in-sync with decoder state, but
+// without doing unnecessary decompression or generating unnecessary
+// garbage for header fields past the limit.
+func (d *Decoder) SetEmitEnabled(v bool) { d.emitEnabled = v }
+
+// EmitEnabled reports whether calls to the emitFunc provided to NewDecoder
+// are currently enabled. The default is true.
+func (d *Decoder) EmitEnabled() bool { return d.emitEnabled }
+
+// TODO: add method *Decoder.Reset(maxSize, emitFunc) to let callers re-use Decoders and their
+// underlying buffers for garbage reasons.
+
+func (d *Decoder) SetMaxDynamicTableSize(v uint32) {
+ d.dynTab.setMaxSize(v)
+}
+
+// SetAllowedMaxDynamicTableSize sets the upper bound that the encoded
+// stream (via dynamic table size updates) may set the maximum size
+// to.
+func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
+ d.dynTab.allowedMaxSize = v
+}
+
+type dynamicTable struct {
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
+ table headerFieldTable
+ size uint32 // in bytes
+ maxSize uint32 // current maxSize
+ allowedMaxSize uint32 // maxSize may go up to this, inclusive
+}
+
+func (dt *dynamicTable) setMaxSize(v uint32) {
+ dt.maxSize = v
+ dt.evict()
+}
+
+func (dt *dynamicTable) add(f HeaderField) {
+ dt.table.addEntry(f)
+ dt.size += f.Size()
+ dt.evict()
+}
+
+// If we're too big, evict old stuff.
+func (dt *dynamicTable) evict() {
+ var n int
+ for dt.size > dt.maxSize && n < dt.table.len() {
+ dt.size -= dt.table.ents[n].Size()
+ n++
+ }
+ dt.table.evictOldest(n)
+}
+
+func (d *Decoder) maxTableIndex() int {
+ // This should never overflow. RFC 7540 Section 6.5.2 limits the size of
+ // the dynamic table to 2^32 bytes, where each entry will occupy more than
+ // one byte. Further, the staticTable has a fixed, small length.
+ return d.dynTab.table.len() + staticTable.len()
+}
+
+func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
+ // See Section 2.3.3.
+ if i == 0 {
+ return
+ }
+ if i <= uint64(staticTable.len()) {
+ return staticTable.ents[i-1], true
+ }
+ if i > uint64(d.maxTableIndex()) {
+ return
+ }
+ // In the dynamic table, newer entries have lower indices.
+ // However, dt.ents[0] is the oldest entry. Hence, dt.ents is
+ // the reversed dynamic table.
+ dt := d.dynTab.table
+ return dt.ents[dt.len()-(int(i)-staticTable.len())], true
+}
+
+// Decode decodes an entire block.
+//
+// TODO: remove this method and make it incremental later? This is
+// easier for debugging now.
+func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
+ var hf []HeaderField
+ saveFunc := d.emit
+ defer func() { d.emit = saveFunc }()
+ d.emit = func(f HeaderField) { hf = append(hf, f) }
+ if _, err := d.Write(p); err != nil {
+ return nil, err
+ }
+ if err := d.Close(); err != nil {
+ return nil, err
+ }
+ return hf, nil
+}
+
+func (d *Decoder) Close() error {
+ if d.saveBuf.Len() > 0 {
+ d.saveBuf.Reset()
+ return DecodingError{errors.New("truncated headers")}
+ }
+ return nil
+}
+
+func (d *Decoder) Write(p []byte) (n int, err error) {
+ if len(p) == 0 {
+ // Prevent state machine CPU attacks (making us redo
+ // work up to the point of finding out we don't have
+ // enough data)
+ return
+ }
+ // Only copy the data if we have to. Optimistically assume
+ // that p will contain a complete header block.
+ if d.saveBuf.Len() == 0 {
+ d.buf = p
+ } else {
+ d.saveBuf.Write(p)
+ d.buf = d.saveBuf.Bytes()
+ d.saveBuf.Reset()
+ }
+
+ for len(d.buf) > 0 {
+ err = d.parseHeaderFieldRepr()
+ if err == errNeedMore {
+ // Extra paranoia, making sure saveBuf won't
+ // get too large. All the varint and string
+ // reading code earlier should already catch
+ // overlong things and return ErrStringLength,
+ // but keep this as a last resort.
+ const varIntOverhead = 8 // conservative
+ if d.maxStrLen != 0 && int64(len(d.buf)) > 2*(int64(d.maxStrLen)+varIntOverhead) {
+ return 0, ErrStringLength
+ }
+ d.saveBuf.Write(d.buf)
+ return len(p), nil
+ }
+ if err != nil {
+ break
+ }
+ }
+ return len(p), err
+}
+
+// errNeedMore is an internal sentinel error value that means the
+// buffer is truncated and we need to read more data before we can
+// continue parsing.
+var errNeedMore = errors.New("need more data")
+
+type indexType int
+
+const (
+ indexedTrue indexType = iota
+ indexedFalse
+ indexedNever
+)
+
+func (v indexType) indexed() bool { return v == indexedTrue }
+func (v indexType) sensitive() bool { return v == indexedNever }
+
+// returns errNeedMore if there isn't enough data available.
+// any other error is fatal.
+// consumes d.buf iff it returns nil.
+// precondition: must be called with len(d.buf) > 0
+func (d *Decoder) parseHeaderFieldRepr() error {
+ b := d.buf[0]
+ switch {
+ case b&128 != 0:
+ // Indexed representation.
+ // High bit set?
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.1
+ return d.parseFieldIndexed()
+ case b&192 == 64:
+ // 6.2.1 Literal Header Field with Incremental Indexing
+ // 0b10xxxxxx: top two bits are 10
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.1
+ return d.parseFieldLiteral(6, indexedTrue)
+ case b&240 == 0:
+ // 6.2.2 Literal Header Field without Indexing
+ // 0b0000xxxx: top four bits are 0000
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.2
+ return d.parseFieldLiteral(4, indexedFalse)
+ case b&240 == 16:
+ // 6.2.3 Literal Header Field never Indexed
+ // 0b0001xxxx: top four bits are 0001
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.3
+ return d.parseFieldLiteral(4, indexedNever)
+ case b&224 == 32:
+ // 6.3 Dynamic Table Size Update
+ // Top three bits are '001'.
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.3
+ return d.parseDynamicTableSizeUpdate()
+ }
+
+ return DecodingError{errors.New("invalid encoding")}
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldIndexed() error {
+ buf := d.buf
+ idx, buf, err := readVarInt(7, buf)
+ if err != nil {
+ return err
+ }
+ hf, ok := d.at(idx)
+ if !ok {
+ return DecodingError{InvalidIndexError(idx)}
+ }
+ d.buf = buf
+ return d.callEmit(HeaderField{Name: hf.Name, Value: hf.Value})
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
+ buf := d.buf
+ nameIdx, buf, err := readVarInt(n, buf)
+ if err != nil {
+ return err
+ }
+
+ var hf HeaderField
+ wantStr := d.emitEnabled || it.indexed()
+ if nameIdx > 0 {
+ ihf, ok := d.at(nameIdx)
+ if !ok {
+ return DecodingError{InvalidIndexError(nameIdx)}
+ }
+ hf.Name = ihf.Name
+ } else {
+ hf.Name, buf, err = d.readString(buf, wantStr)
+ if err != nil {
+ return err
+ }
+ }
+ hf.Value, buf, err = d.readString(buf, wantStr)
+ if err != nil {
+ return err
+ }
+ d.buf = buf
+ if it.indexed() {
+ d.dynTab.add(hf)
+ }
+ hf.Sensitive = it.sensitive()
+ return d.callEmit(hf)
+}
+
+func (d *Decoder) callEmit(hf HeaderField) error {
+ if d.maxStrLen != 0 {
+ if len(hf.Name) > d.maxStrLen || len(hf.Value) > d.maxStrLen {
+ return ErrStringLength
+ }
+ }
+ if d.emitEnabled {
+ d.emit(hf)
+ }
+ return nil
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseDynamicTableSizeUpdate() error {
+ buf := d.buf
+ size, buf, err := readVarInt(5, buf)
+ if err != nil {
+ return err
+ }
+ if size > uint64(d.dynTab.allowedMaxSize) {
+ return DecodingError{errors.New("dynamic table size update too large")}
+ }
+ d.dynTab.setMaxSize(uint32(size))
+ d.buf = buf
+ return nil
+}
+
+var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
+
+// readVarInt reads an unsigned variable length integer off the
+// beginning of p. n is the parameter as described in
+// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
+//
+// n must always be between 1 and 8.
+//
+// The returned remain buffer is either a smaller suffix of p, or err != nil.
+// The error is errNeedMore if p doesn't contain a complete integer.
+func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
+ if n < 1 || n > 8 {
+ panic("bad n")
+ }
+ if len(p) == 0 {
+ return 0, p, errNeedMore
+ }
+ i = uint64(p[0])
+ if n < 8 {
+ i &= (1 << uint64(n)) - 1
+ }
+ if i < (1< 0 {
+ b := p[0]
+ p = p[1:]
+ i += uint64(b&127) << m
+ if b&128 == 0 {
+ return i, p, nil
+ }
+ m += 7
+ if m >= 63 { // TODO: proper overflow check. making this up.
+ return 0, origP, errVarintOverflow
+ }
+ }
+ return 0, origP, errNeedMore
+}
+
+// readString decodes an hpack string from p.
+//
+// wantStr is whether s will be used. If false, decompression and
+// []byte->string garbage are skipped if s will be ignored
+// anyway. This does mean that huffman decoding errors for non-indexed
+// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
+// is returning an error anyway, and because they're not indexed, the error
+// won't affect the decoding state.
+func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
+ if len(p) == 0 {
+ return "", p, errNeedMore
+ }
+ isHuff := p[0]&128 != 0
+ strLen, p, err := readVarInt(7, p)
+ if err != nil {
+ return "", p, err
+ }
+ if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
+ return "", nil, ErrStringLength
+ }
+ if uint64(len(p)) < strLen {
+ return "", p, errNeedMore
+ }
+ if !isHuff {
+ if wantStr {
+ s = string(p[:strLen])
+ }
+ return s, p[strLen:], nil
+ }
+
+ if wantStr {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset() // don't trust others
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
+ buf.Reset()
+ return "", nil, err
+ }
+ s = buf.String()
+ buf.Reset() // be nice to GC
+ }
+ return s, p[strLen:], nil
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/huffman.go b/vendor/golang.org/x/net/http2/hpack/huffman.go
new file mode 100644
index 0000000..8850e39
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/huffman.go
@@ -0,0 +1,212 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hpack
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "sync"
+)
+
+var bufPool = sync.Pool{
+ New: func() interface{} { return new(bytes.Buffer) },
+}
+
+// HuffmanDecode decodes the string in v and writes the expanded
+// result to w, returning the number of bytes written to w and the
+// Write call's return value. At most one Write call is made.
+func HuffmanDecode(w io.Writer, v []byte) (int, error) {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, 0, v); err != nil {
+ return 0, err
+ }
+ return w.Write(buf.Bytes())
+}
+
+// HuffmanDecodeToString decodes the string in v.
+func HuffmanDecodeToString(v []byte) (string, error) {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, 0, v); err != nil {
+ return "", err
+ }
+ return buf.String(), nil
+}
+
+// ErrInvalidHuffman is returned for errors found decoding
+// Huffman-encoded strings.
+var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
+
+// huffmanDecode decodes v to buf.
+// If maxLen is greater than 0, attempts to write more to buf than
+// maxLen bytes will return ErrStringLength.
+func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
+ n := rootHuffmanNode
+ // cur is the bit buffer that has not been fed into n.
+ // cbits is the number of low order bits in cur that are valid.
+ // sbits is the number of bits of the symbol prefix being decoded.
+ cur, cbits, sbits := uint(0), uint8(0), uint8(0)
+ for _, b := range v {
+ cur = cur<<8 | uint(b)
+ cbits += 8
+ sbits += 8
+ for cbits >= 8 {
+ idx := byte(cur >> (cbits - 8))
+ n = n.children[idx]
+ if n == nil {
+ return ErrInvalidHuffman
+ }
+ if n.children == nil {
+ if maxLen != 0 && buf.Len() == maxLen {
+ return ErrStringLength
+ }
+ buf.WriteByte(n.sym)
+ cbits -= n.codeLen
+ n = rootHuffmanNode
+ sbits = cbits
+ } else {
+ cbits -= 8
+ }
+ }
+ }
+ for cbits > 0 {
+ n = n.children[byte(cur<<(8-cbits))]
+ if n == nil {
+ return ErrInvalidHuffman
+ }
+ if n.children != nil || n.codeLen > cbits {
+ break
+ }
+ if maxLen != 0 && buf.Len() == maxLen {
+ return ErrStringLength
+ }
+ buf.WriteByte(n.sym)
+ cbits -= n.codeLen
+ n = rootHuffmanNode
+ sbits = cbits
+ }
+ if sbits > 7 {
+ // Either there was an incomplete symbol, or overlong padding.
+ // Both are decoding errors per RFC 7541 section 5.2.
+ return ErrInvalidHuffman
+ }
+ if mask := uint(1< 8 {
+ codeLen -= 8
+ i := uint8(code >> codeLen)
+ if cur.children[i] == nil {
+ cur.children[i] = newInternalNode()
+ }
+ cur = cur.children[i]
+ }
+ shift := 8 - codeLen
+ start, end := int(uint8(code<> (nbits - rembits))
+ dst[len(dst)-1] |= t
+ }
+
+ return dst
+}
+
+// HuffmanEncodeLength returns the number of bytes required to encode
+// s in Huffman codes. The result is round up to byte boundary.
+func HuffmanEncodeLength(s string) uint64 {
+ n := uint64(0)
+ for i := 0; i < len(s); i++ {
+ n += uint64(huffmanCodeLen[s[i]])
+ }
+ return (n + 7) / 8
+}
+
+// appendByteToHuffmanCode appends Huffman code for c to dst and
+// returns the extended buffer and the remaining bits in the last
+// element. The appending is not byte aligned and the remaining bits
+// in the last element of dst is given in rembits.
+func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) {
+ code := huffmanCodes[c]
+ nbits := huffmanCodeLen[c]
+
+ for {
+ if rembits > nbits {
+ t := uint8(code << (rembits - nbits))
+ dst[len(dst)-1] |= t
+ rembits -= nbits
+ break
+ }
+
+ t := uint8(code >> (nbits - rembits))
+ dst[len(dst)-1] |= t
+
+ nbits -= rembits
+ rembits = 8
+
+ if nbits == 0 {
+ break
+ }
+
+ dst = append(dst, 0)
+ }
+
+ return dst, rembits
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/tables.go b/vendor/golang.org/x/net/http2/hpack/tables.go
new file mode 100644
index 0000000..a66cfbe
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/tables.go
@@ -0,0 +1,479 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hpack
+
+import (
+ "fmt"
+)
+
+// headerFieldTable implements a list of HeaderFields.
+// This is used to implement the static and dynamic tables.
+type headerFieldTable struct {
+ // For static tables, entries are never evicted.
+ //
+ // For dynamic tables, entries are evicted from ents[0] and added to the end.
+ // Each entry has a unique id that starts at one and increments for each
+ // entry that is added. This unique id is stable across evictions, meaning
+ // it can be used as a pointer to a specific entry. As in hpack, unique ids
+ // are 1-based. The unique id for ents[k] is k + evictCount + 1.
+ //
+ // Zero is not a valid unique id.
+ //
+ // evictCount should not overflow in any remotely practical situation. In
+ // practice, we will have one dynamic table per HTTP/2 connection. If we
+ // assume a very powerful server that handles 1M QPS per connection and each
+ // request adds (then evicts) 100 entries from the table, it would still take
+ // 2M years for evictCount to overflow.
+ ents []HeaderField
+ evictCount uint64
+
+ // byName maps a HeaderField name to the unique id of the newest entry with
+ // the same name. See above for a definition of "unique id".
+ byName map[string]uint64
+
+ // byNameValue maps a HeaderField name/value pair to the unique id of the newest
+ // entry with the same name and value. See above for a definition of "unique id".
+ byNameValue map[pairNameValue]uint64
+}
+
+type pairNameValue struct {
+ name, value string
+}
+
+func (t *headerFieldTable) init() {
+ t.byName = make(map[string]uint64)
+ t.byNameValue = make(map[pairNameValue]uint64)
+}
+
+// len reports the number of entries in the table.
+func (t *headerFieldTable) len() int {
+ return len(t.ents)
+}
+
+// addEntry adds a new entry.
+func (t *headerFieldTable) addEntry(f HeaderField) {
+ id := uint64(t.len()) + t.evictCount + 1
+ t.byName[f.Name] = id
+ t.byNameValue[pairNameValue{f.Name, f.Value}] = id
+ t.ents = append(t.ents, f)
+}
+
+// evictOldest evicts the n oldest entries in the table.
+func (t *headerFieldTable) evictOldest(n int) {
+ if n > t.len() {
+ panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
+ }
+ for k := 0; k < n; k++ {
+ f := t.ents[k]
+ id := t.evictCount + uint64(k) + 1
+ if t.byName[f.Name] == id {
+ delete(t.byName, f.Name)
+ }
+ if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
+ delete(t.byNameValue, p)
+ }
+ }
+ copy(t.ents, t.ents[n:])
+ for k := t.len() - n; k < t.len(); k++ {
+ t.ents[k] = HeaderField{} // so strings can be garbage collected
+ }
+ t.ents = t.ents[:t.len()-n]
+ if t.evictCount+uint64(n) < t.evictCount {
+ panic("evictCount overflow")
+ }
+ t.evictCount += uint64(n)
+}
+
+// search finds f in the table. If there is no match, i is 0.
+// If both name and value match, i is the matched index and nameValueMatch
+// becomes true. If only name matches, i points to that index and
+// nameValueMatch becomes false.
+//
+// The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
+// that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
+// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
+// table, the return value i actually refers to the entry t.ents[t.len()-i].
+//
+// All tables are assumed to be a dynamic tables except for the global
+// staticTable pointer.
+//
+// See Section 2.3.3.
+func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
+ if !f.Sensitive {
+ if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
+ return t.idToIndex(id), true
+ }
+ }
+ if id := t.byName[f.Name]; id != 0 {
+ return t.idToIndex(id), false
+ }
+ return 0, false
+}
+
+// idToIndex converts a unique id to an HPACK index.
+// See Section 2.3.3.
+func (t *headerFieldTable) idToIndex(id uint64) uint64 {
+ if id <= t.evictCount {
+ panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
+ }
+ k := id - t.evictCount - 1 // convert id to an index t.ents[k]
+ if t != staticTable {
+ return uint64(t.len()) - k // dynamic table
+ }
+ return k + 1
+}
+
+// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
+var staticTable = newStaticTable()
+var staticTableEntries = [...]HeaderField{
+ {Name: ":authority"},
+ {Name: ":method", Value: "GET"},
+ {Name: ":method", Value: "POST"},
+ {Name: ":path", Value: "/"},
+ {Name: ":path", Value: "/index.html"},
+ {Name: ":scheme", Value: "http"},
+ {Name: ":scheme", Value: "https"},
+ {Name: ":status", Value: "200"},
+ {Name: ":status", Value: "204"},
+ {Name: ":status", Value: "206"},
+ {Name: ":status", Value: "304"},
+ {Name: ":status", Value: "400"},
+ {Name: ":status", Value: "404"},
+ {Name: ":status", Value: "500"},
+ {Name: "accept-charset"},
+ {Name: "accept-encoding", Value: "gzip, deflate"},
+ {Name: "accept-language"},
+ {Name: "accept-ranges"},
+ {Name: "accept"},
+ {Name: "access-control-allow-origin"},
+ {Name: "age"},
+ {Name: "allow"},
+ {Name: "authorization"},
+ {Name: "cache-control"},
+ {Name: "content-disposition"},
+ {Name: "content-encoding"},
+ {Name: "content-language"},
+ {Name: "content-length"},
+ {Name: "content-location"},
+ {Name: "content-range"},
+ {Name: "content-type"},
+ {Name: "cookie"},
+ {Name: "date"},
+ {Name: "etag"},
+ {Name: "expect"},
+ {Name: "expires"},
+ {Name: "from"},
+ {Name: "host"},
+ {Name: "if-match"},
+ {Name: "if-modified-since"},
+ {Name: "if-none-match"},
+ {Name: "if-range"},
+ {Name: "if-unmodified-since"},
+ {Name: "last-modified"},
+ {Name: "link"},
+ {Name: "location"},
+ {Name: "max-forwards"},
+ {Name: "proxy-authenticate"},
+ {Name: "proxy-authorization"},
+ {Name: "range"},
+ {Name: "referer"},
+ {Name: "refresh"},
+ {Name: "retry-after"},
+ {Name: "server"},
+ {Name: "set-cookie"},
+ {Name: "strict-transport-security"},
+ {Name: "transfer-encoding"},
+ {Name: "user-agent"},
+ {Name: "vary"},
+ {Name: "via"},
+ {Name: "www-authenticate"},
+}
+
+func newStaticTable() *headerFieldTable {
+ t := &headerFieldTable{}
+ t.init()
+ for _, e := range staticTableEntries[:] {
+ t.addEntry(e)
+ }
+ return t
+}
+
+var huffmanCodes = [256]uint32{
+ 0x1ff8,
+ 0x7fffd8,
+ 0xfffffe2,
+ 0xfffffe3,
+ 0xfffffe4,
+ 0xfffffe5,
+ 0xfffffe6,
+ 0xfffffe7,
+ 0xfffffe8,
+ 0xffffea,
+ 0x3ffffffc,
+ 0xfffffe9,
+ 0xfffffea,
+ 0x3ffffffd,
+ 0xfffffeb,
+ 0xfffffec,
+ 0xfffffed,
+ 0xfffffee,
+ 0xfffffef,
+ 0xffffff0,
+ 0xffffff1,
+ 0xffffff2,
+ 0x3ffffffe,
+ 0xffffff3,
+ 0xffffff4,
+ 0xffffff5,
+ 0xffffff6,
+ 0xffffff7,
+ 0xffffff8,
+ 0xffffff9,
+ 0xffffffa,
+ 0xffffffb,
+ 0x14,
+ 0x3f8,
+ 0x3f9,
+ 0xffa,
+ 0x1ff9,
+ 0x15,
+ 0xf8,
+ 0x7fa,
+ 0x3fa,
+ 0x3fb,
+ 0xf9,
+ 0x7fb,
+ 0xfa,
+ 0x16,
+ 0x17,
+ 0x18,
+ 0x0,
+ 0x1,
+ 0x2,
+ 0x19,
+ 0x1a,
+ 0x1b,
+ 0x1c,
+ 0x1d,
+ 0x1e,
+ 0x1f,
+ 0x5c,
+ 0xfb,
+ 0x7ffc,
+ 0x20,
+ 0xffb,
+ 0x3fc,
+ 0x1ffa,
+ 0x21,
+ 0x5d,
+ 0x5e,
+ 0x5f,
+ 0x60,
+ 0x61,
+ 0x62,
+ 0x63,
+ 0x64,
+ 0x65,
+ 0x66,
+ 0x67,
+ 0x68,
+ 0x69,
+ 0x6a,
+ 0x6b,
+ 0x6c,
+ 0x6d,
+ 0x6e,
+ 0x6f,
+ 0x70,
+ 0x71,
+ 0x72,
+ 0xfc,
+ 0x73,
+ 0xfd,
+ 0x1ffb,
+ 0x7fff0,
+ 0x1ffc,
+ 0x3ffc,
+ 0x22,
+ 0x7ffd,
+ 0x3,
+ 0x23,
+ 0x4,
+ 0x24,
+ 0x5,
+ 0x25,
+ 0x26,
+ 0x27,
+ 0x6,
+ 0x74,
+ 0x75,
+ 0x28,
+ 0x29,
+ 0x2a,
+ 0x7,
+ 0x2b,
+ 0x76,
+ 0x2c,
+ 0x8,
+ 0x9,
+ 0x2d,
+ 0x77,
+ 0x78,
+ 0x79,
+ 0x7a,
+ 0x7b,
+ 0x7ffe,
+ 0x7fc,
+ 0x3ffd,
+ 0x1ffd,
+ 0xffffffc,
+ 0xfffe6,
+ 0x3fffd2,
+ 0xfffe7,
+ 0xfffe8,
+ 0x3fffd3,
+ 0x3fffd4,
+ 0x3fffd5,
+ 0x7fffd9,
+ 0x3fffd6,
+ 0x7fffda,
+ 0x7fffdb,
+ 0x7fffdc,
+ 0x7fffdd,
+ 0x7fffde,
+ 0xffffeb,
+ 0x7fffdf,
+ 0xffffec,
+ 0xffffed,
+ 0x3fffd7,
+ 0x7fffe0,
+ 0xffffee,
+ 0x7fffe1,
+ 0x7fffe2,
+ 0x7fffe3,
+ 0x7fffe4,
+ 0x1fffdc,
+ 0x3fffd8,
+ 0x7fffe5,
+ 0x3fffd9,
+ 0x7fffe6,
+ 0x7fffe7,
+ 0xffffef,
+ 0x3fffda,
+ 0x1fffdd,
+ 0xfffe9,
+ 0x3fffdb,
+ 0x3fffdc,
+ 0x7fffe8,
+ 0x7fffe9,
+ 0x1fffde,
+ 0x7fffea,
+ 0x3fffdd,
+ 0x3fffde,
+ 0xfffff0,
+ 0x1fffdf,
+ 0x3fffdf,
+ 0x7fffeb,
+ 0x7fffec,
+ 0x1fffe0,
+ 0x1fffe1,
+ 0x3fffe0,
+ 0x1fffe2,
+ 0x7fffed,
+ 0x3fffe1,
+ 0x7fffee,
+ 0x7fffef,
+ 0xfffea,
+ 0x3fffe2,
+ 0x3fffe3,
+ 0x3fffe4,
+ 0x7ffff0,
+ 0x3fffe5,
+ 0x3fffe6,
+ 0x7ffff1,
+ 0x3ffffe0,
+ 0x3ffffe1,
+ 0xfffeb,
+ 0x7fff1,
+ 0x3fffe7,
+ 0x7ffff2,
+ 0x3fffe8,
+ 0x1ffffec,
+ 0x3ffffe2,
+ 0x3ffffe3,
+ 0x3ffffe4,
+ 0x7ffffde,
+ 0x7ffffdf,
+ 0x3ffffe5,
+ 0xfffff1,
+ 0x1ffffed,
+ 0x7fff2,
+ 0x1fffe3,
+ 0x3ffffe6,
+ 0x7ffffe0,
+ 0x7ffffe1,
+ 0x3ffffe7,
+ 0x7ffffe2,
+ 0xfffff2,
+ 0x1fffe4,
+ 0x1fffe5,
+ 0x3ffffe8,
+ 0x3ffffe9,
+ 0xffffffd,
+ 0x7ffffe3,
+ 0x7ffffe4,
+ 0x7ffffe5,
+ 0xfffec,
+ 0xfffff3,
+ 0xfffed,
+ 0x1fffe6,
+ 0x3fffe9,
+ 0x1fffe7,
+ 0x1fffe8,
+ 0x7ffff3,
+ 0x3fffea,
+ 0x3fffeb,
+ 0x1ffffee,
+ 0x1ffffef,
+ 0xfffff4,
+ 0xfffff5,
+ 0x3ffffea,
+ 0x7ffff4,
+ 0x3ffffeb,
+ 0x7ffffe6,
+ 0x3ffffec,
+ 0x3ffffed,
+ 0x7ffffe7,
+ 0x7ffffe8,
+ 0x7ffffe9,
+ 0x7ffffea,
+ 0x7ffffeb,
+ 0xffffffe,
+ 0x7ffffec,
+ 0x7ffffed,
+ 0x7ffffee,
+ 0x7ffffef,
+ 0x7fffff0,
+ 0x3ffffee,
+}
+
+var huffmanCodeLen = [256]uint8{
+ 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
+ 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
+ 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
+ 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
+ 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
+ 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
+ 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
+ 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
+ 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
+ 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
+ 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
+ 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
+ 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
+ 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
+}
diff --git a/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go
new file mode 100644
index 0000000..d565f40
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/http2.go
@@ -0,0 +1,391 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package http2 implements the HTTP/2 protocol.
+//
+// This package is low-level and intended to be used directly by very
+// few people. Most users will use it indirectly through the automatic
+// use by the net/http package (from Go 1.6 and later).
+// For use in earlier Go versions see ConfigureServer. (Transport support
+// requires Go 1.6 or later)
+//
+// See https://http2.github.io/ for more information on HTTP/2.
+//
+// See https://http2.golang.org/ for a test server running this code.
+//
+package http2 // import "golang.org/x/net/http2"
+
+import (
+ "bufio"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/lex/httplex"
+)
+
+var (
+ VerboseLogs bool
+ logFrameWrites bool
+ logFrameReads bool
+ inTests bool
+)
+
+func init() {
+ e := os.Getenv("GODEBUG")
+ if strings.Contains(e, "http2debug=1") {
+ VerboseLogs = true
+ }
+ if strings.Contains(e, "http2debug=2") {
+ VerboseLogs = true
+ logFrameWrites = true
+ logFrameReads = true
+ }
+}
+
+const (
+ // ClientPreface is the string that must be sent by new
+ // connections from clients.
+ ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+
+ // SETTINGS_MAX_FRAME_SIZE default
+ // http://http2.github.io/http2-spec/#rfc.section.6.5.2
+ initialMaxFrameSize = 16384
+
+ // NextProtoTLS is the NPN/ALPN protocol negotiated during
+ // HTTP/2's TLS setup.
+ NextProtoTLS = "h2"
+
+ // http://http2.github.io/http2-spec/#SettingValues
+ initialHeaderTableSize = 4096
+
+ initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
+
+ defaultMaxReadFrameSize = 1 << 20
+)
+
+var (
+ clientPreface = []byte(ClientPreface)
+)
+
+type streamState int
+
+// HTTP/2 stream states.
+//
+// See http://tools.ietf.org/html/rfc7540#section-5.1.
+//
+// For simplicity, the server code merges "reserved (local)" into
+// "half-closed (remote)". This is one less state transition to track.
+// The only downside is that we send PUSH_PROMISEs slightly less
+// liberally than allowable. More discussion here:
+// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
+//
+// "reserved (remote)" is omitted since the client code does not
+// support server push.
+const (
+ stateIdle streamState = iota
+ stateOpen
+ stateHalfClosedLocal
+ stateHalfClosedRemote
+ stateClosed
+)
+
+var stateName = [...]string{
+ stateIdle: "Idle",
+ stateOpen: "Open",
+ stateHalfClosedLocal: "HalfClosedLocal",
+ stateHalfClosedRemote: "HalfClosedRemote",
+ stateClosed: "Closed",
+}
+
+func (st streamState) String() string {
+ return stateName[st]
+}
+
+// Setting is a setting parameter: which setting it is, and its value.
+type Setting struct {
+ // ID is which setting is being set.
+ // See http://http2.github.io/http2-spec/#SettingValues
+ ID SettingID
+
+ // Val is the value.
+ Val uint32
+}
+
+func (s Setting) String() string {
+ return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
+}
+
+// Valid reports whether the setting is valid.
+func (s Setting) Valid() error {
+ // Limits and error codes from 6.5.2 Defined SETTINGS Parameters
+ switch s.ID {
+ case SettingEnablePush:
+ if s.Val != 1 && s.Val != 0 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ case SettingInitialWindowSize:
+ if s.Val > 1<<31-1 {
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ case SettingMaxFrameSize:
+ if s.Val < 16384 || s.Val > 1<<24-1 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ }
+ return nil
+}
+
+// A SettingID is an HTTP/2 setting as defined in
+// http://http2.github.io/http2-spec/#iana-settings
+type SettingID uint16
+
+const (
+ SettingHeaderTableSize SettingID = 0x1
+ SettingEnablePush SettingID = 0x2
+ SettingMaxConcurrentStreams SettingID = 0x3
+ SettingInitialWindowSize SettingID = 0x4
+ SettingMaxFrameSize SettingID = 0x5
+ SettingMaxHeaderListSize SettingID = 0x6
+)
+
+var settingName = map[SettingID]string{
+ SettingHeaderTableSize: "HEADER_TABLE_SIZE",
+ SettingEnablePush: "ENABLE_PUSH",
+ SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
+ SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
+ SettingMaxFrameSize: "MAX_FRAME_SIZE",
+ SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
+}
+
+func (s SettingID) String() string {
+ if v, ok := settingName[s]; ok {
+ return v
+ }
+ return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
+}
+
+var (
+ errInvalidHeaderFieldName = errors.New("http2: invalid header field name")
+ errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
+)
+
+// validWireHeaderFieldName reports whether v is a valid header field
+// name (key). See httplex.ValidHeaderName for the base rules.
+//
+// Further, http2 says:
+// "Just as in HTTP/1.x, header field names are strings of ASCII
+// characters that are compared in a case-insensitive
+// fashion. However, header field names MUST be converted to
+// lowercase prior to their encoding in HTTP/2. "
+func validWireHeaderFieldName(v string) bool {
+ if len(v) == 0 {
+ return false
+ }
+ for _, r := range v {
+ if !httplex.IsTokenRune(r) {
+ return false
+ }
+ if 'A' <= r && r <= 'Z' {
+ return false
+ }
+ }
+ return true
+}
+
+var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
+
+func init() {
+ for i := 100; i <= 999; i++ {
+ if v := http.StatusText(i); v != "" {
+ httpCodeStringCommon[i] = strconv.Itoa(i)
+ }
+ }
+}
+
+func httpCodeString(code int) string {
+ if s, ok := httpCodeStringCommon[code]; ok {
+ return s
+ }
+ return strconv.Itoa(code)
+}
+
+// from pkg io
+type stringWriter interface {
+ WriteString(s string) (n int, err error)
+}
+
+// A gate lets two goroutines coordinate their activities.
+type gate chan struct{}
+
+func (g gate) Done() { g <- struct{}{} }
+func (g gate) Wait() { <-g }
+
+// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
+type closeWaiter chan struct{}
+
+// Init makes a closeWaiter usable.
+// It exists because so a closeWaiter value can be placed inside a
+// larger struct and have the Mutex and Cond's memory in the same
+// allocation.
+func (cw *closeWaiter) Init() {
+ *cw = make(chan struct{})
+}
+
+// Close marks the closeWaiter as closed and unblocks any waiters.
+func (cw closeWaiter) Close() {
+ close(cw)
+}
+
+// Wait waits for the closeWaiter to become closed.
+func (cw closeWaiter) Wait() {
+ <-cw
+}
+
+// bufferedWriter is a buffered writer that writes to w.
+// Its buffered writer is lazily allocated as needed, to minimize
+// idle memory usage with many connections.
+type bufferedWriter struct {
+ w io.Writer // immutable
+ bw *bufio.Writer // non-nil when data is buffered
+}
+
+func newBufferedWriter(w io.Writer) *bufferedWriter {
+ return &bufferedWriter{w: w}
+}
+
+// bufWriterPoolBufferSize is the size of bufio.Writer's
+// buffers created using bufWriterPool.
+//
+// TODO: pick a less arbitrary value? this is a bit under
+// (3 x typical 1500 byte MTU) at least. Other than that,
+// not much thought went into it.
+const bufWriterPoolBufferSize = 4 << 10
+
+var bufWriterPool = sync.Pool{
+ New: func() interface{} {
+ return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
+ },
+}
+
+func (w *bufferedWriter) Available() int {
+ if w.bw == nil {
+ return bufWriterPoolBufferSize
+ }
+ return w.bw.Available()
+}
+
+func (w *bufferedWriter) Write(p []byte) (n int, err error) {
+ if w.bw == nil {
+ bw := bufWriterPool.Get().(*bufio.Writer)
+ bw.Reset(w.w)
+ w.bw = bw
+ }
+ return w.bw.Write(p)
+}
+
+func (w *bufferedWriter) Flush() error {
+ bw := w.bw
+ if bw == nil {
+ return nil
+ }
+ err := bw.Flush()
+ bw.Reset(nil)
+ bufWriterPool.Put(bw)
+ w.bw = nil
+ return err
+}
+
+func mustUint31(v int32) uint32 {
+ if v < 0 || v > 2147483647 {
+ panic("out of range")
+ }
+ return uint32(v)
+}
+
+// bodyAllowedForStatus reports whether a given response status code
+// permits a body. See RFC 2616, section 4.4.
+func bodyAllowedForStatus(status int) bool {
+ switch {
+ case status >= 100 && status <= 199:
+ return false
+ case status == 204:
+ return false
+ case status == 304:
+ return false
+ }
+ return true
+}
+
+type httpError struct {
+ msg string
+ timeout bool
+}
+
+func (e *httpError) Error() string { return e.msg }
+func (e *httpError) Timeout() bool { return e.timeout }
+func (e *httpError) Temporary() bool { return true }
+
+var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
+
+type connectionStater interface {
+ ConnectionState() tls.ConnectionState
+}
+
+var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
+
+type sorter struct {
+ v []string // owned by sorter
+}
+
+func (s *sorter) Len() int { return len(s.v) }
+func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
+func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
+
+// Keys returns the sorted keys of h.
+//
+// The returned slice is only valid until s used again or returned to
+// its pool.
+func (s *sorter) Keys(h http.Header) []string {
+ keys := s.v[:0]
+ for k := range h {
+ keys = append(keys, k)
+ }
+ s.v = keys
+ sort.Sort(s)
+ return keys
+}
+
+func (s *sorter) SortStrings(ss []string) {
+ // Our sorter works on s.v, which sorter owns, so
+ // stash it away while we sort the user's buffer.
+ save := s.v
+ s.v = ss
+ sort.Sort(s)
+ s.v = save
+}
+
+// validPseudoPath reports whether v is a valid :path pseudo-header
+// value. It must be either:
+//
+// *) a non-empty string starting with '/'
+// *) the string '*', for OPTIONS requests.
+//
+// For now this is only used a quick check for deciding when to clean
+// up Opaque URLs before sending requests from the Transport.
+// See golang.org/issue/16847
+//
+// We used to enforce that the path also didn't start with "//", but
+// Google's GFE accepts such paths and Chrome sends them, so ignore
+// that part of the spec. See golang.org/issue/19103.
+func validPseudoPath(v string) bool {
+ return (len(v) > 0 && v[0] == '/') || v == "*"
+}
diff --git a/vendor/golang.org/x/net/http2/not_go16.go b/vendor/golang.org/x/net/http2/not_go16.go
new file mode 100644
index 0000000..508cebc
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/not_go16.go
@@ -0,0 +1,21 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.6
+
+package http2
+
+import (
+ "net/http"
+ "time"
+)
+
+func configureTransport(t1 *http.Transport) (*Transport, error) {
+ return nil, errTransportVersion
+}
+
+func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
+ return 0
+
+}
diff --git a/vendor/golang.org/x/net/http2/not_go17.go b/vendor/golang.org/x/net/http2/not_go17.go
new file mode 100644
index 0000000..140434a
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/not_go17.go
@@ -0,0 +1,87 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package http2
+
+import (
+ "crypto/tls"
+ "net"
+ "net/http"
+ "time"
+)
+
+type contextContext interface {
+ Done() <-chan struct{}
+ Err() error
+}
+
+type fakeContext struct{}
+
+func (fakeContext) Done() <-chan struct{} { return nil }
+func (fakeContext) Err() error { panic("should not be called") }
+
+func reqContext(r *http.Request) fakeContext {
+ return fakeContext{}
+}
+
+func setResponseUncompressed(res *http.Response) {
+ // Nothing.
+}
+
+type clientTrace struct{}
+
+func requestTrace(*http.Request) *clientTrace { return nil }
+func traceGotConn(*http.Request, *ClientConn) {}
+func traceFirstResponseByte(*clientTrace) {}
+func traceWroteHeaders(*clientTrace) {}
+func traceWroteRequest(*clientTrace, error) {}
+func traceGot100Continue(trace *clientTrace) {}
+func traceWait100Continue(trace *clientTrace) {}
+
+func nop() {}
+
+func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
+ return nil, nop
+}
+
+func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
+ return ctx, nop
+}
+
+func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
+ return req
+}
+
+// temporary copy of Go 1.6's private tls.Config.clone:
+func cloneTLSConfig(c *tls.Config) *tls.Config {
+ return &tls.Config{
+ Rand: c.Rand,
+ Time: c.Time,
+ Certificates: c.Certificates,
+ NameToCertificate: c.NameToCertificate,
+ GetCertificate: c.GetCertificate,
+ RootCAs: c.RootCAs,
+ NextProtos: c.NextProtos,
+ ServerName: c.ServerName,
+ ClientAuth: c.ClientAuth,
+ ClientCAs: c.ClientCAs,
+ InsecureSkipVerify: c.InsecureSkipVerify,
+ CipherSuites: c.CipherSuites,
+ PreferServerCipherSuites: c.PreferServerCipherSuites,
+ SessionTicketsDisabled: c.SessionTicketsDisabled,
+ SessionTicketKey: c.SessionTicketKey,
+ ClientSessionCache: c.ClientSessionCache,
+ MinVersion: c.MinVersion,
+ MaxVersion: c.MaxVersion,
+ CurvePreferences: c.CurvePreferences,
+ }
+}
+
+func (cc *ClientConn) Ping(ctx contextContext) error {
+ return cc.ping(ctx)
+}
+
+func (t *Transport) idleConnTimeout() time.Duration { return 0 }
diff --git a/vendor/golang.org/x/net/http2/not_go18.go b/vendor/golang.org/x/net/http2/not_go18.go
new file mode 100644
index 0000000..6f8d3f8
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/not_go18.go
@@ -0,0 +1,29 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.8
+
+package http2
+
+import (
+ "io"
+ "net/http"
+)
+
+func configureServer18(h1 *http.Server, h2 *Server) error {
+ // No IdleTimeout to sync prior to Go 1.8.
+ return nil
+}
+
+func shouldLogPanic(panicValue interface{}) bool {
+ return panicValue != nil
+}
+
+func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
+ return nil
+}
+
+func reqBodyIsNoBody(io.ReadCloser) bool { return false }
+
+func go18httpNoBody() io.ReadCloser { return nil } // for tests only
diff --git a/vendor/golang.org/x/net/http2/not_go19.go b/vendor/golang.org/x/net/http2/not_go19.go
new file mode 100644
index 0000000..5ae0772
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/not_go19.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.9
+
+package http2
+
+import (
+ "net/http"
+)
+
+func configureServer19(s *http.Server, conf *Server) error {
+ // not supported prior to go1.9
+ return nil
+}
diff --git a/vendor/golang.org/x/net/http2/pipe.go b/vendor/golang.org/x/net/http2/pipe.go
new file mode 100644
index 0000000..a614009
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/pipe.go
@@ -0,0 +1,163 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "errors"
+ "io"
+ "sync"
+)
+
+// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
+// io.Pipe except there are no PipeReader/PipeWriter halves, and the
+// underlying buffer is an interface. (io.Pipe is always unbuffered)
+type pipe struct {
+ mu sync.Mutex
+ c sync.Cond // c.L lazily initialized to &p.mu
+ b pipeBuffer // nil when done reading
+ err error // read error once empty. non-nil means closed.
+ breakErr error // immediate read error (caller doesn't see rest of b)
+ donec chan struct{} // closed on error
+ readFn func() // optional code to run in Read before error
+}
+
+type pipeBuffer interface {
+ Len() int
+ io.Writer
+ io.Reader
+}
+
+func (p *pipe) Len() int {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.b == nil {
+ return 0
+ }
+ return p.b.Len()
+}
+
+// Read waits until data is available and copies bytes
+// from the buffer into p.
+func (p *pipe) Read(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ for {
+ if p.breakErr != nil {
+ return 0, p.breakErr
+ }
+ if p.b != nil && p.b.Len() > 0 {
+ return p.b.Read(d)
+ }
+ if p.err != nil {
+ if p.readFn != nil {
+ p.readFn() // e.g. copy trailers
+ p.readFn = nil // not sticky like p.err
+ }
+ p.b = nil
+ return 0, p.err
+ }
+ p.c.Wait()
+ }
+}
+
+var errClosedPipeWrite = errors.New("write on closed buffer")
+
+// Write copies bytes from p into the buffer and wakes a reader.
+// It is an error to write more data than the buffer can hold.
+func (p *pipe) Write(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if p.err != nil {
+ return 0, errClosedPipeWrite
+ }
+ if p.breakErr != nil {
+ return len(d), nil // discard when there is no reader
+ }
+ return p.b.Write(d)
+}
+
+// CloseWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err after all data has been
+// read.
+//
+// The error must be non-nil.
+func (p *pipe) CloseWithError(err error) { p.closeWithError(&p.err, err, nil) }
+
+// BreakWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err immediately, without
+// waiting for unread data.
+func (p *pipe) BreakWithError(err error) { p.closeWithError(&p.breakErr, err, nil) }
+
+// closeWithErrorAndCode is like CloseWithError but also sets some code to run
+// in the caller's goroutine before returning the error.
+func (p *pipe) closeWithErrorAndCode(err error, fn func()) { p.closeWithError(&p.err, err, fn) }
+
+func (p *pipe) closeWithError(dst *error, err error, fn func()) {
+ if err == nil {
+ panic("err must be non-nil")
+ }
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if *dst != nil {
+ // Already been done.
+ return
+ }
+ p.readFn = fn
+ if dst == &p.breakErr {
+ p.b = nil
+ }
+ *dst = err
+ p.closeDoneLocked()
+}
+
+// requires p.mu be held.
+func (p *pipe) closeDoneLocked() {
+ if p.donec == nil {
+ return
+ }
+ // Close if unclosed. This isn't racy since we always
+ // hold p.mu while closing.
+ select {
+ case <-p.donec:
+ default:
+ close(p.donec)
+ }
+}
+
+// Err returns the error (if any) first set by BreakWithError or CloseWithError.
+func (p *pipe) Err() error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.breakErr != nil {
+ return p.breakErr
+ }
+ return p.err
+}
+
+// Done returns a channel which is closed if and when this pipe is closed
+// with CloseWithError.
+func (p *pipe) Done() <-chan struct{} {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.donec == nil {
+ p.donec = make(chan struct{})
+ if p.err != nil || p.breakErr != nil {
+ // Already hit an error.
+ p.closeDoneLocked()
+ }
+ }
+ return p.donec
+}
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
new file mode 100644
index 0000000..3e705a0
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -0,0 +1,2866 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO: turn off the serve goroutine when idle, so
+// an idle conn only has the readFrames goroutine active. (which could
+// also be optimized probably to pin less memory in crypto/tls). This
+// would involve tracking when the serve goroutine is active (atomic
+// int32 read/CAS probably?) and starting it up when frames arrive,
+// and shutting it down when all handlers exit. the occasional PING
+// packets could use time.AfterFunc to call sc.wakeStartServeLoop()
+// (which is a no-op if already running) and then queue the PING write
+// as normal. The serve loop would then exit in most cases (if no
+// Handlers running) and not be woken up again until the PING packet
+// returns.
+
+// TODO (maybe): add a mechanism for Handlers to going into
+// half-closed-local mode (rw.(io.Closer) test?) but not exit their
+// handler, and continue to be able to read from the
+// Request.Body. This would be a somewhat semantic change from HTTP/1
+// (or at least what we expose in net/http), so I'd probably want to
+// add it there too. For now, this package says that returning from
+// the Handler ServeHTTP function means you're both done reading and
+// done writing, without a way to stop just one or the other.
+
+package http2
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+ "net"
+ "net/http"
+ "net/textproto"
+ "net/url"
+ "os"
+ "reflect"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/http2/hpack"
+)
+
+const (
+ prefaceTimeout = 10 * time.Second
+ firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
+ handlerChunkWriteSize = 4 << 10
+ defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
+)
+
+var (
+ errClientDisconnected = errors.New("client disconnected")
+ errClosedBody = errors.New("body closed by handler")
+ errHandlerComplete = errors.New("http2: request body closed due to handler exiting")
+ errStreamClosed = errors.New("http2: stream closed")
+)
+
+var responseWriterStatePool = sync.Pool{
+ New: func() interface{} {
+ rws := &responseWriterState{}
+ rws.bw = bufio.NewWriterSize(chunkWriter{rws}, handlerChunkWriteSize)
+ return rws
+ },
+}
+
+// Test hooks.
+var (
+ testHookOnConn func()
+ testHookGetServerConn func(*serverConn)
+ testHookOnPanicMu *sync.Mutex // nil except in tests
+ testHookOnPanic func(sc *serverConn, panicVal interface{}) (rePanic bool)
+)
+
+// Server is an HTTP/2 server.
+type Server struct {
+ // MaxHandlers limits the number of http.Handler ServeHTTP goroutines
+ // which may run at a time over all connections.
+ // Negative or zero no limit.
+ // TODO: implement
+ MaxHandlers int
+
+ // MaxConcurrentStreams optionally specifies the number of
+ // concurrent streams that each client may have open at a
+ // time. This is unrelated to the number of http.Handler goroutines
+ // which may be active globally, which is MaxHandlers.
+ // If zero, MaxConcurrentStreams defaults to at least 100, per
+ // the HTTP/2 spec's recommendations.
+ MaxConcurrentStreams uint32
+
+ // MaxReadFrameSize optionally specifies the largest frame
+ // this server is willing to read. A valid value is between
+ // 16k and 16M, inclusive. If zero or otherwise invalid, a
+ // default value is used.
+ MaxReadFrameSize uint32
+
+ // PermitProhibitedCipherSuites, if true, permits the use of
+ // cipher suites prohibited by the HTTP/2 spec.
+ PermitProhibitedCipherSuites bool
+
+ // IdleTimeout specifies how long until idle clients should be
+ // closed with a GOAWAY frame. PING frames are not considered
+ // activity for the purposes of IdleTimeout.
+ IdleTimeout time.Duration
+
+ // MaxUploadBufferPerConnection is the size of the initial flow
+ // control window for each connections. The HTTP/2 spec does not
+ // allow this to be smaller than 65535 or larger than 2^32-1.
+ // If the value is outside this range, a default value will be
+ // used instead.
+ MaxUploadBufferPerConnection int32
+
+ // MaxUploadBufferPerStream is the size of the initial flow control
+ // window for each stream. The HTTP/2 spec does not allow this to
+ // be larger than 2^32-1. If the value is zero or larger than the
+ // maximum, a default value will be used instead.
+ MaxUploadBufferPerStream int32
+
+ // NewWriteScheduler constructs a write scheduler for a connection.
+ // If nil, a default scheduler is chosen.
+ NewWriteScheduler func() WriteScheduler
+
+ // Internal state. This is a pointer (rather than embedded directly)
+ // so that we don't embed a Mutex in this struct, which will make the
+ // struct non-copyable, which might break some callers.
+ state *serverInternalState
+}
+
+func (s *Server) initialConnRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerConnection > initialWindowSize {
+ return s.MaxUploadBufferPerConnection
+ }
+ return 1 << 20
+}
+
+func (s *Server) initialStreamRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerStream > 0 {
+ return s.MaxUploadBufferPerStream
+ }
+ return 1 << 20
+}
+
+func (s *Server) maxReadFrameSize() uint32 {
+ if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
+ return v
+ }
+ return defaultMaxReadFrameSize
+}
+
+func (s *Server) maxConcurrentStreams() uint32 {
+ if v := s.MaxConcurrentStreams; v > 0 {
+ return v
+ }
+ return defaultMaxStreams
+}
+
+type serverInternalState struct {
+ mu sync.Mutex
+ activeConns map[*serverConn]struct{}
+}
+
+func (s *serverInternalState) registerConn(sc *serverConn) {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ s.activeConns[sc] = struct{}{}
+ s.mu.Unlock()
+}
+
+func (s *serverInternalState) unregisterConn(sc *serverConn) {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ delete(s.activeConns, sc)
+ s.mu.Unlock()
+}
+
+func (s *serverInternalState) startGracefulShutdown() {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ for sc := range s.activeConns {
+ sc.startGracefulShutdown()
+ }
+ s.mu.Unlock()
+}
+
+// ConfigureServer adds HTTP/2 support to a net/http Server.
+//
+// The configuration conf may be nil.
+//
+// ConfigureServer must be called before s begins serving.
+func ConfigureServer(s *http.Server, conf *Server) error {
+ if s == nil {
+ panic("nil *http.Server")
+ }
+ if conf == nil {
+ conf = new(Server)
+ }
+ conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
+ if err := configureServer18(s, conf); err != nil {
+ return err
+ }
+ if err := configureServer19(s, conf); err != nil {
+ return err
+ }
+
+ if s.TLSConfig == nil {
+ s.TLSConfig = new(tls.Config)
+ } else if s.TLSConfig.CipherSuites != nil {
+ // If they already provided a CipherSuite list, return
+ // an error if it has a bad order or is missing
+ // ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
+ haveRequired := false
+ sawBad := false
+ for i, cs := range s.TLSConfig.CipherSuites {
+ switch cs {
+ case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ // Alternative MTI cipher to not discourage ECDSA-only servers.
+ // See http://golang.org/cl/30721 for further information.
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ haveRequired = true
+ }
+ if isBadCipher(cs) {
+ sawBad = true
+ } else if sawBad {
+ return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs)
+ }
+ }
+ if !haveRequired {
+ return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
+ }
+ }
+
+ // Note: not setting MinVersion to tls.VersionTLS12,
+ // as we don't want to interfere with HTTP/1.1 traffic
+ // on the user's server. We enforce TLS 1.2 later once
+ // we accept a connection. Ideally this should be done
+ // during next-proto selection, but using TLS <1.2 with
+ // HTTP/2 is still the client's bug.
+
+ s.TLSConfig.PreferServerCipherSuites = true
+
+ haveNPN := false
+ for _, p := range s.TLSConfig.NextProtos {
+ if p == NextProtoTLS {
+ haveNPN = true
+ break
+ }
+ }
+ if !haveNPN {
+ s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
+ }
+
+ if s.TLSNextProto == nil {
+ s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
+ }
+ protoHandler := func(hs *http.Server, c *tls.Conn, h http.Handler) {
+ if testHookOnConn != nil {
+ testHookOnConn()
+ }
+ conf.ServeConn(c, &ServeConnOpts{
+ Handler: h,
+ BaseConfig: hs,
+ })
+ }
+ s.TLSNextProto[NextProtoTLS] = protoHandler
+ return nil
+}
+
+// ServeConnOpts are options for the Server.ServeConn method.
+type ServeConnOpts struct {
+ // BaseConfig optionally sets the base configuration
+ // for values. If nil, defaults are used.
+ BaseConfig *http.Server
+
+ // Handler specifies which handler to use for processing
+ // requests. If nil, BaseConfig.Handler is used. If BaseConfig
+ // or BaseConfig.Handler is nil, http.DefaultServeMux is used.
+ Handler http.Handler
+}
+
+func (o *ServeConnOpts) baseConfig() *http.Server {
+ if o != nil && o.BaseConfig != nil {
+ return o.BaseConfig
+ }
+ return new(http.Server)
+}
+
+func (o *ServeConnOpts) handler() http.Handler {
+ if o != nil {
+ if o.Handler != nil {
+ return o.Handler
+ }
+ if o.BaseConfig != nil && o.BaseConfig.Handler != nil {
+ return o.BaseConfig.Handler
+ }
+ }
+ return http.DefaultServeMux
+}
+
+// ServeConn serves HTTP/2 requests on the provided connection and
+// blocks until the connection is no longer readable.
+//
+// ServeConn starts speaking HTTP/2 assuming that c has not had any
+// reads or writes. It writes its initial settings frame and expects
+// to be able to read the preface and settings frame from the
+// client. If c has a ConnectionState method like a *tls.Conn, the
+// ConnectionState is used to verify the TLS ciphersuite and to set
+// the Request.TLS field in Handlers.
+//
+// ServeConn does not support h2c by itself. Any h2c support must be
+// implemented in terms of providing a suitably-behaving net.Conn.
+//
+// The opts parameter is optional. If nil, default values are used.
+func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+ baseCtx, cancel := serverConnBaseContext(c, opts)
+ defer cancel()
+
+ sc := &serverConn{
+ srv: s,
+ hs: opts.baseConfig(),
+ conn: c,
+ baseCtx: baseCtx,
+ remoteAddrStr: c.RemoteAddr().String(),
+ bw: newBufferedWriter(c),
+ handler: opts.handler(),
+ streams: make(map[uint32]*stream),
+ readFrameCh: make(chan readFrameResult),
+ wantWriteFrameCh: make(chan FrameWriteRequest, 8),
+ serveMsgCh: make(chan interface{}, 8),
+ wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
+ bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
+ doneServing: make(chan struct{}),
+ clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
+ advMaxStreams: s.maxConcurrentStreams(),
+ initialStreamSendWindowSize: initialWindowSize,
+ maxFrameSize: initialMaxFrameSize,
+ headerTableSize: initialHeaderTableSize,
+ serveG: newGoroutineLock(),
+ pushEnabled: true,
+ }
+
+ s.state.registerConn(sc)
+ defer s.state.unregisterConn(sc)
+
+ // The net/http package sets the write deadline from the
+ // http.Server.WriteTimeout during the TLS handshake, but then
+ // passes the connection off to us with the deadline already set.
+ // Write deadlines are set per stream in serverConn.newStream.
+ // Disarm the net.Conn write deadline here.
+ if sc.hs.WriteTimeout != 0 {
+ sc.conn.SetWriteDeadline(time.Time{})
+ }
+
+ if s.NewWriteScheduler != nil {
+ sc.writeSched = s.NewWriteScheduler()
+ } else {
+ sc.writeSched = NewRandomWriteScheduler()
+ }
+
+ // These start at the RFC-specified defaults. If there is a higher
+ // configured value for inflow, that will be updated when we send a
+ // WINDOW_UPDATE shortly after sending SETTINGS.
+ sc.flow.add(initialWindowSize)
+ sc.inflow.add(initialWindowSize)
+ sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
+
+ fr := NewFramer(sc.bw, c)
+ fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
+ fr.MaxHeaderListSize = sc.maxHeaderListSize()
+ fr.SetMaxReadFrameSize(s.maxReadFrameSize())
+ sc.framer = fr
+
+ if tc, ok := c.(connectionStater); ok {
+ sc.tlsState = new(tls.ConnectionState)
+ *sc.tlsState = tc.ConnectionState()
+ // 9.2 Use of TLS Features
+ // An implementation of HTTP/2 over TLS MUST use TLS
+ // 1.2 or higher with the restrictions on feature set
+ // and cipher suite described in this section. Due to
+ // implementation limitations, it might not be
+ // possible to fail TLS negotiation. An endpoint MUST
+ // immediately terminate an HTTP/2 connection that
+ // does not meet the TLS requirements described in
+ // this section with a connection error (Section
+ // 5.4.1) of type INADEQUATE_SECURITY.
+ if sc.tlsState.Version < tls.VersionTLS12 {
+ sc.rejectConn(ErrCodeInadequateSecurity, "TLS version too low")
+ return
+ }
+
+ if sc.tlsState.ServerName == "" {
+ // Client must use SNI, but we don't enforce that anymore,
+ // since it was causing problems when connecting to bare IP
+ // addresses during development.
+ //
+ // TODO: optionally enforce? Or enforce at the time we receive
+ // a new request, and verify the the ServerName matches the :authority?
+ // But that precludes proxy situations, perhaps.
+ //
+ // So for now, do nothing here again.
+ }
+
+ if !s.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) {
+ // "Endpoints MAY choose to generate a connection error
+ // (Section 5.4.1) of type INADEQUATE_SECURITY if one of
+ // the prohibited cipher suites are negotiated."
+ //
+ // We choose that. In my opinion, the spec is weak
+ // here. It also says both parties must support at least
+ // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no
+ // excuses here. If we really must, we could allow an
+ // "AllowInsecureWeakCiphers" option on the server later.
+ // Let's see how it plays out first.
+ sc.rejectConn(ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite))
+ return
+ }
+ }
+
+ if hook := testHookGetServerConn; hook != nil {
+ hook(sc)
+ }
+ sc.serve()
+}
+
+func (sc *serverConn) rejectConn(err ErrCode, debug string) {
+ sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
+ // ignoring errors. hanging up anyway.
+ sc.framer.WriteGoAway(0, err, []byte(debug))
+ sc.bw.Flush()
+ sc.conn.Close()
+}
+
+type serverConn struct {
+ // Immutable:
+ srv *Server
+ hs *http.Server
+ conn net.Conn
+ bw *bufferedWriter // writing to conn
+ handler http.Handler
+ baseCtx contextContext
+ framer *Framer
+ doneServing chan struct{} // closed when serverConn.serve ends
+ readFrameCh chan readFrameResult // written by serverConn.readFrames
+ wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
+ wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
+ bodyReadCh chan bodyReadMsg // from handlers -> serve
+ serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
+ flow flow // conn-wide (not stream-specific) outbound flow control
+ inflow flow // conn-wide inbound flow control
+ tlsState *tls.ConnectionState // shared by all handlers, like net/http
+ remoteAddrStr string
+ writeSched WriteScheduler
+
+ // Everything following is owned by the serve loop; use serveG.check():
+ serveG goroutineLock // used to verify funcs are on serve()
+ pushEnabled bool
+ sawFirstSettings bool // got the initial SETTINGS frame after the preface
+ needToSendSettingsAck bool
+ unackedSettings int // how many SETTINGS have we sent without ACKs?
+ clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
+ advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
+ curClientStreams uint32 // number of open streams initiated by the client
+ curPushedStreams uint32 // number of open streams initiated by server push
+ maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
+ maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
+ streams map[uint32]*stream
+ initialStreamSendWindowSize int32
+ maxFrameSize int32
+ headerTableSize uint32
+ peerMaxHeaderListSize uint32 // zero means unknown (default)
+ canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
+ writingFrame bool // started writing a frame (on serve goroutine or separate)
+ writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
+ needsFrameFlush bool // last frame write wasn't a flush
+ inGoAway bool // we've started to or sent GOAWAY
+ inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
+ needToSendGoAway bool // we need to schedule a GOAWAY frame write
+ goAwayCode ErrCode
+ shutdownTimer *time.Timer // nil until used
+ idleTimer *time.Timer // nil if unused
+
+ // Owned by the writeFrameAsync goroutine:
+ headerWriteBuf bytes.Buffer
+ hpackEncoder *hpack.Encoder
+
+ // Used by startGracefulShutdown.
+ shutdownOnce sync.Once
+}
+
+func (sc *serverConn) maxHeaderListSize() uint32 {
+ n := sc.hs.MaxHeaderBytes
+ if n <= 0 {
+ n = http.DefaultMaxHeaderBytes
+ }
+ // http2's count is in a slightly different unit and includes 32 bytes per pair.
+ // So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
+ const perFieldOverhead = 32 // per http2 spec
+ const typicalHeaders = 10 // conservative
+ return uint32(n + typicalHeaders*perFieldOverhead)
+}
+
+func (sc *serverConn) curOpenStreams() uint32 {
+ sc.serveG.check()
+ return sc.curClientStreams + sc.curPushedStreams
+}
+
+// stream represents a stream. This is the minimal metadata needed by
+// the serve goroutine. Most of the actual stream state is owned by
+// the http.Handler's goroutine in the responseWriter. Because the
+// responseWriter's responseWriterState is recycled at the end of a
+// handler, this struct intentionally has no pointer to the
+// *responseWriter{,State} itself, as the Handler ending nils out the
+// responseWriter's state field.
+type stream struct {
+ // immutable:
+ sc *serverConn
+ id uint32
+ body *pipe // non-nil if expecting DATA frames
+ cw closeWaiter // closed wait stream transitions to closed state
+ ctx contextContext
+ cancelCtx func()
+
+ // owned by serverConn's serve loop:
+ bodyBytes int64 // body bytes seen so far
+ declBodyBytes int64 // or -1 if undeclared
+ flow flow // limits writing from Handler to client
+ inflow flow // what the client is allowed to POST/etc to us
+ parent *stream // or nil
+ numTrailerValues int64
+ weight uint8
+ state streamState
+ resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
+ gotTrailerHeader bool // HEADER frame for trailers was seen
+ wroteHeaders bool // whether we wrote headers (not status 100)
+ writeDeadline *time.Timer // nil if unused
+
+ trailer http.Header // accumulated trailers
+ reqTrailer http.Header // handler's Request.Trailer
+}
+
+func (sc *serverConn) Framer() *Framer { return sc.framer }
+func (sc *serverConn) CloseConn() error { return sc.conn.Close() }
+func (sc *serverConn) Flush() error { return sc.bw.Flush() }
+func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
+ return sc.hpackEncoder, &sc.headerWriteBuf
+}
+
+func (sc *serverConn) state(streamID uint32) (streamState, *stream) {
+ sc.serveG.check()
+ // http://tools.ietf.org/html/rfc7540#section-5.1
+ if st, ok := sc.streams[streamID]; ok {
+ return st.state, st
+ }
+ // "The first use of a new stream identifier implicitly closes all
+ // streams in the "idle" state that might have been initiated by
+ // that peer with a lower-valued stream identifier. For example, if
+ // a client sends a HEADERS frame on stream 7 without ever sending a
+ // frame on stream 5, then stream 5 transitions to the "closed"
+ // state when the first frame for stream 7 is sent or received."
+ if streamID%2 == 1 {
+ if streamID <= sc.maxClientStreamID {
+ return stateClosed, nil
+ }
+ } else {
+ if streamID <= sc.maxPushPromiseID {
+ return stateClosed, nil
+ }
+ }
+ return stateIdle, nil
+}
+
+// setConnState calls the net/http ConnState hook for this connection, if configured.
+// Note that the net/http package does StateNew and StateClosed for us.
+// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
+func (sc *serverConn) setConnState(state http.ConnState) {
+ if sc.hs.ConnState != nil {
+ sc.hs.ConnState(sc.conn, state)
+ }
+}
+
+func (sc *serverConn) vlogf(format string, args ...interface{}) {
+ if VerboseLogs {
+ sc.logf(format, args...)
+ }
+}
+
+func (sc *serverConn) logf(format string, args ...interface{}) {
+ if lg := sc.hs.ErrorLog; lg != nil {
+ lg.Printf(format, args...)
+ } else {
+ log.Printf(format, args...)
+ }
+}
+
+// errno returns v's underlying uintptr, else 0.
+//
+// TODO: remove this helper function once http2 can use build
+// tags. See comment in isClosedConnError.
+func errno(v error) uintptr {
+ if rv := reflect.ValueOf(v); rv.Kind() == reflect.Uintptr {
+ return uintptr(rv.Uint())
+ }
+ return 0
+}
+
+// isClosedConnError reports whether err is an error from use of a closed
+// network connection.
+func isClosedConnError(err error) bool {
+ if err == nil {
+ return false
+ }
+
+ // TODO: remove this string search and be more like the Windows
+ // case below. That might involve modifying the standard library
+ // to return better error types.
+ str := err.Error()
+ if strings.Contains(str, "use of closed network connection") {
+ return true
+ }
+
+ // TODO(bradfitz): x/tools/cmd/bundle doesn't really support
+ // build tags, so I can't make an http2_windows.go file with
+ // Windows-specific stuff. Fix that and move this, once we
+ // have a way to bundle this into std's net/http somehow.
+ if runtime.GOOS == "windows" {
+ if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
+ if se, ok := oe.Err.(*os.SyscallError); ok && se.Syscall == "wsarecv" {
+ const WSAECONNABORTED = 10053
+ const WSAECONNRESET = 10054
+ if n := errno(se.Err); n == WSAECONNRESET || n == WSAECONNABORTED {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
+ if err == nil {
+ return
+ }
+ if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) {
+ // Boring, expected errors.
+ sc.vlogf(format, args...)
+ } else {
+ sc.logf(format, args...)
+ }
+}
+
+func (sc *serverConn) canonicalHeader(v string) string {
+ sc.serveG.check()
+ cv, ok := commonCanonHeader[v]
+ if ok {
+ return cv
+ }
+ cv, ok = sc.canonHeader[v]
+ if ok {
+ return cv
+ }
+ if sc.canonHeader == nil {
+ sc.canonHeader = make(map[string]string)
+ }
+ cv = http.CanonicalHeaderKey(v)
+ sc.canonHeader[v] = cv
+ return cv
+}
+
+type readFrameResult struct {
+ f Frame // valid until readMore is called
+ err error
+
+ // readMore should be called once the consumer no longer needs or
+ // retains f. After readMore, f is invalid and more frames can be
+ // read.
+ readMore func()
+}
+
+// readFrames is the loop that reads incoming frames.
+// It takes care to only read one frame at a time, blocking until the
+// consumer is done with the frame.
+// It's run on its own goroutine.
+func (sc *serverConn) readFrames() {
+ gate := make(gate)
+ gateDone := gate.Done
+ for {
+ f, err := sc.framer.ReadFrame()
+ select {
+ case sc.readFrameCh <- readFrameResult{f, err, gateDone}:
+ case <-sc.doneServing:
+ return
+ }
+ select {
+ case <-gate:
+ case <-sc.doneServing:
+ return
+ }
+ if terminalReadFrameError(err) {
+ return
+ }
+ }
+}
+
+// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
+type frameWriteResult struct {
+ wr FrameWriteRequest // what was written (or attempted)
+ err error // result of the writeFrame call
+}
+
+// writeFrameAsync runs in its own goroutine and writes a single frame
+// and then reports when it's done.
+// At most one goroutine can be running writeFrameAsync at a time per
+// serverConn.
+func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrameCh <- frameWriteResult{wr, err}
+}
+
+func (sc *serverConn) closeAllStreamsOnConnClose() {
+ sc.serveG.check()
+ for _, st := range sc.streams {
+ sc.closeStream(st, errClientDisconnected)
+ }
+}
+
+func (sc *serverConn) stopShutdownTimer() {
+ sc.serveG.check()
+ if t := sc.shutdownTimer; t != nil {
+ t.Stop()
+ }
+}
+
+func (sc *serverConn) notePanic() {
+ // Note: this is for serverConn.serve panicking, not http.Handler code.
+ if testHookOnPanicMu != nil {
+ testHookOnPanicMu.Lock()
+ defer testHookOnPanicMu.Unlock()
+ }
+ if testHookOnPanic != nil {
+ if e := recover(); e != nil {
+ if testHookOnPanic(sc, e) {
+ panic(e)
+ }
+ }
+ }
+}
+
+func (sc *serverConn) serve() {
+ sc.serveG.check()
+ defer sc.notePanic()
+ defer sc.conn.Close()
+ defer sc.closeAllStreamsOnConnClose()
+ defer sc.stopShutdownTimer()
+ defer close(sc.doneServing) // unblocks handlers trying to send
+
+ if VerboseLogs {
+ sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
+ }
+
+ sc.writeFrame(FrameWriteRequest{
+ write: writeSettings{
+ {SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
+ {SettingMaxConcurrentStreams, sc.advMaxStreams},
+ {SettingMaxHeaderListSize, sc.maxHeaderListSize()},
+ {SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
+ },
+ })
+ sc.unackedSettings++
+
+ // Each connection starts with intialWindowSize inflow tokens.
+ // If a higher value is configured, we add more tokens.
+ if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
+ sc.sendWindowUpdate(nil, int(diff))
+ }
+
+ if err := sc.readPreface(); err != nil {
+ sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
+ return
+ }
+ // Now that we've got the preface, get us out of the
+ // "StateNew" state. We can't go directly to idle, though.
+ // Active means we read some data and anticipate a request. We'll
+ // do another Active when we get a HEADERS frame.
+ sc.setConnState(http.StateActive)
+ sc.setConnState(http.StateIdle)
+
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
+ defer sc.idleTimer.Stop()
+ }
+
+ go sc.readFrames() // closed by defer sc.conn.Close above
+
+ settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
+ defer settingsTimer.Stop()
+
+ loopNum := 0
+ for {
+ loopNum++
+ select {
+ case wr := <-sc.wantWriteFrameCh:
+ if se, ok := wr.write.(StreamError); ok {
+ sc.resetStream(se)
+ break
+ }
+ sc.writeFrame(wr)
+ case res := <-sc.wroteFrameCh:
+ sc.wroteFrame(res)
+ case res := <-sc.readFrameCh:
+ if !sc.processFrameFromReader(res) {
+ return
+ }
+ res.readMore()
+ if settingsTimer != nil {
+ settingsTimer.Stop()
+ settingsTimer = nil
+ }
+ case m := <-sc.bodyReadCh:
+ sc.noteBodyRead(m.st, m.n)
+ case msg := <-sc.serveMsgCh:
+ switch v := msg.(type) {
+ case func(int):
+ v(loopNum) // for testing
+ case *serverMessage:
+ switch v {
+ case settingsTimerMsg:
+ sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
+ return
+ case idleTimerMsg:
+ sc.vlogf("connection is idle")
+ sc.goAway(ErrCodeNo)
+ case shutdownTimerMsg:
+ sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
+ return
+ case gracefulShutdownMsg:
+ sc.startGracefulShutdownInternal()
+ default:
+ panic("unknown timer")
+ }
+ case *startPushRequest:
+ sc.startPush(v)
+ default:
+ panic(fmt.Sprintf("unexpected type %T", v))
+ }
+ }
+
+ // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
+ // with no error code (graceful shutdown), don't start the timer until
+ // all open streams have been completed.
+ sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
+ gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
+ if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
+ sc.shutDownIn(goAwayTimeout)
+ }
+ }
+}
+
+func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) {
+ select {
+ case <-sc.doneServing:
+ case <-sharedCh:
+ close(privateCh)
+ }
+}
+
+type serverMessage int
+
+// Message values sent to serveMsgCh.
+var (
+ settingsTimerMsg = new(serverMessage)
+ idleTimerMsg = new(serverMessage)
+ shutdownTimerMsg = new(serverMessage)
+ gracefulShutdownMsg = new(serverMessage)
+)
+
+func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
+func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
+func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
+
+func (sc *serverConn) sendServeMsg(msg interface{}) {
+ sc.serveG.checkNotOn() // NOT
+ select {
+ case sc.serveMsgCh <- msg:
+ case <-sc.doneServing:
+ }
+}
+
+// readPreface reads the ClientPreface greeting from the peer
+// or returns an error on timeout or an invalid greeting.
+func (sc *serverConn) readPreface() error {
+ errc := make(chan error, 1)
+ go func() {
+ // Read the client preface
+ buf := make([]byte, len(ClientPreface))
+ if _, err := io.ReadFull(sc.conn, buf); err != nil {
+ errc <- err
+ } else if !bytes.Equal(buf, clientPreface) {
+ errc <- fmt.Errorf("bogus greeting %q", buf)
+ } else {
+ errc <- nil
+ }
+ }()
+ timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server?
+ defer timer.Stop()
+ select {
+ case <-timer.C:
+ return errors.New("timeout waiting for client preface")
+ case err := <-errc:
+ if err == nil {
+ if VerboseLogs {
+ sc.vlogf("http2: server: client %v said hello", sc.conn.RemoteAddr())
+ }
+ }
+ return err
+ }
+}
+
+var errChanPool = sync.Pool{
+ New: func() interface{} { return make(chan error, 1) },
+}
+
+var writeDataPool = sync.Pool{
+ New: func() interface{} { return new(writeData) },
+}
+
+// writeDataFromHandler writes DATA response frames from a handler on
+// the given stream.
+func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error {
+ ch := errChanPool.Get().(chan error)
+ writeArg := writeDataPool.Get().(*writeData)
+ *writeArg = writeData{stream.id, data, endStream}
+ err := sc.writeFrameFromHandler(FrameWriteRequest{
+ write: writeArg,
+ stream: stream,
+ done: ch,
+ })
+ if err != nil {
+ return err
+ }
+ var frameWriteDone bool // the frame write is done (successfully or not)
+ select {
+ case err = <-ch:
+ frameWriteDone = true
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-stream.cw:
+ // If both ch and stream.cw were ready (as might
+ // happen on the final Write after an http.Handler
+ // ends), prefer the write result. Otherwise this
+ // might just be us successfully closing the stream.
+ // The writeFrameAsync and serve goroutines guarantee
+ // that the ch send will happen before the stream.cw
+ // close.
+ select {
+ case err = <-ch:
+ frameWriteDone = true
+ default:
+ return errStreamClosed
+ }
+ }
+ errChanPool.Put(ch)
+ if frameWriteDone {
+ writeDataPool.Put(writeArg)
+ }
+ return err
+}
+
+// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
+// if the connection has gone away.
+//
+// This must not be run from the serve goroutine itself, else it might
+// deadlock writing to sc.wantWriteFrameCh (which is only mildly
+// buffered and is read by serve itself). If you're on the serve
+// goroutine, call writeFrame instead.
+func (sc *serverConn) writeFrameFromHandler(wr FrameWriteRequest) error {
+ sc.serveG.checkNotOn() // NOT
+ select {
+ case sc.wantWriteFrameCh <- wr:
+ return nil
+ case <-sc.doneServing:
+ // Serve loop is gone.
+ // Client has closed their connection to the server.
+ return errClientDisconnected
+ }
+}
+
+// writeFrame schedules a frame to write and sends it if there's nothing
+// already being written.
+//
+// There is no pushback here (the serve goroutine never blocks). It's
+// the http.Handlers that block, waiting for their previous frames to
+// make it onto the wire
+//
+// If you're not on the serve goroutine, use writeFrameFromHandler instead.
+func (sc *serverConn) writeFrame(wr FrameWriteRequest) {
+ sc.serveG.check()
+
+ // If true, wr will not be written and wr.done will not be signaled.
+ var ignoreWrite bool
+
+ // We are not allowed to write frames on closed streams. RFC 7540 Section
+ // 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on
+ // a closed stream." Our server never sends PRIORITY, so that exception
+ // does not apply.
+ //
+ // The serverConn might close an open stream while the stream's handler
+ // is still running. For example, the server might close a stream when it
+ // receives bad data from the client. If this happens, the handler might
+ // attempt to write a frame after the stream has been closed (since the
+ // handler hasn't yet been notified of the close). In this case, we simply
+ // ignore the frame. The handler will notice that the stream is closed when
+ // it waits for the frame to be written.
+ //
+ // As an exception to this rule, we allow sending RST_STREAM after close.
+ // This allows us to immediately reject new streams without tracking any
+ // state for those streams (except for the queued RST_STREAM frame). This
+ // may result in duplicate RST_STREAMs in some cases, but the client should
+ // ignore those.
+ if wr.StreamID() != 0 {
+ _, isReset := wr.write.(StreamError)
+ if state, _ := sc.state(wr.StreamID()); state == stateClosed && !isReset {
+ ignoreWrite = true
+ }
+ }
+
+ // Don't send a 100-continue response if we've already sent headers.
+ // See golang.org/issue/14030.
+ switch wr.write.(type) {
+ case *writeResHeaders:
+ wr.stream.wroteHeaders = true
+ case write100ContinueHeadersFrame:
+ if wr.stream.wroteHeaders {
+ // We do not need to notify wr.done because this frame is
+ // never written with wr.done != nil.
+ if wr.done != nil {
+ panic("wr.done != nil for write100ContinueHeadersFrame")
+ }
+ ignoreWrite = true
+ }
+ }
+
+ if !ignoreWrite {
+ sc.writeSched.Push(wr)
+ }
+ sc.scheduleFrameWrite()
+}
+
+// startFrameWrite starts a goroutine to write wr (in a separate
+// goroutine since that might block on the network), and updates the
+// serve goroutine's state about the world, updated from info in wr.
+func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
+ sc.serveG.check()
+ if sc.writingFrame {
+ panic("internal error: can only be writing one frame at a time")
+ }
+
+ st := wr.stream
+ if st != nil {
+ switch st.state {
+ case stateHalfClosedLocal:
+ switch wr.write.(type) {
+ case StreamError, handlerPanicRST, writeWindowUpdate:
+ // RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE
+ // in this state. (We never send PRIORITY from the server, so that is not checked.)
+ default:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr))
+ }
+ case stateClosed:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr))
+ }
+ }
+ if wpp, ok := wr.write.(*writePushPromise); ok {
+ var err error
+ wpp.promisedID, err = wpp.allocatePromisedID()
+ if err != nil {
+ sc.writingFrameAsync = false
+ wr.replyToWriter(err)
+ return
+ }
+ }
+
+ sc.writingFrame = true
+ sc.needsFrameFlush = true
+ if wr.write.staysWithinBuffer(sc.bw.Available()) {
+ sc.writingFrameAsync = false
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrame(frameWriteResult{wr, err})
+ } else {
+ sc.writingFrameAsync = true
+ go sc.writeFrameAsync(wr)
+ }
+}
+
+// errHandlerPanicked is the error given to any callers blocked in a read from
+// Request.Body when the main goroutine panics. Since most handlers read in the
+// the main ServeHTTP goroutine, this will show up rarely.
+var errHandlerPanicked = errors.New("http2: handler panicked")
+
+// wroteFrame is called on the serve goroutine with the result of
+// whatever happened on writeFrameAsync.
+func (sc *serverConn) wroteFrame(res frameWriteResult) {
+ sc.serveG.check()
+ if !sc.writingFrame {
+ panic("internal error: expected to be already writing a frame")
+ }
+ sc.writingFrame = false
+ sc.writingFrameAsync = false
+
+ wr := res.wr
+
+ if writeEndsStream(wr.write) {
+ st := wr.stream
+ if st == nil {
+ panic("internal error: expecting non-nil stream")
+ }
+ switch st.state {
+ case stateOpen:
+ // Here we would go to stateHalfClosedLocal in
+ // theory, but since our handler is done and
+ // the net/http package provides no mechanism
+ // for closing a ResponseWriter while still
+ // reading data (see possible TODO at top of
+ // this file), we go into closed state here
+ // anyway, after telling the peer we're
+ // hanging up on them. We'll transition to
+ // stateClosed after the RST_STREAM frame is
+ // written.
+ st.state = stateHalfClosedLocal
+ // Section 8.1: a server MAY request that the client abort
+ // transmission of a request without error by sending a
+ // RST_STREAM with an error code of NO_ERROR after sending
+ // a complete response.
+ sc.resetStream(streamError(st.id, ErrCodeNo))
+ case stateHalfClosedRemote:
+ sc.closeStream(st, errHandlerComplete)
+ }
+ } else {
+ switch v := wr.write.(type) {
+ case StreamError:
+ // st may be unknown if the RST_STREAM was generated to reject bad input.
+ if st, ok := sc.streams[v.StreamID]; ok {
+ sc.closeStream(st, v)
+ }
+ case handlerPanicRST:
+ sc.closeStream(wr.stream, errHandlerPanicked)
+ }
+ }
+
+ // Reply (if requested) to unblock the ServeHTTP goroutine.
+ wr.replyToWriter(res.err)
+
+ sc.scheduleFrameWrite()
+}
+
+// scheduleFrameWrite tickles the frame writing scheduler.
+//
+// If a frame is already being written, nothing happens. This will be called again
+// when the frame is done being written.
+//
+// If a frame isn't being written we need to send one, the best frame
+// to send is selected, preferring first things that aren't
+// stream-specific (e.g. ACKing settings), and then finding the
+// highest priority stream.
+//
+// If a frame isn't being written and there's nothing else to send, we
+// flush the write buffer.
+func (sc *serverConn) scheduleFrameWrite() {
+ sc.serveG.check()
+ if sc.writingFrame || sc.inFrameScheduleLoop {
+ return
+ }
+ sc.inFrameScheduleLoop = true
+ for !sc.writingFrameAsync {
+ if sc.needToSendGoAway {
+ sc.needToSendGoAway = false
+ sc.startFrameWrite(FrameWriteRequest{
+ write: &writeGoAway{
+ maxStreamID: sc.maxClientStreamID,
+ code: sc.goAwayCode,
+ },
+ })
+ continue
+ }
+ if sc.needToSendSettingsAck {
+ sc.needToSendSettingsAck = false
+ sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}})
+ continue
+ }
+ if !sc.inGoAway || sc.goAwayCode == ErrCodeNo {
+ if wr, ok := sc.writeSched.Pop(); ok {
+ sc.startFrameWrite(wr)
+ continue
+ }
+ }
+ if sc.needsFrameFlush {
+ sc.startFrameWrite(FrameWriteRequest{write: flushFrameWriter{}})
+ sc.needsFrameFlush = false // after startFrameWrite, since it sets this true
+ continue
+ }
+ break
+ }
+ sc.inFrameScheduleLoop = false
+}
+
+// startGracefulShutdown gracefully shuts down a connection. This
+// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
+// shutting down. The connection isn't closed until all current
+// streams are done.
+//
+// startGracefulShutdown returns immediately; it does not wait until
+// the connection has shut down.
+func (sc *serverConn) startGracefulShutdown() {
+ sc.serveG.checkNotOn() // NOT
+ sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
+}
+
+// After sending GOAWAY, the connection will close after goAwayTimeout.
+// If we close the connection immediately after sending GOAWAY, there may
+// be unsent data in our kernel receive buffer, which will cause the kernel
+// to send a TCP RST on close() instead of a FIN. This RST will abort the
+// connection immediately, whether or not the client had received the GOAWAY.
+//
+// Ideally we should delay for at least 1 RTT + epsilon so the client has
+// a chance to read the GOAWAY and stop sending messages. Measuring RTT
+// is hard, so we approximate with 1 second. See golang.org/issue/18701.
+//
+// This is a var so it can be shorter in tests, where all requests uses the
+// loopback interface making the expected RTT very small.
+//
+// TODO: configurable?
+var goAwayTimeout = 1 * time.Second
+
+func (sc *serverConn) startGracefulShutdownInternal() {
+ sc.goAway(ErrCodeNo)
+}
+
+func (sc *serverConn) goAway(code ErrCode) {
+ sc.serveG.check()
+ if sc.inGoAway {
+ return
+ }
+ sc.inGoAway = true
+ sc.needToSendGoAway = true
+ sc.goAwayCode = code
+ sc.scheduleFrameWrite()
+}
+
+func (sc *serverConn) shutDownIn(d time.Duration) {
+ sc.serveG.check()
+ sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
+}
+
+func (sc *serverConn) resetStream(se StreamError) {
+ sc.serveG.check()
+ sc.writeFrame(FrameWriteRequest{write: se})
+ if st, ok := sc.streams[se.StreamID]; ok {
+ st.resetQueued = true
+ }
+}
+
+// processFrameFromReader processes the serve loop's read from readFrameCh from the
+// frame-reading goroutine.
+// processFrameFromReader returns whether the connection should be kept open.
+func (sc *serverConn) processFrameFromReader(res readFrameResult) bool {
+ sc.serveG.check()
+ err := res.err
+ if err != nil {
+ if err == ErrFrameTooLarge {
+ sc.goAway(ErrCodeFrameSize)
+ return true // goAway will close the loop
+ }
+ clientGone := err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err)
+ if clientGone {
+ // TODO: could we also get into this state if
+ // the peer does a half close
+ // (e.g. CloseWrite) because they're done
+ // sending frames but they're still wanting
+ // our open replies? Investigate.
+ // TODO: add CloseWrite to crypto/tls.Conn first
+ // so we have a way to test this? I suppose
+ // just for testing we could have a non-TLS mode.
+ return false
+ }
+ } else {
+ f := res.f
+ if VerboseLogs {
+ sc.vlogf("http2: server read frame %v", summarizeFrame(f))
+ }
+ err = sc.processFrame(f)
+ if err == nil {
+ return true
+ }
+ }
+
+ switch ev := err.(type) {
+ case StreamError:
+ sc.resetStream(ev)
+ return true
+ case goAwayFlowError:
+ sc.goAway(ErrCodeFlowControl)
+ return true
+ case ConnectionError:
+ sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)
+ sc.goAway(ErrCode(ev))
+ return true // goAway will handle shutdown
+ default:
+ if res.err != nil {
+ sc.vlogf("http2: server closing client connection; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)
+ } else {
+ sc.logf("http2: server closing client connection: %v", err)
+ }
+ return false
+ }
+}
+
+func (sc *serverConn) processFrame(f Frame) error {
+ sc.serveG.check()
+
+ // First frame received must be SETTINGS.
+ if !sc.sawFirstSettings {
+ if _, ok := f.(*SettingsFrame); !ok {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ sc.sawFirstSettings = true
+ }
+
+ switch f := f.(type) {
+ case *SettingsFrame:
+ return sc.processSettings(f)
+ case *MetaHeadersFrame:
+ return sc.processHeaders(f)
+ case *WindowUpdateFrame:
+ return sc.processWindowUpdate(f)
+ case *PingFrame:
+ return sc.processPing(f)
+ case *DataFrame:
+ return sc.processData(f)
+ case *RSTStreamFrame:
+ return sc.processResetStream(f)
+ case *PriorityFrame:
+ return sc.processPriority(f)
+ case *GoAwayFrame:
+ return sc.processGoAway(f)
+ case *PushPromiseFrame:
+ // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
+ // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
+ return ConnectionError(ErrCodeProtocol)
+ default:
+ sc.vlogf("http2: server ignoring frame: %v", f.Header())
+ return nil
+ }
+}
+
+func (sc *serverConn) processPing(f *PingFrame) error {
+ sc.serveG.check()
+ if f.IsAck() {
+ // 6.7 PING: " An endpoint MUST NOT respond to PING frames
+ // containing this flag."
+ return nil
+ }
+ if f.StreamID != 0 {
+ // "PING frames are not associated with any individual
+ // stream. If a PING frame is received with a stream
+ // identifier field value other than 0x0, the recipient MUST
+ // respond with a connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
+ return nil
+ }
+ sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})
+ return nil
+}
+
+func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
+ sc.serveG.check()
+ switch {
+ case f.StreamID != 0: // stream-level flow control
+ state, st := sc.state(f.StreamID)
+ if state == stateIdle {
+ // Section 5.1: "Receiving any frame other than HEADERS
+ // or PRIORITY on a stream in this state MUST be
+ // treated as a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st == nil {
+ // "WINDOW_UPDATE can be sent by a peer that has sent a
+ // frame bearing the END_STREAM flag. This means that a
+ // receiver could receive a WINDOW_UPDATE frame on a "half
+ // closed (remote)" or "closed" stream. A receiver MUST
+ // NOT treat this as an error, see Section 5.1."
+ return nil
+ }
+ if !st.flow.add(int32(f.Increment)) {
+ return streamError(f.StreamID, ErrCodeFlowControl)
+ }
+ default: // connection-level flow control
+ if !sc.flow.add(int32(f.Increment)) {
+ return goAwayFlowError{}
+ }
+ }
+ sc.scheduleFrameWrite()
+ return nil
+}
+
+func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
+ sc.serveG.check()
+
+ state, st := sc.state(f.StreamID)
+ if state == stateIdle {
+ // 6.4 "RST_STREAM frames MUST NOT be sent for a
+ // stream in the "idle" state. If a RST_STREAM frame
+ // identifying an idle stream is received, the
+ // recipient MUST treat this as a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st != nil {
+ st.cancelCtx()
+ sc.closeStream(st, streamError(f.StreamID, f.ErrCode))
+ }
+ return nil
+}
+
+func (sc *serverConn) closeStream(st *stream, err error) {
+ sc.serveG.check()
+ if st.state == stateIdle || st.state == stateClosed {
+ panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
+ }
+ st.state = stateClosed
+ if st.writeDeadline != nil {
+ st.writeDeadline.Stop()
+ }
+ if st.isPushed() {
+ sc.curPushedStreams--
+ } else {
+ sc.curClientStreams--
+ }
+ delete(sc.streams, st.id)
+ if len(sc.streams) == 0 {
+ sc.setConnState(http.StateIdle)
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer.Reset(sc.srv.IdleTimeout)
+ }
+ if h1ServerKeepAlivesDisabled(sc.hs) {
+ sc.startGracefulShutdownInternal()
+ }
+ }
+ if p := st.body; p != nil {
+ // Return any buffered unread bytes worth of conn-level flow control.
+ // See golang.org/issue/16481
+ sc.sendWindowUpdate(nil, p.Len())
+
+ p.CloseWithError(err)
+ }
+ st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
+ sc.writeSched.CloseStream(st.id)
+}
+
+func (sc *serverConn) processSettings(f *SettingsFrame) error {
+ sc.serveG.check()
+ if f.IsAck() {
+ sc.unackedSettings--
+ if sc.unackedSettings < 0 {
+ // Why is the peer ACKing settings we never sent?
+ // The spec doesn't mention this case, but
+ // hang up on them anyway.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ return nil
+ }
+ if err := f.ForeachSetting(sc.processSetting); err != nil {
+ return err
+ }
+ sc.needToSendSettingsAck = true
+ sc.scheduleFrameWrite()
+ return nil
+}
+
+func (sc *serverConn) processSetting(s Setting) error {
+ sc.serveG.check()
+ if err := s.Valid(); err != nil {
+ return err
+ }
+ if VerboseLogs {
+ sc.vlogf("http2: server processing setting %v", s)
+ }
+ switch s.ID {
+ case SettingHeaderTableSize:
+ sc.headerTableSize = s.Val
+ sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
+ case SettingEnablePush:
+ sc.pushEnabled = s.Val != 0
+ case SettingMaxConcurrentStreams:
+ sc.clientMaxStreams = s.Val
+ case SettingInitialWindowSize:
+ return sc.processSettingInitialWindowSize(s.Val)
+ case SettingMaxFrameSize:
+ sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31
+ case SettingMaxHeaderListSize:
+ sc.peerMaxHeaderListSize = s.Val
+ default:
+ // Unknown setting: "An endpoint that receives a SETTINGS
+ // frame with any unknown or unsupported identifier MUST
+ // ignore that setting."
+ if VerboseLogs {
+ sc.vlogf("http2: server ignoring unknown setting %v", s)
+ }
+ }
+ return nil
+}
+
+func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
+ sc.serveG.check()
+ // Note: val already validated to be within range by
+ // processSetting's Valid call.
+
+ // "A SETTINGS frame can alter the initial flow control window
+ // size for all current streams. When the value of
+ // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
+ // adjust the size of all stream flow control windows that it
+ // maintains by the difference between the new value and the
+ // old value."
+ old := sc.initialStreamSendWindowSize
+ sc.initialStreamSendWindowSize = int32(val)
+ growth := int32(val) - old // may be negative
+ for _, st := range sc.streams {
+ if !st.flow.add(growth) {
+ // 6.9.2 Initial Flow Control Window Size
+ // "An endpoint MUST treat a change to
+ // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
+ // control window to exceed the maximum size as a
+ // connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR."
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ }
+ return nil
+}
+
+func (sc *serverConn) processData(f *DataFrame) error {
+ sc.serveG.check()
+ if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
+ return nil
+ }
+ data := f.Data()
+
+ // "If a DATA frame is received whose stream is not in "open"
+ // or "half closed (local)" state, the recipient MUST respond
+ // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
+ id := f.Header().StreamID
+ state, st := sc.state(id)
+ if id == 0 || state == stateIdle {
+ // Section 5.1: "Receiving any frame other than HEADERS
+ // or PRIORITY on a stream in this state MUST be
+ // treated as a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued {
+ // This includes sending a RST_STREAM if the stream is
+ // in stateHalfClosedLocal (which currently means that
+ // the http.Handler returned, so it's done reading &
+ // done writing). Try to stop the client from sending
+ // more DATA.
+
+ // But still enforce their connection-level flow control,
+ // and return any flow control bytes since we're not going
+ // to consume them.
+ if sc.inflow.available() < int32(f.Length) {
+ return streamError(id, ErrCodeFlowControl)
+ }
+ // Deduct the flow control from inflow, since we're
+ // going to immediately add it back in
+ // sendWindowUpdate, which also schedules sending the
+ // frames.
+ sc.inflow.take(int32(f.Length))
+ sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
+
+ if st != nil && st.resetQueued {
+ // Already have a stream error in flight. Don't send another.
+ return nil
+ }
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if st.body == nil {
+ panic("internal error: should have a body in this state")
+ }
+
+ // Sender sending more than they'd declared?
+ if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
+ st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if f.Length > 0 {
+ // Check whether the client has flow control quota.
+ if st.inflow.available() < int32(f.Length) {
+ return streamError(id, ErrCodeFlowControl)
+ }
+ st.inflow.take(int32(f.Length))
+
+ if len(data) > 0 {
+ wrote, err := st.body.Write(data)
+ if err != nil {
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if wrote != len(data) {
+ panic("internal error: bad Writer")
+ }
+ st.bodyBytes += int64(len(data))
+ }
+
+ // Return any padded flow control now, since we won't
+ // refund it later on body reads.
+ if pad := int32(f.Length) - int32(len(data)); pad > 0 {
+ sc.sendWindowUpdate32(nil, pad)
+ sc.sendWindowUpdate32(st, pad)
+ }
+ }
+ if f.StreamEnded() {
+ st.endStream()
+ }
+ return nil
+}
+
+func (sc *serverConn) processGoAway(f *GoAwayFrame) error {
+ sc.serveG.check()
+ if f.ErrCode != ErrCodeNo {
+ sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ } else {
+ sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ }
+ sc.startGracefulShutdownInternal()
+ // http://tools.ietf.org/html/rfc7540#section-6.8
+ // We should not create any new streams, which means we should disable push.
+ sc.pushEnabled = false
+ return nil
+}
+
+// isPushed reports whether the stream is server-initiated.
+func (st *stream) isPushed() bool {
+ return st.id%2 == 0
+}
+
+// endStream closes a Request.Body's pipe. It is called when a DATA
+// frame says a request body is over (or after trailers).
+func (st *stream) endStream() {
+ sc := st.sc
+ sc.serveG.check()
+
+ if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
+ st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
+ st.declBodyBytes, st.bodyBytes))
+ } else {
+ st.body.closeWithErrorAndCode(io.EOF, st.copyTrailersToHandlerRequest)
+ st.body.CloseWithError(io.EOF)
+ }
+ st.state = stateHalfClosedRemote
+}
+
+// copyTrailersToHandlerRequest is run in the Handler's goroutine in
+// its Request.Body.Read just before it gets io.EOF.
+func (st *stream) copyTrailersToHandlerRequest() {
+ for k, vv := range st.trailer {
+ if _, ok := st.reqTrailer[k]; ok {
+ // Only copy it over it was pre-declared.
+ st.reqTrailer[k] = vv
+ }
+ }
+}
+
+// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
+// when the stream's WriteTimeout has fired.
+func (st *stream) onWriteTimeout() {
+ st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)})
+}
+
+func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
+ sc.serveG.check()
+ id := f.StreamID
+ if sc.inGoAway {
+ // Ignore.
+ return nil
+ }
+ // http://tools.ietf.org/html/rfc7540#section-5.1.1
+ // Streams initiated by a client MUST use odd-numbered stream
+ // identifiers. [...] An endpoint that receives an unexpected
+ // stream identifier MUST respond with a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ if id%2 != 1 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ // A HEADERS frame can be used to create a new stream or
+ // send a trailer for an open one. If we already have a stream
+ // open, let it process its own HEADERS frame (trailers at this
+ // point, if it's valid).
+ if st := sc.streams[f.StreamID]; st != nil {
+ if st.resetQueued {
+ // We're sending RST_STREAM to close the stream, so don't bother
+ // processing this frame.
+ return nil
+ }
+ return st.processTrailerHeaders(f)
+ }
+
+ // [...] The identifier of a newly established stream MUST be
+ // numerically greater than all streams that the initiating
+ // endpoint has opened or reserved. [...] An endpoint that
+ // receives an unexpected stream identifier MUST respond with
+ // a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
+ if id <= sc.maxClientStreamID {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ sc.maxClientStreamID = id
+
+ if sc.idleTimer != nil {
+ sc.idleTimer.Stop()
+ }
+
+ // http://tools.ietf.org/html/rfc7540#section-5.1.2
+ // [...] Endpoints MUST NOT exceed the limit set by their peer. An
+ // endpoint that receives a HEADERS frame that causes their
+ // advertised concurrent stream limit to be exceeded MUST treat
+ // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR
+ // or REFUSED_STREAM.
+ if sc.curClientStreams+1 > sc.advMaxStreams {
+ if sc.unackedSettings == 0 {
+ // They should know better.
+ return streamError(id, ErrCodeProtocol)
+ }
+ // Assume it's a network race, where they just haven't
+ // received our last SETTINGS update. But actually
+ // this can't happen yet, because we don't yet provide
+ // a way for users to adjust server parameters at
+ // runtime.
+ return streamError(id, ErrCodeRefusedStream)
+ }
+
+ initialState := stateOpen
+ if f.StreamEnded() {
+ initialState = stateHalfClosedRemote
+ }
+ st := sc.newStream(id, 0, initialState)
+
+ if f.HasPriority() {
+ if err := checkPriority(f.StreamID, f.Priority); err != nil {
+ return err
+ }
+ sc.writeSched.AdjustStream(st.id, f.Priority)
+ }
+
+ rw, req, err := sc.newWriterAndRequest(st, f)
+ if err != nil {
+ return err
+ }
+ st.reqTrailer = req.Trailer
+ if st.reqTrailer != nil {
+ st.trailer = make(http.Header)
+ }
+ st.body = req.Body.(*requestBody).pipe // may be nil
+ st.declBodyBytes = req.ContentLength
+
+ handler := sc.handler.ServeHTTP
+ if f.Truncated {
+ // Their header list was too long. Send a 431 error.
+ handler = handleHeaderListTooLong
+ } else if err := checkValidHTTP2RequestHeaders(req.Header); err != nil {
+ handler = new400Handler(err)
+ }
+
+ // The net/http package sets the read deadline from the
+ // http.Server.ReadTimeout during the TLS handshake, but then
+ // passes the connection off to us with the deadline already
+ // set. Disarm it here after the request headers are read,
+ // similar to how the http1 server works. Here it's
+ // technically more like the http1 Server's ReadHeaderTimeout
+ // (in Go 1.8), though. That's a more sane option anyway.
+ if sc.hs.ReadTimeout != 0 {
+ sc.conn.SetReadDeadline(time.Time{})
+ }
+
+ go sc.runHandler(rw, req, handler)
+ return nil
+}
+
+func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
+ sc := st.sc
+ sc.serveG.check()
+ if st.gotTrailerHeader {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ st.gotTrailerHeader = true
+ if !f.StreamEnded() {
+ return streamError(st.id, ErrCodeProtocol)
+ }
+
+ if len(f.PseudoFields()) > 0 {
+ return streamError(st.id, ErrCodeProtocol)
+ }
+ if st.trailer != nil {
+ for _, hf := range f.RegularFields() {
+ key := sc.canonicalHeader(hf.Name)
+ if !ValidTrailerHeader(key) {
+ // TODO: send more details to the peer somehow. But http2 has
+ // no way to send debug data at a stream level. Discuss with
+ // HTTP folk.
+ return streamError(st.id, ErrCodeProtocol)
+ }
+ st.trailer[key] = append(st.trailer[key], hf.Value)
+ }
+ }
+ st.endStream()
+ return nil
+}
+
+func checkPriority(streamID uint32, p PriorityParam) error {
+ if streamID == p.StreamDep {
+ // Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
+ // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
+ // Section 5.3.3 says that a stream can depend on one of its dependencies,
+ // so it's only self-dependencies that are forbidden.
+ return streamError(streamID, ErrCodeProtocol)
+ }
+ return nil
+}
+
+func (sc *serverConn) processPriority(f *PriorityFrame) error {
+ if sc.inGoAway {
+ return nil
+ }
+ if err := checkPriority(f.StreamID, f.PriorityParam); err != nil {
+ return err
+ }
+ sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
+ return nil
+}
+
+func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream {
+ sc.serveG.check()
+ if id == 0 {
+ panic("internal error: cannot create stream with id 0")
+ }
+
+ ctx, cancelCtx := contextWithCancel(sc.baseCtx)
+ st := &stream{
+ sc: sc,
+ id: id,
+ state: state,
+ ctx: ctx,
+ cancelCtx: cancelCtx,
+ }
+ st.cw.Init()
+ st.flow.conn = &sc.flow // link to conn-level counter
+ st.flow.add(sc.initialStreamSendWindowSize)
+ st.inflow.conn = &sc.inflow // link to conn-level counter
+ st.inflow.add(sc.srv.initialStreamRecvWindowSize())
+ if sc.hs.WriteTimeout != 0 {
+ st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
+ }
+
+ sc.streams[id] = st
+ sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
+ if st.isPushed() {
+ sc.curPushedStreams++
+ } else {
+ sc.curClientStreams++
+ }
+ if sc.curOpenStreams() == 1 {
+ sc.setConnState(http.StateActive)
+ }
+
+ return st
+}
+
+func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *http.Request, error) {
+ sc.serveG.check()
+
+ rp := requestParam{
+ method: f.PseudoValue("method"),
+ scheme: f.PseudoValue("scheme"),
+ authority: f.PseudoValue("authority"),
+ path: f.PseudoValue("path"),
+ }
+
+ isConnect := rp.method == "CONNECT"
+ if isConnect {
+ if rp.path != "" || rp.scheme != "" || rp.authority == "" {
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+ } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
+ // See 8.1.2.6 Malformed Requests and Responses:
+ //
+ // Malformed requests or responses that are detected
+ // MUST be treated as a stream error (Section 5.4.2)
+ // of type PROTOCOL_ERROR."
+ //
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // "All HTTP/2 requests MUST include exactly one valid
+ // value for the :method, :scheme, and :path
+ // pseudo-header fields"
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+
+ bodyOpen := !f.StreamEnded()
+ if rp.method == "HEAD" && bodyOpen {
+ // HEAD requests can't have bodies
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+
+ rp.header = make(http.Header)
+ for _, hf := range f.RegularFields() {
+ rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
+ }
+ if rp.authority == "" {
+ rp.authority = rp.header.Get("Host")
+ }
+
+ rw, req, err := sc.newWriterAndRequestNoBody(st, rp)
+ if err != nil {
+ return nil, nil, err
+ }
+ if bodyOpen {
+ if vv, ok := rp.header["Content-Length"]; ok {
+ req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
+ } else {
+ req.ContentLength = -1
+ }
+ req.Body.(*requestBody).pipe = &pipe{
+ b: &dataBuffer{expected: req.ContentLength},
+ }
+ }
+ return rw, req, nil
+}
+
+type requestParam struct {
+ method string
+ scheme, authority, path string
+ header http.Header
+}
+
+func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*responseWriter, *http.Request, error) {
+ sc.serveG.check()
+
+ var tlsState *tls.ConnectionState // nil if not scheme https
+ if rp.scheme == "https" {
+ tlsState = sc.tlsState
+ }
+
+ needsContinue := rp.header.Get("Expect") == "100-continue"
+ if needsContinue {
+ rp.header.Del("Expect")
+ }
+ // Merge Cookie headers into one "; "-delimited value.
+ if cookies := rp.header["Cookie"]; len(cookies) > 1 {
+ rp.header.Set("Cookie", strings.Join(cookies, "; "))
+ }
+
+ // Setup Trailers
+ var trailer http.Header
+ for _, v := range rp.header["Trailer"] {
+ for _, key := range strings.Split(v, ",") {
+ key = http.CanonicalHeaderKey(strings.TrimSpace(key))
+ switch key {
+ case "Transfer-Encoding", "Trailer", "Content-Length":
+ // Bogus. (copy of http1 rules)
+ // Ignore.
+ default:
+ if trailer == nil {
+ trailer = make(http.Header)
+ }
+ trailer[key] = nil
+ }
+ }
+ }
+ delete(rp.header, "Trailer")
+
+ var url_ *url.URL
+ var requestURI string
+ if rp.method == "CONNECT" {
+ url_ = &url.URL{Host: rp.authority}
+ requestURI = rp.authority // mimic HTTP/1 server behavior
+ } else {
+ var err error
+ url_, err = url.ParseRequestURI(rp.path)
+ if err != nil {
+ return nil, nil, streamError(st.id, ErrCodeProtocol)
+ }
+ requestURI = rp.path
+ }
+
+ body := &requestBody{
+ conn: sc,
+ stream: st,
+ needsContinue: needsContinue,
+ }
+ req := &http.Request{
+ Method: rp.method,
+ URL: url_,
+ RemoteAddr: sc.remoteAddrStr,
+ Header: rp.header,
+ RequestURI: requestURI,
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ ProtoMinor: 0,
+ TLS: tlsState,
+ Host: rp.authority,
+ Body: body,
+ Trailer: trailer,
+ }
+ req = requestWithContext(req, st.ctx)
+
+ rws := responseWriterStatePool.Get().(*responseWriterState)
+ bwSave := rws.bw
+ *rws = responseWriterState{} // zero all the fields
+ rws.conn = sc
+ rws.bw = bwSave
+ rws.bw.Reset(chunkWriter{rws})
+ rws.stream = st
+ rws.req = req
+ rws.body = body
+
+ rw := &responseWriter{rws: rws}
+ return rw, req, nil
+}
+
+// Run on its own goroutine.
+func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
+ didPanic := true
+ defer func() {
+ rw.rws.stream.cancelCtx()
+ if didPanic {
+ e := recover()
+ sc.writeFrameFromHandler(FrameWriteRequest{
+ write: handlerPanicRST{rw.rws.stream.id},
+ stream: rw.rws.stream,
+ })
+ // Same as net/http:
+ if shouldLogPanic(e) {
+ const size = 64 << 10
+ buf := make([]byte, size)
+ buf = buf[:runtime.Stack(buf, false)]
+ sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf)
+ }
+ return
+ }
+ rw.handlerDone()
+ }()
+ handler(rw, req)
+ didPanic = false
+}
+
+func handleHeaderListTooLong(w http.ResponseWriter, r *http.Request) {
+ // 10.5.1 Limits on Header Block Size:
+ // .. "A server that receives a larger header block than it is
+ // willing to handle can send an HTTP 431 (Request Header Fields Too
+ // Large) status code"
+ const statusRequestHeaderFieldsTooLarge = 431 // only in Go 1.6+
+ w.WriteHeader(statusRequestHeaderFieldsTooLarge)
+ io.WriteString(w, "
+{{end}}
+
+
+`
diff --git a/vendor/golang.org/x/net/trace/histogram.go b/vendor/golang.org/x/net/trace/histogram.go
new file mode 100644
index 0000000..9bf4286
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/histogram.go
@@ -0,0 +1,365 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package trace
+
+// This file implements histogramming for RPC statistics collection.
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "log"
+ "math"
+ "sync"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+const (
+ bucketCount = 38
+)
+
+// histogram keeps counts of values in buckets that are spaced
+// out in powers of 2: 0-1, 2-3, 4-7...
+// histogram implements timeseries.Observable
+type histogram struct {
+ sum int64 // running total of measurements
+ sumOfSquares float64 // square of running total
+ buckets []int64 // bucketed values for histogram
+ value int // holds a single value as an optimization
+ valueCount int64 // number of values recorded for single value
+}
+
+// AddMeasurement records a value measurement observation to the histogram.
+func (h *histogram) addMeasurement(value int64) {
+ // TODO: assert invariant
+ h.sum += value
+ h.sumOfSquares += float64(value) * float64(value)
+
+ bucketIndex := getBucket(value)
+
+ if h.valueCount == 0 || (h.valueCount > 0 && h.value == bucketIndex) {
+ h.value = bucketIndex
+ h.valueCount++
+ } else {
+ h.allocateBuckets()
+ h.buckets[bucketIndex]++
+ }
+}
+
+func (h *histogram) allocateBuckets() {
+ if h.buckets == nil {
+ h.buckets = make([]int64, bucketCount)
+ h.buckets[h.value] = h.valueCount
+ h.value = 0
+ h.valueCount = -1
+ }
+}
+
+func log2(i int64) int {
+ n := 0
+ for ; i >= 0x100; i >>= 8 {
+ n += 8
+ }
+ for ; i > 0; i >>= 1 {
+ n += 1
+ }
+ return n
+}
+
+func getBucket(i int64) (index int) {
+ index = log2(i) - 1
+ if index < 0 {
+ index = 0
+ }
+ if index >= bucketCount {
+ index = bucketCount - 1
+ }
+ return
+}
+
+// Total returns the number of recorded observations.
+func (h *histogram) total() (total int64) {
+ if h.valueCount >= 0 {
+ total = h.valueCount
+ }
+ for _, val := range h.buckets {
+ total += int64(val)
+ }
+ return
+}
+
+// Average returns the average value of recorded observations.
+func (h *histogram) average() float64 {
+ t := h.total()
+ if t == 0 {
+ return 0
+ }
+ return float64(h.sum) / float64(t)
+}
+
+// Variance returns the variance of recorded observations.
+func (h *histogram) variance() float64 {
+ t := float64(h.total())
+ if t == 0 {
+ return 0
+ }
+ s := float64(h.sum) / t
+ return h.sumOfSquares/t - s*s
+}
+
+// StandardDeviation returns the standard deviation of recorded observations.
+func (h *histogram) standardDeviation() float64 {
+ return math.Sqrt(h.variance())
+}
+
+// PercentileBoundary estimates the value that the given fraction of recorded
+// observations are less than.
+func (h *histogram) percentileBoundary(percentile float64) int64 {
+ total := h.total()
+
+ // Corner cases (make sure result is strictly less than Total())
+ if total == 0 {
+ return 0
+ } else if total == 1 {
+ return int64(h.average())
+ }
+
+ percentOfTotal := round(float64(total) * percentile)
+ var runningTotal int64
+
+ for i := range h.buckets {
+ value := h.buckets[i]
+ runningTotal += value
+ if runningTotal == percentOfTotal {
+ // We hit an exact bucket boundary. If the next bucket has data, it is a
+ // good estimate of the value. If the bucket is empty, we interpolate the
+ // midpoint between the next bucket's boundary and the next non-zero
+ // bucket. If the remaining buckets are all empty, then we use the
+ // boundary for the next bucket as the estimate.
+ j := uint8(i + 1)
+ min := bucketBoundary(j)
+ if runningTotal < total {
+ for h.buckets[j] == 0 {
+ j++
+ }
+ }
+ max := bucketBoundary(j)
+ return min + round(float64(max-min)/2)
+ } else if runningTotal > percentOfTotal {
+ // The value is in this bucket. Interpolate the value.
+ delta := runningTotal - percentOfTotal
+ percentBucket := float64(value-delta) / float64(value)
+ bucketMin := bucketBoundary(uint8(i))
+ nextBucketMin := bucketBoundary(uint8(i + 1))
+ bucketSize := nextBucketMin - bucketMin
+ return bucketMin + round(percentBucket*float64(bucketSize))
+ }
+ }
+ return bucketBoundary(bucketCount - 1)
+}
+
+// Median returns the estimated median of the observed values.
+func (h *histogram) median() int64 {
+ return h.percentileBoundary(0.5)
+}
+
+// Add adds other to h.
+func (h *histogram) Add(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == 0 {
+ // Other histogram is empty
+ } else if h.valueCount >= 0 && o.valueCount > 0 && h.value == o.value {
+ // Both have a single bucketed value, aggregate them
+ h.valueCount += o.valueCount
+ } else {
+ // Two different values necessitate buckets in this histogram
+ h.allocateBuckets()
+ if o.valueCount >= 0 {
+ h.buckets[o.value] += o.valueCount
+ } else {
+ for i := range h.buckets {
+ h.buckets[i] += o.buckets[i]
+ }
+ }
+ }
+ h.sumOfSquares += o.sumOfSquares
+ h.sum += o.sum
+}
+
+// Clear resets the histogram to an empty state, removing all observed values.
+func (h *histogram) Clear() {
+ h.buckets = nil
+ h.value = 0
+ h.valueCount = 0
+ h.sum = 0
+ h.sumOfSquares = 0
+}
+
+// CopyFrom copies from other, which must be a *histogram, into h.
+func (h *histogram) CopyFrom(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == -1 {
+ h.allocateBuckets()
+ copy(h.buckets, o.buckets)
+ }
+ h.sum = o.sum
+ h.sumOfSquares = o.sumOfSquares
+ h.value = o.value
+ h.valueCount = o.valueCount
+}
+
+// Multiply scales the histogram by the specified ratio.
+func (h *histogram) Multiply(ratio float64) {
+ if h.valueCount == -1 {
+ for i := range h.buckets {
+ h.buckets[i] = int64(float64(h.buckets[i]) * ratio)
+ }
+ } else {
+ h.valueCount = int64(float64(h.valueCount) * ratio)
+ }
+ h.sum = int64(float64(h.sum) * ratio)
+ h.sumOfSquares = h.sumOfSquares * ratio
+}
+
+// New creates a new histogram.
+func (h *histogram) New() timeseries.Observable {
+ r := new(histogram)
+ r.Clear()
+ return r
+}
+
+func (h *histogram) String() string {
+ return fmt.Sprintf("%d, %f, %d, %d, %v",
+ h.sum, h.sumOfSquares, h.value, h.valueCount, h.buckets)
+}
+
+// round returns the closest int64 to the argument
+func round(in float64) int64 {
+ return int64(math.Floor(in + 0.5))
+}
+
+// bucketBoundary returns the first value in the bucket.
+func bucketBoundary(bucket uint8) int64 {
+ if bucket == 0 {
+ return 0
+ }
+ return 1 << bucket
+}
+
+// bucketData holds data about a specific bucket for use in distTmpl.
+type bucketData struct {
+ Lower, Upper int64
+ N int64
+ Pct, CumulativePct float64
+ GraphWidth int
+}
+
+// data holds data about a Distribution for use in distTmpl.
+type data struct {
+ Buckets []*bucketData
+ Count, Median int64
+ Mean, StandardDeviation float64
+}
+
+// maxHTMLBarWidth is the maximum width of the HTML bar for visualizing buckets.
+const maxHTMLBarWidth = 350.0
+
+// newData returns data representing h for use in distTmpl.
+func (h *histogram) newData() *data {
+ // Force the allocation of buckets to simplify the rendering implementation
+ h.allocateBuckets()
+ // We scale the bars on the right so that the largest bar is
+ // maxHTMLBarWidth pixels in width.
+ maxBucket := int64(0)
+ for _, n := range h.buckets {
+ if n > maxBucket {
+ maxBucket = n
+ }
+ }
+ total := h.total()
+ barsizeMult := maxHTMLBarWidth / float64(maxBucket)
+ var pctMult float64
+ if total == 0 {
+ pctMult = 1.0
+ } else {
+ pctMult = 100.0 / float64(total)
+ }
+
+ buckets := make([]*bucketData, len(h.buckets))
+ runningTotal := int64(0)
+ for i, n := range h.buckets {
+ if n == 0 {
+ continue
+ }
+ runningTotal += n
+ var upperBound int64
+ if i < bucketCount-1 {
+ upperBound = bucketBoundary(uint8(i + 1))
+ } else {
+ upperBound = math.MaxInt64
+ }
+ buckets[i] = &bucketData{
+ Lower: bucketBoundary(uint8(i)),
+ Upper: upperBound,
+ N: n,
+ Pct: float64(n) * pctMult,
+ CumulativePct: float64(runningTotal) * pctMult,
+ GraphWidth: int(float64(n) * barsizeMult),
+ }
+ }
+ return &data{
+ Buckets: buckets,
+ Count: total,
+ Median: h.median(),
+ Mean: h.average(),
+ StandardDeviation: h.standardDeviation(),
+ }
+}
+
+func (h *histogram) html() template.HTML {
+ buf := new(bytes.Buffer)
+ if err := distTmpl().Execute(buf, h.newData()); err != nil {
+ buf.Reset()
+ log.Printf("net/trace: couldn't execute template: %v", err)
+ }
+ return template.HTML(buf.String())
+}
+
+var distTmplCache *template.Template
+var distTmplOnce sync.Once
+
+func distTmpl() *template.Template {
+ distTmplOnce.Do(func() {
+ // Input: data
+ distTmplCache = template.Must(template.New("distTmpl").Parse(`
+
+
+
Count: {{.Count}}
+
Mean: {{printf "%.0f" .Mean}}
+
StdDev: {{printf "%.0f" .StandardDeviation}}
+
Median: {{.Median}}
+
+
+
+
+{{range $b := .Buckets}}
+{{if $b}}
+
+
[
+
{{.Lower}},
+
{{.Upper}})
+
{{.N}}
+
{{printf "%#.3f" .Pct}}%
+
{{printf "%#.3f" .CumulativePct}}%
+
+
+{{end}}
+{{end}}
+
+`))
+ })
+ return distTmplCache
+}
diff --git a/vendor/golang.org/x/net/trace/trace.go b/vendor/golang.org/x/net/trace/trace.go
new file mode 100644
index 0000000..bb72a52
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/trace.go
@@ -0,0 +1,1082 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package trace implements tracing of requests and long-lived objects.
+It exports HTTP interfaces on /debug/requests and /debug/events.
+
+A trace.Trace provides tracing for short-lived objects, usually requests.
+A request handler might be implemented like this:
+
+ func fooHandler(w http.ResponseWriter, req *http.Request) {
+ tr := trace.New("mypkg.Foo", req.URL.Path)
+ defer tr.Finish()
+ ...
+ tr.LazyPrintf("some event %q happened", str)
+ ...
+ if err := somethingImportant(); err != nil {
+ tr.LazyPrintf("somethingImportant failed: %v", err)
+ tr.SetError()
+ }
+ }
+
+The /debug/requests HTTP endpoint organizes the traces by family,
+errors, and duration. It also provides histogram of request duration
+for each family.
+
+A trace.EventLog provides tracing for long-lived objects, such as RPC
+connections.
+
+ // A Fetcher fetches URL paths for a single domain.
+ type Fetcher struct {
+ domain string
+ events trace.EventLog
+ }
+
+ func NewFetcher(domain string) *Fetcher {
+ return &Fetcher{
+ domain,
+ trace.NewEventLog("mypkg.Fetcher", domain),
+ }
+ }
+
+ func (f *Fetcher) Fetch(path string) (string, error) {
+ resp, err := http.Get("http://" + f.domain + "/" + path)
+ if err != nil {
+ f.events.Errorf("Get(%q) = %v", path, err)
+ return "", err
+ }
+ f.events.Printf("Get(%q) = %s", path, resp.Status)
+ ...
+ }
+
+ func (f *Fetcher) Close() error {
+ f.events.Finish()
+ return nil
+ }
+
+The /debug/events HTTP endpoint organizes the event logs by family and
+by time since the last error. The expanded view displays recent log
+entries and the log's call stack.
+*/
+package trace // import "golang.org/x/net/trace"
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "runtime"
+ "sort"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+// DebugUseAfterFinish controls whether to debug uses of Trace values after finishing.
+// FOR DEBUGGING ONLY. This will slow down the program.
+var DebugUseAfterFinish = false
+
+// AuthRequest determines whether a specific request is permitted to load the
+// /debug/requests or /debug/events pages.
+//
+// It returns two bools; the first indicates whether the page may be viewed at all,
+// and the second indicates whether sensitive events will be shown.
+//
+// AuthRequest may be replaced by a program to customize its authorization requirements.
+//
+// The default AuthRequest function returns (true, true) if and only if the request
+// comes from localhost/127.0.0.1/[::1].
+var AuthRequest = func(req *http.Request) (any, sensitive bool) {
+ // RemoteAddr is commonly in the form "IP" or "IP:port".
+ // If it is in the form "IP:port", split off the port.
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+ if err != nil {
+ host = req.RemoteAddr
+ }
+ switch host {
+ case "localhost", "127.0.0.1", "::1":
+ return true, true
+ default:
+ return false, false
+ }
+}
+
+func init() {
+ // TODO(jbd): Serve Traces from /debug/traces in the future?
+ // There is no requirement for a request to be present to have traces.
+ http.HandleFunc("/debug/requests", Traces)
+ http.HandleFunc("/debug/events", Events)
+}
+
+// Traces responds with traces from the program.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/requests.
+//
+// It performs authorization by running AuthRequest.
+func Traces(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ Render(w, req, sensitive)
+}
+
+// Events responds with a page of events collected by EventLogs.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/events.
+//
+// It performs authorization by running AuthRequest.
+func Events(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ RenderEvents(w, req, sensitive)
+}
+
+// Render renders the HTML page typically served at /debug/requests.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Traces handler.
+func Render(w io.Writer, req *http.Request, sensitive bool) {
+ data := &struct {
+ Families []string
+ ActiveTraceCount map[string]int
+ CompletedTraces map[string]*family
+
+ // Set when a bucket has been selected.
+ Traces traceList
+ Family string
+ Bucket int
+ Expanded bool
+ Traced bool
+ Active bool
+ ShowSensitive bool // whether to show sensitive events
+
+ Histogram template.HTML
+ HistogramWindow string // e.g. "last minute", "last hour", "all time"
+
+ // If non-zero, the set of traces is a partial set,
+ // and this is the total number.
+ Total int
+ }{
+ CompletedTraces: completedTraces,
+ }
+
+ data.ShowSensitive = sensitive
+ if req != nil {
+ // Allow show_sensitive=0 to force hiding of sensitive data for testing.
+ // This only goes one way; you can't use show_sensitive=1 to see things.
+ if req.FormValue("show_sensitive") == "0" {
+ data.ShowSensitive = false
+ }
+
+ if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil {
+ data.Expanded = exp
+ }
+ if exp, err := strconv.ParseBool(req.FormValue("rtraced")); err == nil {
+ data.Traced = exp
+ }
+ }
+
+ completedMu.RLock()
+ data.Families = make([]string, 0, len(completedTraces))
+ for fam := range completedTraces {
+ data.Families = append(data.Families, fam)
+ }
+ completedMu.RUnlock()
+ sort.Strings(data.Families)
+
+ // We are careful here to minimize the time spent locking activeMu,
+ // since that lock is required every time an RPC starts and finishes.
+ data.ActiveTraceCount = make(map[string]int, len(data.Families))
+ activeMu.RLock()
+ for fam, s := range activeTraces {
+ data.ActiveTraceCount[fam] = s.Len()
+ }
+ activeMu.RUnlock()
+
+ var ok bool
+ data.Family, data.Bucket, ok = parseArgs(req)
+ switch {
+ case !ok:
+ // No-op
+ case data.Bucket == -1:
+ data.Active = true
+ n := data.ActiveTraceCount[data.Family]
+ data.Traces = getActiveTraces(data.Family)
+ if len(data.Traces) < n {
+ data.Total = n
+ }
+ case data.Bucket < bucketsPerFamily:
+ if b := lookupBucket(data.Family, data.Bucket); b != nil {
+ data.Traces = b.Copy(data.Traced)
+ }
+ default:
+ if f := getFamily(data.Family, false); f != nil {
+ var obs timeseries.Observable
+ f.LatencyMu.RLock()
+ switch o := data.Bucket - bucketsPerFamily; o {
+ case 0:
+ obs = f.Latency.Minute()
+ data.HistogramWindow = "last minute"
+ case 1:
+ obs = f.Latency.Hour()
+ data.HistogramWindow = "last hour"
+ case 2:
+ obs = f.Latency.Total()
+ data.HistogramWindow = "all time"
+ }
+ f.LatencyMu.RUnlock()
+ if obs != nil {
+ data.Histogram = obs.(*histogram).html()
+ }
+ }
+ }
+
+ if data.Traces != nil {
+ defer data.Traces.Free()
+ sort.Sort(data.Traces)
+ }
+
+ completedMu.RLock()
+ defer completedMu.RUnlock()
+ if err := pageTmpl().ExecuteTemplate(w, "Page", data); err != nil {
+ log.Printf("net/trace: Failed executing template: %v", err)
+ }
+}
+
+func parseArgs(req *http.Request) (fam string, b int, ok bool) {
+ if req == nil {
+ return "", 0, false
+ }
+ fam, bStr := req.FormValue("fam"), req.FormValue("b")
+ if fam == "" || bStr == "" {
+ return "", 0, false
+ }
+ b, err := strconv.Atoi(bStr)
+ if err != nil || b < -1 {
+ return "", 0, false
+ }
+
+ return fam, b, true
+}
+
+func lookupBucket(fam string, b int) *traceBucket {
+ f := getFamily(fam, false)
+ if f == nil || b < 0 || b >= len(f.Buckets) {
+ return nil
+ }
+ return f.Buckets[b]
+}
+
+type contextKeyT string
+
+var contextKey = contextKeyT("golang.org/x/net/trace.Trace")
+
+// Trace represents an active request.
+type Trace interface {
+ // LazyLog adds x to the event log. It will be evaluated each time the
+ // /debug/requests page is rendered. Any memory referenced by x will be
+ // pinned until the trace is finished and later discarded.
+ LazyLog(x fmt.Stringer, sensitive bool)
+
+ // LazyPrintf evaluates its arguments with fmt.Sprintf each time the
+ // /debug/requests page is rendered. Any memory referenced by a will be
+ // pinned until the trace is finished and later discarded.
+ LazyPrintf(format string, a ...interface{})
+
+ // SetError declares that this trace resulted in an error.
+ SetError()
+
+ // SetRecycler sets a recycler for the trace.
+ // f will be called for each event passed to LazyLog at a time when
+ // it is no longer required, whether while the trace is still active
+ // and the event is discarded, or when a completed trace is discarded.
+ SetRecycler(f func(interface{}))
+
+ // SetTraceInfo sets the trace info for the trace.
+ // This is currently unused.
+ SetTraceInfo(traceID, spanID uint64)
+
+ // SetMaxEvents sets the maximum number of events that will be stored
+ // in the trace. This has no effect if any events have already been
+ // added to the trace.
+ SetMaxEvents(m int)
+
+ // Finish declares that this trace is complete.
+ // The trace should not be used after calling this method.
+ Finish()
+}
+
+type lazySprintf struct {
+ format string
+ a []interface{}
+}
+
+func (l *lazySprintf) String() string {
+ return fmt.Sprintf(l.format, l.a...)
+}
+
+// New returns a new Trace with the specified family and title.
+func New(family, title string) Trace {
+ tr := newTrace()
+ tr.ref()
+ tr.Family, tr.Title = family, title
+ tr.Start = time.Now()
+ tr.maxEvents = maxEventsPerTrace
+ tr.events = tr.eventsBuf[:0]
+
+ activeMu.RLock()
+ s := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ if s == nil {
+ activeMu.Lock()
+ s = activeTraces[tr.Family] // check again
+ if s == nil {
+ s = new(traceSet)
+ activeTraces[tr.Family] = s
+ }
+ activeMu.Unlock()
+ }
+ s.Add(tr)
+
+ // Trigger allocation of the completed trace structure for this family.
+ // This will cause the family to be present in the request page during
+ // the first trace of this family. We don't care about the return value,
+ // nor is there any need for this to run inline, so we execute it in its
+ // own goroutine, but only if the family isn't allocated yet.
+ completedMu.RLock()
+ if _, ok := completedTraces[tr.Family]; !ok {
+ go allocFamily(tr.Family)
+ }
+ completedMu.RUnlock()
+
+ return tr
+}
+
+func (tr *trace) Finish() {
+ tr.Elapsed = time.Now().Sub(tr.Start)
+ if DebugUseAfterFinish {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ tr.finishStack = buf[:n]
+ }
+
+ activeMu.RLock()
+ m := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ m.Remove(tr)
+
+ f := getFamily(tr.Family, true)
+ for _, b := range f.Buckets {
+ if b.Cond.match(tr) {
+ b.Add(tr)
+ }
+ }
+ // Add a sample of elapsed time as microseconds to the family's timeseries
+ h := new(histogram)
+ h.addMeasurement(tr.Elapsed.Nanoseconds() / 1e3)
+ f.LatencyMu.Lock()
+ f.Latency.Add(h)
+ f.LatencyMu.Unlock()
+
+ tr.unref() // matches ref in New
+}
+
+const (
+ bucketsPerFamily = 9
+ tracesPerBucket = 10
+ maxActiveTraces = 20 // Maximum number of active traces to show.
+ maxEventsPerTrace = 10
+ numHistogramBuckets = 38
+)
+
+var (
+ // The active traces.
+ activeMu sync.RWMutex
+ activeTraces = make(map[string]*traceSet) // family -> traces
+
+ // Families of completed traces.
+ completedMu sync.RWMutex
+ completedTraces = make(map[string]*family) // family -> traces
+)
+
+type traceSet struct {
+ mu sync.RWMutex
+ m map[*trace]bool
+
+ // We could avoid the entire map scan in FirstN by having a slice of all the traces
+ // ordered by start time, and an index into that from the trace struct, with a periodic
+ // repack of the slice after enough traces finish; we could also use a skip list or similar.
+ // However, that would shift some of the expense from /debug/requests time to RPC time,
+ // which is probably the wrong trade-off.
+}
+
+func (ts *traceSet) Len() int {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+ return len(ts.m)
+}
+
+func (ts *traceSet) Add(tr *trace) {
+ ts.mu.Lock()
+ if ts.m == nil {
+ ts.m = make(map[*trace]bool)
+ }
+ ts.m[tr] = true
+ ts.mu.Unlock()
+}
+
+func (ts *traceSet) Remove(tr *trace) {
+ ts.mu.Lock()
+ delete(ts.m, tr)
+ ts.mu.Unlock()
+}
+
+// FirstN returns the first n traces ordered by time.
+func (ts *traceSet) FirstN(n int) traceList {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+
+ if n > len(ts.m) {
+ n = len(ts.m)
+ }
+ trl := make(traceList, 0, n)
+
+ // Fast path for when no selectivity is needed.
+ if n == len(ts.m) {
+ for tr := range ts.m {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ sort.Sort(trl)
+ return trl
+ }
+
+ // Pick the oldest n traces.
+ // This is inefficient. See the comment in the traceSet struct.
+ for tr := range ts.m {
+ // Put the first n traces into trl in the order they occur.
+ // When we have n, sort trl, and thereafter maintain its order.
+ if len(trl) < n {
+ tr.ref()
+ trl = append(trl, tr)
+ if len(trl) == n {
+ // This is guaranteed to happen exactly once during this loop.
+ sort.Sort(trl)
+ }
+ continue
+ }
+ if tr.Start.After(trl[n-1].Start) {
+ continue
+ }
+
+ // Find where to insert this one.
+ tr.ref()
+ i := sort.Search(n, func(i int) bool { return trl[i].Start.After(tr.Start) })
+ trl[n-1].unref()
+ copy(trl[i+1:], trl[i:])
+ trl[i] = tr
+ }
+
+ return trl
+}
+
+func getActiveTraces(fam string) traceList {
+ activeMu.RLock()
+ s := activeTraces[fam]
+ activeMu.RUnlock()
+ if s == nil {
+ return nil
+ }
+ return s.FirstN(maxActiveTraces)
+}
+
+func getFamily(fam string, allocNew bool) *family {
+ completedMu.RLock()
+ f := completedTraces[fam]
+ completedMu.RUnlock()
+ if f == nil && allocNew {
+ f = allocFamily(fam)
+ }
+ return f
+}
+
+func allocFamily(fam string) *family {
+ completedMu.Lock()
+ defer completedMu.Unlock()
+ f := completedTraces[fam]
+ if f == nil {
+ f = newFamily()
+ completedTraces[fam] = f
+ }
+ return f
+}
+
+// family represents a set of trace buckets and associated latency information.
+type family struct {
+ // traces may occur in multiple buckets.
+ Buckets [bucketsPerFamily]*traceBucket
+
+ // latency time series
+ LatencyMu sync.RWMutex
+ Latency *timeseries.MinuteHourSeries
+}
+
+func newFamily() *family {
+ return &family{
+ Buckets: [bucketsPerFamily]*traceBucket{
+ {Cond: minCond(0)},
+ {Cond: minCond(50 * time.Millisecond)},
+ {Cond: minCond(100 * time.Millisecond)},
+ {Cond: minCond(200 * time.Millisecond)},
+ {Cond: minCond(500 * time.Millisecond)},
+ {Cond: minCond(1 * time.Second)},
+ {Cond: minCond(10 * time.Second)},
+ {Cond: minCond(100 * time.Second)},
+ {Cond: errorCond{}},
+ },
+ Latency: timeseries.NewMinuteHourSeries(func() timeseries.Observable { return new(histogram) }),
+ }
+}
+
+// traceBucket represents a size-capped bucket of historic traces,
+// along with a condition for a trace to belong to the bucket.
+type traceBucket struct {
+ Cond cond
+
+ // Ring buffer implementation of a fixed-size FIFO queue.
+ mu sync.RWMutex
+ buf [tracesPerBucket]*trace
+ start int // < tracesPerBucket
+ length int // <= tracesPerBucket
+}
+
+func (b *traceBucket) Add(tr *trace) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ i := b.start + b.length
+ if i >= tracesPerBucket {
+ i -= tracesPerBucket
+ }
+ if b.length == tracesPerBucket {
+ // "Remove" an element from the bucket.
+ b.buf[i].unref()
+ b.start++
+ if b.start == tracesPerBucket {
+ b.start = 0
+ }
+ }
+ b.buf[i] = tr
+ if b.length < tracesPerBucket {
+ b.length++
+ }
+ tr.ref()
+}
+
+// Copy returns a copy of the traces in the bucket.
+// If tracedOnly is true, only the traces with trace information will be returned.
+// The logs will be ref'd before returning; the caller should call
+// the Free method when it is done with them.
+// TODO(dsymonds): keep track of traced requests in separate buckets.
+func (b *traceBucket) Copy(tracedOnly bool) traceList {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+
+ trl := make(traceList, 0, b.length)
+ for i, x := 0, b.start; i < b.length; i++ {
+ tr := b.buf[x]
+ if !tracedOnly || tr.spanID != 0 {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ x++
+ if x == b.length {
+ x = 0
+ }
+ }
+ return trl
+}
+
+func (b *traceBucket) Empty() bool {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ return b.length == 0
+}
+
+// cond represents a condition on a trace.
+type cond interface {
+ match(t *trace) bool
+ String() string
+}
+
+type minCond time.Duration
+
+func (m minCond) match(t *trace) bool { return t.Elapsed >= time.Duration(m) }
+func (m minCond) String() string { return fmt.Sprintf("≥%gs", time.Duration(m).Seconds()) }
+
+type errorCond struct{}
+
+func (e errorCond) match(t *trace) bool { return t.IsError }
+func (e errorCond) String() string { return "errors" }
+
+type traceList []*trace
+
+// Free calls unref on each element of the list.
+func (trl traceList) Free() {
+ for _, t := range trl {
+ t.unref()
+ }
+}
+
+// traceList may be sorted in reverse chronological order.
+func (trl traceList) Len() int { return len(trl) }
+func (trl traceList) Less(i, j int) bool { return trl[i].Start.After(trl[j].Start) }
+func (trl traceList) Swap(i, j int) { trl[i], trl[j] = trl[j], trl[i] }
+
+// An event is a timestamped log entry in a trace.
+type event struct {
+ When time.Time
+ Elapsed time.Duration // since previous event in trace
+ NewDay bool // whether this event is on a different day to the previous event
+ Recyclable bool // whether this event was passed via LazyLog
+ Sensitive bool // whether this event contains sensitive information
+ What interface{} // string or fmt.Stringer
+}
+
+// WhenString returns a string representation of the elapsed time of the event.
+// It will include the date if midnight was crossed.
+func (e event) WhenString() string {
+ if e.NewDay {
+ return e.When.Format("2006/01/02 15:04:05.000000")
+ }
+ return e.When.Format("15:04:05.000000")
+}
+
+// discarded represents a number of discarded events.
+// It is stored as *discarded to make it easier to update in-place.
+type discarded int
+
+func (d *discarded) String() string {
+ return fmt.Sprintf("(%d events discarded)", int(*d))
+}
+
+// trace represents an active or complete request,
+// either sent or received by this program.
+type trace struct {
+ // Family is the top-level grouping of traces to which this belongs.
+ Family string
+
+ // Title is the title of this trace.
+ Title string
+
+ // Timing information.
+ Start time.Time
+ Elapsed time.Duration // zero while active
+
+ // Trace information if non-zero.
+ traceID uint64
+ spanID uint64
+
+ // Whether this trace resulted in an error.
+ IsError bool
+
+ // Append-only sequence of events (modulo discards).
+ mu sync.RWMutex
+ events []event
+ maxEvents int
+
+ refs int32 // how many buckets this is in
+ recycler func(interface{})
+ disc discarded // scratch space to avoid allocation
+
+ finishStack []byte // where finish was called, if DebugUseAfterFinish is set
+
+ eventsBuf [4]event // preallocated buffer in case we only log a few events
+}
+
+func (tr *trace) reset() {
+ // Clear all but the mutex. Mutexes may not be copied, even when unlocked.
+ tr.Family = ""
+ tr.Title = ""
+ tr.Start = time.Time{}
+ tr.Elapsed = 0
+ tr.traceID = 0
+ tr.spanID = 0
+ tr.IsError = false
+ tr.maxEvents = 0
+ tr.events = nil
+ tr.refs = 0
+ tr.recycler = nil
+ tr.disc = 0
+ tr.finishStack = nil
+ for i := range tr.eventsBuf {
+ tr.eventsBuf[i] = event{}
+ }
+}
+
+// delta returns the elapsed time since the last event or the trace start,
+// and whether it spans midnight.
+// L >= tr.mu
+func (tr *trace) delta(t time.Time) (time.Duration, bool) {
+ if len(tr.events) == 0 {
+ return t.Sub(tr.Start), false
+ }
+ prev := tr.events[len(tr.events)-1].When
+ return t.Sub(prev), prev.Day() != t.Day()
+}
+
+func (tr *trace) addEvent(x interface{}, recyclable, sensitive bool) {
+ if DebugUseAfterFinish && tr.finishStack != nil {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ log.Printf("net/trace: trace used after finish:\nFinished at:\n%s\nUsed at:\n%s", tr.finishStack, buf[:n])
+ }
+
+ /*
+ NOTE TO DEBUGGERS
+
+ If you are here because your program panicked in this code,
+ it is almost definitely the fault of code using this package,
+ and very unlikely to be the fault of this code.
+
+ The most likely scenario is that some code elsewhere is using
+ a trace.Trace after its Finish method is called.
+ You can temporarily set the DebugUseAfterFinish var
+ to help discover where that is; do not leave that var set,
+ since it makes this package much less efficient.
+ */
+
+ e := event{When: time.Now(), What: x, Recyclable: recyclable, Sensitive: sensitive}
+ tr.mu.Lock()
+ e.Elapsed, e.NewDay = tr.delta(e.When)
+ if len(tr.events) < tr.maxEvents {
+ tr.events = append(tr.events, e)
+ } else {
+ // Discard the middle events.
+ di := int((tr.maxEvents - 1) / 2)
+ if d, ok := tr.events[di].What.(*discarded); ok {
+ (*d)++
+ } else {
+ // disc starts at two to count for the event it is replacing,
+ // plus the next one that we are about to drop.
+ tr.disc = 2
+ if tr.recycler != nil && tr.events[di].Recyclable {
+ go tr.recycler(tr.events[di].What)
+ }
+ tr.events[di].What = &tr.disc
+ }
+ // The timestamp of the discarded meta-event should be
+ // the time of the last event it is representing.
+ tr.events[di].When = tr.events[di+1].When
+
+ if tr.recycler != nil && tr.events[di+1].Recyclable {
+ go tr.recycler(tr.events[di+1].What)
+ }
+ copy(tr.events[di+1:], tr.events[di+2:])
+ tr.events[tr.maxEvents-1] = e
+ }
+ tr.mu.Unlock()
+}
+
+func (tr *trace) LazyLog(x fmt.Stringer, sensitive bool) {
+ tr.addEvent(x, true, sensitive)
+}
+
+func (tr *trace) LazyPrintf(format string, a ...interface{}) {
+ tr.addEvent(&lazySprintf{format, a}, false, false)
+}
+
+func (tr *trace) SetError() { tr.IsError = true }
+
+func (tr *trace) SetRecycler(f func(interface{})) {
+ tr.recycler = f
+}
+
+func (tr *trace) SetTraceInfo(traceID, spanID uint64) {
+ tr.traceID, tr.spanID = traceID, spanID
+}
+
+func (tr *trace) SetMaxEvents(m int) {
+ // Always keep at least three events: first, discarded count, last.
+ if len(tr.events) == 0 && m > 3 {
+ tr.maxEvents = m
+ }
+}
+
+func (tr *trace) ref() {
+ atomic.AddInt32(&tr.refs, 1)
+}
+
+func (tr *trace) unref() {
+ if atomic.AddInt32(&tr.refs, -1) == 0 {
+ if tr.recycler != nil {
+ // freeTrace clears tr, so we hold tr.recycler and tr.events here.
+ go func(f func(interface{}), es []event) {
+ for _, e := range es {
+ if e.Recyclable {
+ f(e.What)
+ }
+ }
+ }(tr.recycler, tr.events)
+ }
+
+ freeTrace(tr)
+ }
+}
+
+func (tr *trace) When() string {
+ return tr.Start.Format("2006/01/02 15:04:05.000000")
+}
+
+func (tr *trace) ElapsedTime() string {
+ t := tr.Elapsed
+ if t == 0 {
+ // Active trace.
+ t = time.Since(tr.Start)
+ }
+ return fmt.Sprintf("%.6f", t.Seconds())
+}
+
+func (tr *trace) Events() []event {
+ tr.mu.RLock()
+ defer tr.mu.RUnlock()
+ return tr.events
+}
+
+var traceFreeList = make(chan *trace, 1000) // TODO(dsymonds): Use sync.Pool?
+
+// newTrace returns a trace ready to use.
+func newTrace() *trace {
+ select {
+ case tr := <-traceFreeList:
+ return tr
+ default:
+ return new(trace)
+ }
+}
+
+// freeTrace adds tr to traceFreeList if there's room.
+// This is non-blocking.
+func freeTrace(tr *trace) {
+ if DebugUseAfterFinish {
+ return // never reuse
+ }
+ tr.reset()
+ select {
+ case traceFreeList <- tr:
+ default:
+ }
+}
+
+func elapsed(d time.Duration) string {
+ b := []byte(fmt.Sprintf("%.6f", d.Seconds()))
+
+ // For subsecond durations, blank all zeros before decimal point,
+ // and all zeros between the decimal point and the first non-zero digit.
+ if d < time.Second {
+ dot := bytes.IndexByte(b, '.')
+ for i := 0; i < dot; i++ {
+ b[i] = ' '
+ }
+ for i := dot + 1; i < len(b); i++ {
+ if b[i] == '0' {
+ b[i] = ' '
+ } else {
+ break
+ }
+ }
+ }
+
+ return string(b)
+}
+
+var pageTmplCache *template.Template
+var pageTmplOnce sync.Once
+
+func pageTmpl() *template.Template {
+ pageTmplOnce.Do(func() {
+ pageTmplCache = template.Must(template.New("Page").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "add": func(a, b int) int { return a + b },
+ }).Parse(pageHTML))
+ })
+ return pageTmplCache
+}
+
+const pageHTML = `
+{{template "Prolog" .}}
+{{template "StatusTable" .}}
+{{template "Epilog" .}}
+
+{{define "Prolog"}}
+
+
+ /debug/requests
+
+
+
+
+
/debug/requests
+{{end}} {{/* end of Prolog */}}
+
+{{define "StatusTable"}}
+
{{if or $.ShowSensitive (not .Sensitive)}}... {{.What}}{{else}}[redacted]{{end}}
+
+ {{end}}
+ {{end}}
+ {{end}}
+
+{{end}} {{/* if $.Traces */}}
+
+{{if $.Histogram}}
+
Latency (µs) of {{$.Family}} over {{$.HistogramWindow}}
+{{$.Histogram}}
+{{end}} {{/* if $.Histogram */}}
+
+
+
+{{end}} {{/* end of Epilog */}}
+`
diff --git a/vendor/golang.org/x/net/trace/trace_go16.go b/vendor/golang.org/x/net/trace/trace_go16.go
new file mode 100644
index 0000000..d608191
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/trace_go16.go
@@ -0,0 +1,21 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package trace
+
+import "golang.org/x/net/context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
diff --git a/vendor/golang.org/x/net/trace/trace_go17.go b/vendor/golang.org/x/net/trace/trace_go17.go
new file mode 100644
index 0000000..df6e1fb
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/trace_go17.go
@@ -0,0 +1,21 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+package trace
+
+import "context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
diff --git a/vendor/golang.org/x/oauth2/AUTHORS b/vendor/golang.org/x/oauth2/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md
new file mode 100644
index 0000000..46aa2b1
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+
+## Filing issues
+
+When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+**We do not accept GitHub pull requests**
+(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
+
diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTORS b/vendor/golang.org/x/oauth2/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md
new file mode 100644
index 0000000..eb8dcee
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/README.md
@@ -0,0 +1,77 @@
+# OAuth2 for Go
+
+[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2)
+[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2)
+
+oauth2 package contains a client implementation for OAuth 2.0 spec.
+
+## Installation
+
+~~~~
+go get golang.org/x/oauth2
+~~~~
+
+Or you can manually git clone the repository to
+`$(go env GOPATH)/src/golang.org/x/oauth2`.
+
+See godoc for further documentation and examples.
+
+* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2)
+* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google)
+
+
+## App Engine
+
+In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor
+of the [`context.Context`](https://golang.org/x/net/context#Context) type from
+the `golang.org/x/net/context` package
+
+This means it's no longer possible to use the "Classic App Engine"
+`appengine.Context` type with the `oauth2` package. (You're using
+Classic App Engine if you import the package `"appengine"`.)
+
+To work around this, you may use the new `"google.golang.org/appengine"`
+package. This package has almost the same API as the `"appengine"` package,
+but it can be fetched with `go get` and used on "Managed VMs" and well as
+Classic App Engine.
+
+See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app)
+for information on updating your app.
+
+If you don't want to update your entire app to use the new App Engine packages,
+you may use both sets of packages in parallel, using only the new packages
+with the `oauth2` package.
+
+```go
+import (
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ newappengine "google.golang.org/appengine"
+ newurlfetch "google.golang.org/appengine/urlfetch"
+
+ "appengine"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ var c appengine.Context = appengine.NewContext(r)
+ c.Infof("Logging a message with the old package")
+
+ var ctx context.Context = newappengine.NewContext(r)
+ client := &http.Client{
+ Transport: &oauth2.Transport{
+ Source: google.AppEngineTokenSource(ctx, "scope"),
+ Base: &newurlfetch.Transport{Context: ctx},
+ },
+ }
+ client.Get("...")
+}
+```
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit changes to
+this repository, see https://golang.org/doc/contribute.html.
+
+The main issue tracker for the oauth2 repository is located at
+https://github.com/golang/oauth2/issues.
diff --git a/vendor/golang.org/x/oauth2/amazon/amazon.go b/vendor/golang.org/x/oauth2/amazon/amazon.go
new file mode 100644
index 0000000..d21da11
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/amazon/amazon.go
@@ -0,0 +1,16 @@
+// Copyright 2017 The oauth2 Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package amazon provides constants for using OAuth2 to access Amazon.
+package amazon
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Amazon's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.amazon.com/ap/oa",
+ TokenURL: "https://api.amazon.com/auth/o2/token",
+}
diff --git a/vendor/golang.org/x/oauth2/bitbucket/bitbucket.go b/vendor/golang.org/x/oauth2/bitbucket/bitbucket.go
new file mode 100644
index 0000000..44af1f1
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/bitbucket/bitbucket.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The oauth2 Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bitbucket provides constants for using OAuth2 to access Bitbucket.
+package bitbucket
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Bitbucket's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://bitbucket.org/site/oauth2/authorize",
+ TokenURL: "https://bitbucket.org/site/oauth2/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/client_appengine.go b/vendor/golang.org/x/oauth2/client_appengine.go
new file mode 100644
index 0000000..8962c49
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/client_appengine.go
@@ -0,0 +1,25 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+// App Engine hooks.
+
+package oauth2
+
+import (
+ "net/http"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2/internal"
+ "google.golang.org/appengine/urlfetch"
+)
+
+func init() {
+ internal.RegisterContextClientFunc(contextClientAppEngine)
+}
+
+func contextClientAppEngine(ctx context.Context) (*http.Client, error) {
+ return urlfetch.Client(ctx), nil
+}
diff --git a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
new file mode 100644
index 0000000..53a96b6
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
@@ -0,0 +1,104 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package clientcredentials implements the OAuth2.0 "client credentials" token flow,
+// also known as the "two-legged OAuth 2.0".
+//
+// This should be used when the client is acting on its own behalf or when the client
+// is the resource owner. It may also be used when requesting access to protected
+// resources based on an authorization previously arranged with the authorization
+// server.
+//
+// See https://tools.ietf.org/html/rfc6749#section-4.4
+package clientcredentials // import "golang.org/x/oauth2/clientcredentials"
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+)
+
+// Config describes a 2-legged OAuth2 flow, with both the
+// client application information and the server's endpoint URLs.
+type Config struct {
+ // ClientID is the application's ID.
+ ClientID string
+
+ // ClientSecret is the application's secret.
+ ClientSecret string
+
+ // TokenURL is the resource server's token endpoint
+ // URL. This is a constant specific to each server.
+ TokenURL string
+
+ // Scope specifies optional requested permissions.
+ Scopes []string
+
+ // EndpointParams specifies additional parameters for requests to the token endpoint.
+ EndpointParams url.Values
+}
+
+// Token uses client credentials to retrieve a token.
+// The HTTP client to use is derived from the context.
+// If nil, http.DefaultClient is used.
+func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) {
+ return c.TokenSource(ctx).Token()
+}
+
+// Client returns an HTTP client using the provided token.
+// The token will auto-refresh as necessary. The underlying
+// HTTP transport will be obtained using the provided context.
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context) *http.Client {
+ return oauth2.NewClient(ctx, c.TokenSource(ctx))
+}
+
+// TokenSource returns a TokenSource that returns t until t expires,
+// automatically refreshing it as necessary using the provided context and the
+// client ID and client secret.
+//
+// Most users will use Config.Client instead.
+func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
+ source := &tokenSource{
+ ctx: ctx,
+ conf: c,
+ }
+ return oauth2.ReuseTokenSource(nil, source)
+}
+
+type tokenSource struct {
+ ctx context.Context
+ conf *Config
+}
+
+// Token refreshes the token by using a new client credentials request.
+// tokens received this way do not include a refresh token
+func (c *tokenSource) Token() (*oauth2.Token, error) {
+ v := url.Values{
+ "grant_type": {"client_credentials"},
+ "scope": internal.CondVal(strings.Join(c.conf.Scopes, " ")),
+ }
+ for k, p := range c.conf.EndpointParams {
+ if _, ok := v[k]; ok {
+ return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k)
+ }
+ v[k] = p
+ }
+ tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v)
+ if err != nil {
+ return nil, err
+ }
+ t := &oauth2.Token{
+ AccessToken: tk.AccessToken,
+ TokenType: tk.TokenType,
+ RefreshToken: tk.RefreshToken,
+ Expiry: tk.Expiry,
+ }
+ return t.WithExtra(tk.Raw), nil
+}
diff --git a/vendor/golang.org/x/oauth2/facebook/facebook.go b/vendor/golang.org/x/oauth2/facebook/facebook.go
new file mode 100644
index 0000000..14c801a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/facebook/facebook.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package facebook provides constants for using OAuth2 to access Facebook.
+package facebook // import "golang.org/x/oauth2/facebook"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Facebook's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.facebook.com/dialog/oauth",
+ TokenURL: "https://graph.facebook.com/oauth/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/fitbit/fitbit.go b/vendor/golang.org/x/oauth2/fitbit/fitbit.go
new file mode 100644
index 0000000..b31b82a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/fitbit/fitbit.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package fitbit provides constants for using OAuth2 to access the Fitbit API.
+package fitbit // import "golang.org/x/oauth2/fitbit"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is the Fitbit API's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.fitbit.com/oauth2/authorize",
+ TokenURL: "https://api.fitbit.com/oauth2/token",
+}
diff --git a/vendor/golang.org/x/oauth2/foursquare/foursquare.go b/vendor/golang.org/x/oauth2/foursquare/foursquare.go
new file mode 100644
index 0000000..d2fa099
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/foursquare/foursquare.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package foursquare provides constants for using OAuth2 to access Foursquare.
+package foursquare // import "golang.org/x/oauth2/foursquare"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Foursquare's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://foursquare.com/oauth2/authorize",
+ TokenURL: "https://foursquare.com/oauth2/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/github/github.go b/vendor/golang.org/x/oauth2/github/github.go
new file mode 100644
index 0000000..f297801
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/github/github.go
@@ -0,0 +1,16 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package github provides constants for using OAuth2 to access Github.
+package github // import "golang.org/x/oauth2/github"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Github's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://github.com/login/oauth/authorize",
+ TokenURL: "https://github.com/login/oauth/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/google/appengine.go b/vendor/golang.org/x/oauth2/google/appengine.go
new file mode 100644
index 0000000..50d918b
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengine.go
@@ -0,0 +1,89 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+)
+
+// appengineFlex is set at init time by appengineflex_hook.go. If true, we are on App Engine Flex.
+var appengineFlex bool
+
+// Set at init time by appengine_hook.go. If nil, we're not on App Engine.
+var appengineTokenFunc func(c context.Context, scopes ...string) (token string, expiry time.Time, err error)
+
+// Set at init time by appengine_hook.go. If nil, we're not on App Engine.
+var appengineAppIDFunc func(c context.Context) string
+
+// AppEngineTokenSource returns a token source that fetches tokens
+// issued to the current App Engine application's service account.
+// If you are implementing a 3-legged OAuth 2.0 flow on App Engine
+// that involves user accounts, see oauth2.Config instead.
+//
+// The provided context must have come from appengine.NewContext.
+func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
+ if appengineTokenFunc == nil {
+ panic("google: AppEngineTokenSource can only be used on App Engine.")
+ }
+ scopes := append([]string{}, scope...)
+ sort.Strings(scopes)
+ return &appEngineTokenSource{
+ ctx: ctx,
+ scopes: scopes,
+ key: strings.Join(scopes, " "),
+ }
+}
+
+// aeTokens helps the fetched tokens to be reused until their expiration.
+var (
+ aeTokensMu sync.Mutex
+ aeTokens = make(map[string]*tokenLock) // key is space-separated scopes
+)
+
+type tokenLock struct {
+ mu sync.Mutex // guards t; held while fetching or updating t
+ t *oauth2.Token
+}
+
+type appEngineTokenSource struct {
+ ctx context.Context
+ scopes []string
+ key string // to aeTokens map; space-separated scopes
+}
+
+func (ts *appEngineTokenSource) Token() (*oauth2.Token, error) {
+ if appengineTokenFunc == nil {
+ panic("google: AppEngineTokenSource can only be used on App Engine.")
+ }
+
+ aeTokensMu.Lock()
+ tok, ok := aeTokens[ts.key]
+ if !ok {
+ tok = &tokenLock{}
+ aeTokens[ts.key] = tok
+ }
+ aeTokensMu.Unlock()
+
+ tok.mu.Lock()
+ defer tok.mu.Unlock()
+ if tok.t.Valid() {
+ return tok.t, nil
+ }
+ access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...)
+ if err != nil {
+ return nil, err
+ }
+ tok.t = &oauth2.Token{
+ AccessToken: access,
+ Expiry: exp,
+ }
+ return tok.t, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/appengine_hook.go b/vendor/golang.org/x/oauth2/google/appengine_hook.go
new file mode 100644
index 0000000..56669ea
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengine_hook.go
@@ -0,0 +1,14 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine appenginevm
+
+package google
+
+import "google.golang.org/appengine"
+
+func init() {
+ appengineTokenFunc = appengine.AccessToken
+ appengineAppIDFunc = appengine.AppID
+}
diff --git a/vendor/golang.org/x/oauth2/google/appengineflex_hook.go b/vendor/golang.org/x/oauth2/google/appengineflex_hook.go
new file mode 100644
index 0000000..5d0231a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengineflex_hook.go
@@ -0,0 +1,11 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appenginevm
+
+package google
+
+func init() {
+ appengineFlex = true // Flex doesn't support appengine.AccessToken; depend on metadata server.
+}
diff --git a/vendor/golang.org/x/oauth2/google/default.go b/vendor/golang.org/x/oauth2/google/default.go
new file mode 100644
index 0000000..b4b6274
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/default.go
@@ -0,0 +1,137 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "cloud.google.com/go/compute/metadata"
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+)
+
+// DefaultCredentials holds "Application Default Credentials".
+// For more details, see:
+// https://developers.google.com/accounts/docs/application-default-credentials
+type DefaultCredentials struct {
+ ProjectID string // may be empty
+ TokenSource oauth2.TokenSource
+
+ // JSON contains the raw bytes from a JSON credentials file.
+ // This field may be nil if authentication is provided by the
+ // environment and not with a credentials file, e.g. when code is
+ // running on Google Cloud Platform.
+ JSON []byte
+}
+
+// DefaultClient returns an HTTP Client that uses the
+// DefaultTokenSource to obtain authentication credentials.
+func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) {
+ ts, err := DefaultTokenSource(ctx, scope...)
+ if err != nil {
+ return nil, err
+ }
+ return oauth2.NewClient(ctx, ts), nil
+}
+
+// DefaultTokenSource returns the token source for
+// "Application Default Credentials".
+// It is a shortcut for FindDefaultCredentials(ctx, scope).TokenSource.
+func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) {
+ creds, err := FindDefaultCredentials(ctx, scope...)
+ if err != nil {
+ return nil, err
+ }
+ return creds.TokenSource, nil
+}
+
+// FindDefaultCredentials searches for "Application Default Credentials".
+//
+// It looks for credentials in the following places,
+// preferring the first location found:
+//
+// 1. A JSON file whose path is specified by the
+// GOOGLE_APPLICATION_CREDENTIALS environment variable.
+// 2. A JSON file in a location known to the gcloud command-line tool.
+// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json.
+// On other systems, $HOME/.config/gcloud/application_default_credentials.json.
+// 3. On Google App Engine it uses the appengine.AccessToken function.
+// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches
+// credentials from the metadata server.
+// (In this final case any provided scopes are ignored.)
+func FindDefaultCredentials(ctx context.Context, scope ...string) (*DefaultCredentials, error) {
+ // First, try the environment variable.
+ const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
+ if filename := os.Getenv(envVar); filename != "" {
+ creds, err := readCredentialsFile(ctx, filename, scope)
+ if err != nil {
+ return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err)
+ }
+ return creds, nil
+ }
+
+ // Second, try a well-known file.
+ filename := wellKnownFile()
+ if creds, err := readCredentialsFile(ctx, filename, scope); err == nil {
+ return creds, nil
+ } else if !os.IsNotExist(err) {
+ return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err)
+ }
+
+ // Third, if we're on Google App Engine use those credentials.
+ if appengineTokenFunc != nil && !appengineFlex {
+ return &DefaultCredentials{
+ ProjectID: appengineAppIDFunc(ctx),
+ TokenSource: AppEngineTokenSource(ctx, scope...),
+ }, nil
+ }
+
+ // Fourth, if we're on Google Compute Engine use the metadata server.
+ if metadata.OnGCE() {
+ id, _ := metadata.ProjectID()
+ return &DefaultCredentials{
+ ProjectID: id,
+ TokenSource: ComputeTokenSource(""),
+ }, nil
+ }
+
+ // None are found; return helpful error.
+ const url = "https://developers.google.com/accounts/docs/application-default-credentials"
+ return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url)
+}
+
+func wellKnownFile() string {
+ const f = "application_default_credentials.json"
+ if runtime.GOOS == "windows" {
+ return filepath.Join(os.Getenv("APPDATA"), "gcloud", f)
+ }
+ return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f)
+}
+
+func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) {
+ b, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ var f credentialsFile
+ if err := json.Unmarshal(b, &f); err != nil {
+ return nil, err
+ }
+ ts, err := f.tokenSource(ctx, append([]string(nil), scopes...))
+ if err != nil {
+ return nil, err
+ }
+ return &DefaultCredentials{
+ ProjectID: f.ProjectID,
+ TokenSource: ts,
+ JSON: b,
+ }, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/google.go b/vendor/golang.org/x/oauth2/google/google.go
new file mode 100644
index 0000000..66a8b0e
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/google.go
@@ -0,0 +1,202 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package google provides support for making OAuth2 authorized and
+// authenticated HTTP requests to Google APIs.
+// It supports the Web server flow, client-side credentials, service accounts,
+// Google Compute Engine service accounts, and Google App Engine service
+// accounts.
+//
+// For more information, please read
+// https://developers.google.com/accounts/docs/OAuth2
+// and
+// https://developers.google.com/accounts/docs/application-default-credentials.
+package google // import "golang.org/x/oauth2/google"
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "cloud.google.com/go/compute/metadata"
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/jwt"
+)
+
+// Endpoint is Google's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://accounts.google.com/o/oauth2/auth",
+ TokenURL: "https://accounts.google.com/o/oauth2/token",
+}
+
+// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
+const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"
+
+// ConfigFromJSON uses a Google Developers Console client_credentials.json
+// file to construct a config.
+// client_credentials.json can be downloaded from
+// https://console.developers.google.com, under "Credentials". Download the Web
+// application credentials in the JSON format and provide the contents of the
+// file as jsonKey.
+func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) {
+ type cred struct {
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+ RedirectURIs []string `json:"redirect_uris"`
+ AuthURI string `json:"auth_uri"`
+ TokenURI string `json:"token_uri"`
+ }
+ var j struct {
+ Web *cred `json:"web"`
+ Installed *cred `json:"installed"`
+ }
+ if err := json.Unmarshal(jsonKey, &j); err != nil {
+ return nil, err
+ }
+ var c *cred
+ switch {
+ case j.Web != nil:
+ c = j.Web
+ case j.Installed != nil:
+ c = j.Installed
+ default:
+ return nil, fmt.Errorf("oauth2/google: no credentials found")
+ }
+ if len(c.RedirectURIs) < 1 {
+ return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json")
+ }
+ return &oauth2.Config{
+ ClientID: c.ClientID,
+ ClientSecret: c.ClientSecret,
+ RedirectURL: c.RedirectURIs[0],
+ Scopes: scope,
+ Endpoint: oauth2.Endpoint{
+ AuthURL: c.AuthURI,
+ TokenURL: c.TokenURI,
+ },
+ }, nil
+}
+
+// JWTConfigFromJSON uses a Google Developers service account JSON key file to read
+// the credentials that authorize and authenticate the requests.
+// Create a service account on "Credentials" for your project at
+// https://console.developers.google.com to download a JSON key file.
+func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
+ var f credentialsFile
+ if err := json.Unmarshal(jsonKey, &f); err != nil {
+ return nil, err
+ }
+ if f.Type != serviceAccountKey {
+ return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey)
+ }
+ scope = append([]string(nil), scope...) // copy
+ return f.jwtConfig(scope), nil
+}
+
+// JSON key file types.
+const (
+ serviceAccountKey = "service_account"
+ userCredentialsKey = "authorized_user"
+)
+
+// credentialsFile is the unmarshalled representation of a credentials file.
+type credentialsFile struct {
+ Type string `json:"type"` // serviceAccountKey or userCredentialsKey
+
+ // Service Account fields
+ ClientEmail string `json:"client_email"`
+ PrivateKeyID string `json:"private_key_id"`
+ PrivateKey string `json:"private_key"`
+ TokenURL string `json:"token_uri"`
+ ProjectID string `json:"project_id"`
+
+ // User Credential fields
+ // (These typically come from gcloud auth.)
+ ClientSecret string `json:"client_secret"`
+ ClientID string `json:"client_id"`
+ RefreshToken string `json:"refresh_token"`
+}
+
+func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config {
+ cfg := &jwt.Config{
+ Email: f.ClientEmail,
+ PrivateKey: []byte(f.PrivateKey),
+ PrivateKeyID: f.PrivateKeyID,
+ Scopes: scopes,
+ TokenURL: f.TokenURL,
+ }
+ if cfg.TokenURL == "" {
+ cfg.TokenURL = JWTTokenURL
+ }
+ return cfg
+}
+
+func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) {
+ switch f.Type {
+ case serviceAccountKey:
+ cfg := f.jwtConfig(scopes)
+ return cfg.TokenSource(ctx), nil
+ case userCredentialsKey:
+ cfg := &oauth2.Config{
+ ClientID: f.ClientID,
+ ClientSecret: f.ClientSecret,
+ Scopes: scopes,
+ Endpoint: Endpoint,
+ }
+ tok := &oauth2.Token{RefreshToken: f.RefreshToken}
+ return cfg.TokenSource(ctx, tok), nil
+ case "":
+ return nil, errors.New("missing 'type' field in credentials")
+ default:
+ return nil, fmt.Errorf("unknown credential type: %q", f.Type)
+ }
+}
+
+// ComputeTokenSource returns a token source that fetches access tokens
+// from Google Compute Engine (GCE)'s metadata server. It's only valid to use
+// this token source if your program is running on a GCE instance.
+// If no account is specified, "default" is used.
+// Further information about retrieving access tokens from the GCE metadata
+// server can be found at https://cloud.google.com/compute/docs/authentication.
+func ComputeTokenSource(account string) oauth2.TokenSource {
+ return oauth2.ReuseTokenSource(nil, computeSource{account: account})
+}
+
+type computeSource struct {
+ account string
+}
+
+func (cs computeSource) Token() (*oauth2.Token, error) {
+ if !metadata.OnGCE() {
+ return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
+ }
+ acct := cs.account
+ if acct == "" {
+ acct = "default"
+ }
+ tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
+ if err != nil {
+ return nil, err
+ }
+ var res struct {
+ AccessToken string `json:"access_token"`
+ ExpiresInSec int `json:"expires_in"`
+ TokenType string `json:"token_type"`
+ }
+ err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
+ }
+ if res.ExpiresInSec == 0 || res.AccessToken == "" {
+ return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
+ }
+ return &oauth2.Token{
+ AccessToken: res.AccessToken,
+ TokenType: res.TokenType,
+ Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
+ }, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/jwt.go b/vendor/golang.org/x/oauth2/google/jwt.go
new file mode 100644
index 0000000..b0fdb3a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/jwt.go
@@ -0,0 +1,74 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "crypto/rsa"
+ "fmt"
+ "time"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+ "golang.org/x/oauth2/jws"
+)
+
+// JWTAccessTokenSourceFromJSON uses a Google Developers service account JSON
+// key file to read the credentials that authorize and authenticate the
+// requests, and returns a TokenSource that does not use any OAuth2 flow but
+// instead creates a JWT and sends that as the access token.
+// The audience is typically a URL that specifies the scope of the credentials.
+//
+// Note that this is not a standard OAuth flow, but rather an
+// optimization supported by a few Google services.
+// Unless you know otherwise, you should use JWTConfigFromJSON instead.
+func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) {
+ cfg, err := JWTConfigFromJSON(jsonKey)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not parse JSON key: %v", err)
+ }
+ pk, err := internal.ParseKey(cfg.PrivateKey)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not parse key: %v", err)
+ }
+ ts := &jwtAccessTokenSource{
+ email: cfg.Email,
+ audience: audience,
+ pk: pk,
+ pkID: cfg.PrivateKeyID,
+ }
+ tok, err := ts.Token()
+ if err != nil {
+ return nil, err
+ }
+ return oauth2.ReuseTokenSource(tok, ts), nil
+}
+
+type jwtAccessTokenSource struct {
+ email, audience string
+ pk *rsa.PrivateKey
+ pkID string
+}
+
+func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) {
+ iat := time.Now()
+ exp := iat.Add(time.Hour)
+ cs := &jws.ClaimSet{
+ Iss: ts.email,
+ Sub: ts.email,
+ Aud: ts.audience,
+ Iat: iat.Unix(),
+ Exp: exp.Unix(),
+ }
+ hdr := &jws.Header{
+ Algorithm: "RS256",
+ Typ: "JWT",
+ KeyID: string(ts.pkID),
+ }
+ msg, err := jws.Encode(hdr, cs, ts.pk)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not encode JWT: %v", err)
+ }
+ return &oauth2.Token{AccessToken: msg, TokenType: "Bearer", Expiry: exp}, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/sdk.go b/vendor/golang.org/x/oauth2/google/sdk.go
new file mode 100644
index 0000000..bdc1808
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/sdk.go
@@ -0,0 +1,172 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "os"
+ "os/user"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+)
+
+type sdkCredentials struct {
+ Data []struct {
+ Credential struct {
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+ AccessToken string `json:"access_token"`
+ RefreshToken string `json:"refresh_token"`
+ TokenExpiry *time.Time `json:"token_expiry"`
+ } `json:"credential"`
+ Key struct {
+ Account string `json:"account"`
+ Scope string `json:"scope"`
+ } `json:"key"`
+ }
+}
+
+// An SDKConfig provides access to tokens from an account already
+// authorized via the Google Cloud SDK.
+type SDKConfig struct {
+ conf oauth2.Config
+ initialToken *oauth2.Token
+}
+
+// NewSDKConfig creates an SDKConfig for the given Google Cloud SDK
+// account. If account is empty, the account currently active in
+// Google Cloud SDK properties is used.
+// Google Cloud SDK credentials must be created by running `gcloud auth`
+// before using this function.
+// The Google Cloud SDK is available at https://cloud.google.com/sdk/.
+func NewSDKConfig(account string) (*SDKConfig, error) {
+ configPath, err := sdkConfigPath()
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: error getting SDK config path: %v", err)
+ }
+ credentialsPath := filepath.Join(configPath, "credentials")
+ f, err := os.Open(credentialsPath)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to load SDK credentials: %v", err)
+ }
+ defer f.Close()
+
+ var c sdkCredentials
+ if err := json.NewDecoder(f).Decode(&c); err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to decode SDK credentials from %q: %v", credentialsPath, err)
+ }
+ if len(c.Data) == 0 {
+ return nil, fmt.Errorf("oauth2/google: no credentials found in %q, run `gcloud auth login` to create one", credentialsPath)
+ }
+ if account == "" {
+ propertiesPath := filepath.Join(configPath, "properties")
+ f, err := os.Open(propertiesPath)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to load SDK properties: %v", err)
+ }
+ defer f.Close()
+ ini, err := internal.ParseINI(f)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to parse SDK properties %q: %v", propertiesPath, err)
+ }
+ core, ok := ini["core"]
+ if !ok {
+ return nil, fmt.Errorf("oauth2/google: failed to find [core] section in %v", ini)
+ }
+ active, ok := core["account"]
+ if !ok {
+ return nil, fmt.Errorf("oauth2/google: failed to find %q attribute in %v", "account", core)
+ }
+ account = active
+ }
+
+ for _, d := range c.Data {
+ if account == "" || d.Key.Account == account {
+ if d.Credential.AccessToken == "" && d.Credential.RefreshToken == "" {
+ return nil, fmt.Errorf("oauth2/google: no token available for account %q", account)
+ }
+ var expiry time.Time
+ if d.Credential.TokenExpiry != nil {
+ expiry = *d.Credential.TokenExpiry
+ }
+ return &SDKConfig{
+ conf: oauth2.Config{
+ ClientID: d.Credential.ClientID,
+ ClientSecret: d.Credential.ClientSecret,
+ Scopes: strings.Split(d.Key.Scope, " "),
+ Endpoint: Endpoint,
+ RedirectURL: "oob",
+ },
+ initialToken: &oauth2.Token{
+ AccessToken: d.Credential.AccessToken,
+ RefreshToken: d.Credential.RefreshToken,
+ Expiry: expiry,
+ },
+ }, nil
+ }
+ }
+ return nil, fmt.Errorf("oauth2/google: no such credentials for account %q", account)
+}
+
+// Client returns an HTTP client using Google Cloud SDK credentials to
+// authorize requests. The token will auto-refresh as necessary. The
+// underlying http.RoundTripper will be obtained using the provided
+// context. The returned client and its Transport should not be
+// modified.
+func (c *SDKConfig) Client(ctx context.Context) *http.Client {
+ return &http.Client{
+ Transport: &oauth2.Transport{
+ Source: c.TokenSource(ctx),
+ },
+ }
+}
+
+// TokenSource returns an oauth2.TokenSource that retrieve tokens from
+// Google Cloud SDK credentials using the provided context.
+// It will returns the current access token stored in the credentials,
+// and refresh it when it expires, but it won't update the credentials
+// with the new access token.
+func (c *SDKConfig) TokenSource(ctx context.Context) oauth2.TokenSource {
+ return c.conf.TokenSource(ctx, c.initialToken)
+}
+
+// Scopes are the OAuth 2.0 scopes the current account is authorized for.
+func (c *SDKConfig) Scopes() []string {
+ return c.conf.Scopes
+}
+
+// sdkConfigPath tries to guess where the gcloud config is located.
+// It can be overridden during tests.
+var sdkConfigPath = func() (string, error) {
+ if runtime.GOOS == "windows" {
+ return filepath.Join(os.Getenv("APPDATA"), "gcloud"), nil
+ }
+ homeDir := guessUnixHomeDir()
+ if homeDir == "" {
+ return "", errors.New("unable to get current user home directory: os/user lookup failed; $HOME is empty")
+ }
+ return filepath.Join(homeDir, ".config", "gcloud"), nil
+}
+
+func guessUnixHomeDir() string {
+ // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
+ if v := os.Getenv("HOME"); v != "" {
+ return v
+ }
+ // Else, fall back to user.Current:
+ if u, err := user.Current(); err == nil {
+ return u.HomeDir
+ }
+ return ""
+}
diff --git a/vendor/golang.org/x/oauth2/heroku/heroku.go b/vendor/golang.org/x/oauth2/heroku/heroku.go
new file mode 100644
index 0000000..5b4fdb8
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/heroku/heroku.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package heroku provides constants for using OAuth2 to access Heroku.
+package heroku // import "golang.org/x/oauth2/heroku"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Heroku's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://id.heroku.com/oauth/authorize",
+ TokenURL: "https://id.heroku.com/oauth/token",
+}
diff --git a/vendor/golang.org/x/oauth2/hipchat/hipchat.go b/vendor/golang.org/x/oauth2/hipchat/hipchat.go
new file mode 100644
index 0000000..594fe07
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/hipchat/hipchat.go
@@ -0,0 +1,60 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package hipchat provides constants for using OAuth2 to access HipChat.
+package hipchat // import "golang.org/x/oauth2/hipchat"
+
+import (
+ "encoding/json"
+ "errors"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/clientcredentials"
+)
+
+// Endpoint is HipChat's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.hipchat.com/users/authorize",
+ TokenURL: "https://api.hipchat.com/v2/oauth/token",
+}
+
+// ServerEndpoint returns a new oauth2.Endpoint for a HipChat Server instance
+// running on the given domain or host.
+func ServerEndpoint(host string) oauth2.Endpoint {
+ return oauth2.Endpoint{
+ AuthURL: "https://" + host + "/users/authorize",
+ TokenURL: "https://" + host + "/v2/oauth/token",
+ }
+}
+
+// ClientCredentialsConfigFromCaps generates a Config from a HipChat API
+// capabilities descriptor. It does not verify the scopes against the
+// capabilities document at this time.
+//
+// For more information see: https://www.hipchat.com/docs/apiv2/method/get_capabilities
+func ClientCredentialsConfigFromCaps(capsJSON []byte, clientID, clientSecret string, scopes ...string) (*clientcredentials.Config, error) {
+ var caps struct {
+ Caps struct {
+ Endpoint struct {
+ TokenURL string `json:"tokenUrl"`
+ } `json:"oauth2Provider"`
+ } `json:"capabilities"`
+ }
+
+ if err := json.Unmarshal(capsJSON, &caps); err != nil {
+ return nil, err
+ }
+
+ // Verify required fields.
+ if caps.Caps.Endpoint.TokenURL == "" {
+ return nil, errors.New("oauth2/hipchat: missing OAuth2 token URL in the capabilities descriptor JSON")
+ }
+
+ return &clientcredentials.Config{
+ ClientID: clientID,
+ ClientSecret: clientSecret,
+ Scopes: scopes,
+ TokenURL: caps.Caps.Endpoint.TokenURL,
+ }, nil
+}
diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go
new file mode 100644
index 0000000..03265e8
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/doc.go
@@ -0,0 +1,6 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package internal contains support packages for oauth2 package.
+package internal
diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go
new file mode 100644
index 0000000..6978192
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/oauth2.go
@@ -0,0 +1,75 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "bufio"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// ParseKey converts the binary contents of a private key file
+// to an *rsa.PrivateKey. It detects whether the private key is in a
+// PEM container or not. If so, it extracts the the private key
+// from PEM container before conversion. It only supports PEM
+// containers with no passphrase.
+func ParseKey(key []byte) (*rsa.PrivateKey, error) {
+ block, _ := pem.Decode(key)
+ if block != nil {
+ key = block.Bytes
+ }
+ parsedKey, err := x509.ParsePKCS8PrivateKey(key)
+ if err != nil {
+ parsedKey, err = x509.ParsePKCS1PrivateKey(key)
+ if err != nil {
+ return nil, fmt.Errorf("private key should be a PEM or plain PKSC1 or PKCS8; parse error: %v", err)
+ }
+ }
+ parsed, ok := parsedKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("private key is invalid")
+ }
+ return parsed, nil
+}
+
+func ParseINI(ini io.Reader) (map[string]map[string]string, error) {
+ result := map[string]map[string]string{
+ "": {}, // root section
+ }
+ scanner := bufio.NewScanner(ini)
+ currentSection := ""
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+ if strings.HasPrefix(line, ";") {
+ // comment.
+ continue
+ }
+ if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
+ currentSection = strings.TrimSpace(line[1 : len(line)-1])
+ result[currentSection] = map[string]string{}
+ continue
+ }
+ parts := strings.SplitN(line, "=", 2)
+ if len(parts) == 2 && parts[0] != "" {
+ result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("error scanning ini: %v", err)
+ }
+ return result, nil
+}
+
+func CondVal(v string) []string {
+ if v == "" {
+ return nil
+ }
+ return []string{v}
+}
diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go
new file mode 100644
index 0000000..600dbe6
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/token.go
@@ -0,0 +1,251 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "mime"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/net/context/ctxhttp"
+)
+
+// Token represents the credentials used to authorize
+// the requests to access protected resources on the OAuth 2.0
+// provider's backend.
+//
+// This type is a mirror of oauth2.Token and exists to break
+// an otherwise-circular dependency. Other internal packages
+// should convert this Token into an oauth2.Token before use.
+type Token struct {
+ // AccessToken is the token that authorizes and authenticates
+ // the requests.
+ AccessToken string
+
+ // TokenType is the type of token.
+ // The Type method returns either this or "Bearer", the default.
+ TokenType string
+
+ // RefreshToken is a token that's used by the application
+ // (as opposed to the user) to refresh the access token
+ // if it expires.
+ RefreshToken string
+
+ // Expiry is the optional expiration time of the access token.
+ //
+ // If zero, TokenSource implementations will reuse the same
+ // token forever and RefreshToken or equivalent
+ // mechanisms for that TokenSource will not be used.
+ Expiry time.Time
+
+ // Raw optionally contains extra metadata from the server
+ // when updating a token.
+ Raw interface{}
+}
+
+// tokenJSON is the struct representing the HTTP response from OAuth2
+// providers returning a token in JSON form.
+type tokenJSON struct {
+ AccessToken string `json:"access_token"`
+ TokenType string `json:"token_type"`
+ RefreshToken string `json:"refresh_token"`
+ ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
+ Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in
+}
+
+func (e *tokenJSON) expiry() (t time.Time) {
+ if v := e.ExpiresIn; v != 0 {
+ return time.Now().Add(time.Duration(v) * time.Second)
+ }
+ if v := e.Expires; v != 0 {
+ return time.Now().Add(time.Duration(v) * time.Second)
+ }
+ return
+}
+
+type expirationTime int32
+
+func (e *expirationTime) UnmarshalJSON(b []byte) error {
+ var n json.Number
+ err := json.Unmarshal(b, &n)
+ if err != nil {
+ return err
+ }
+ i, err := n.Int64()
+ if err != nil {
+ return err
+ }
+ *e = expirationTime(i)
+ return nil
+}
+
+var brokenAuthHeaderProviders = []string{
+ "https://accounts.google.com/",
+ "https://api.codeswholesale.com/oauth/token",
+ "https://api.dropbox.com/",
+ "https://api.dropboxapi.com/",
+ "https://api.instagram.com/",
+ "https://api.netatmo.net/",
+ "https://api.odnoklassniki.ru/",
+ "https://api.pushbullet.com/",
+ "https://api.soundcloud.com/",
+ "https://api.twitch.tv/",
+ "https://app.box.com/",
+ "https://connect.stripe.com/",
+ "https://graph.facebook.com", // see https://github.com/golang/oauth2/issues/214
+ "https://login.microsoftonline.com/",
+ "https://login.salesforce.com/",
+ "https://login.windows.net",
+ "https://login.live.com/",
+ "https://oauth.sandbox.trainingpeaks.com/",
+ "https://oauth.trainingpeaks.com/",
+ "https://oauth.vk.com/",
+ "https://openapi.baidu.com/",
+ "https://slack.com/",
+ "https://test-sandbox.auth.corp.google.com",
+ "https://test.salesforce.com/",
+ "https://user.gini.net/",
+ "https://www.douban.com/",
+ "https://www.googleapis.com/",
+ "https://www.linkedin.com/",
+ "https://www.strava.com/oauth/",
+ "https://www.wunderlist.com/oauth/",
+ "https://api.patreon.com/",
+ "https://sandbox.codeswholesale.com/oauth/token",
+ "https://api.sipgate.com/v1/authorization/oauth",
+}
+
+// brokenAuthHeaderDomains lists broken providers that issue dynamic endpoints.
+var brokenAuthHeaderDomains = []string{
+ ".force.com",
+ ".myshopify.com",
+ ".okta.com",
+ ".oktapreview.com",
+}
+
+func RegisterBrokenAuthHeaderProvider(tokenURL string) {
+ brokenAuthHeaderProviders = append(brokenAuthHeaderProviders, tokenURL)
+}
+
+// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL
+// implements the OAuth2 spec correctly
+// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
+// In summary:
+// - Reddit only accepts client secret in the Authorization header
+// - Dropbox accepts either it in URL param or Auth header, but not both.
+// - Google only accepts URL param (not spec compliant?), not Auth header
+// - Stripe only accepts client secret in Auth header with Bearer method, not Basic
+func providerAuthHeaderWorks(tokenURL string) bool {
+ for _, s := range brokenAuthHeaderProviders {
+ if strings.HasPrefix(tokenURL, s) {
+ // Some sites fail to implement the OAuth2 spec fully.
+ return false
+ }
+ }
+
+ if u, err := url.Parse(tokenURL); err == nil {
+ for _, s := range brokenAuthHeaderDomains {
+ if strings.HasSuffix(u.Host, s) {
+ return false
+ }
+ }
+ }
+
+ // Assume the provider implements the spec properly
+ // otherwise. We can add more exceptions as they're
+ // discovered. We will _not_ be adding configurable hooks
+ // to this package to let users select server bugs.
+ return true
+}
+
+func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values) (*Token, error) {
+ hc, err := ContextClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ bustedAuth := !providerAuthHeaderWorks(tokenURL)
+ if bustedAuth {
+ if clientID != "" {
+ v.Set("client_id", clientID)
+ }
+ if clientSecret != "" {
+ v.Set("client_secret", clientSecret)
+ }
+ }
+ req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode()))
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ if !bustedAuth {
+ req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret))
+ }
+ r, err := ctxhttp.Do(ctx, hc, req)
+ if err != nil {
+ return nil, err
+ }
+ defer r.Body.Close()
+ body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20))
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ if code := r.StatusCode; code < 200 || code > 299 {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", r.Status, body)
+ }
+
+ var token *Token
+ content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
+ switch content {
+ case "application/x-www-form-urlencoded", "text/plain":
+ vals, err := url.ParseQuery(string(body))
+ if err != nil {
+ return nil, err
+ }
+ token = &Token{
+ AccessToken: vals.Get("access_token"),
+ TokenType: vals.Get("token_type"),
+ RefreshToken: vals.Get("refresh_token"),
+ Raw: vals,
+ }
+ e := vals.Get("expires_in")
+ if e == "" {
+ // TODO(jbd): Facebook's OAuth2 implementation is broken and
+ // returns expires_in field in expires. Remove the fallback to expires,
+ // when Facebook fixes their implementation.
+ e = vals.Get("expires")
+ }
+ expires, _ := strconv.Atoi(e)
+ if expires != 0 {
+ token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
+ }
+ default:
+ var tj tokenJSON
+ if err = json.Unmarshal(body, &tj); err != nil {
+ return nil, err
+ }
+ token = &Token{
+ AccessToken: tj.AccessToken,
+ TokenType: tj.TokenType,
+ RefreshToken: tj.RefreshToken,
+ Expiry: tj.expiry(),
+ Raw: make(map[string]interface{}),
+ }
+ json.Unmarshal(body, &token.Raw) // no error checks for optional fields
+ }
+ // Don't overwrite `RefreshToken` with an empty value
+ // if this was a token refreshing request.
+ if token.RefreshToken == "" {
+ token.RefreshToken = v.Get("refresh_token")
+ }
+ return token, nil
+}
diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go
new file mode 100644
index 0000000..783bd98
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/transport.go
@@ -0,0 +1,68 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "net/http"
+
+ "golang.org/x/net/context"
+)
+
+// HTTPClient is the context key to use with golang.org/x/net/context's
+// WithValue function to associate an *http.Client value with a context.
+var HTTPClient ContextKey
+
+// ContextKey is just an empty struct. It exists so HTTPClient can be
+// an immutable public variable with a unique type. It's immutable
+// because nobody else can create a ContextKey, being unexported.
+type ContextKey struct{}
+
+// ContextClientFunc is a func which tries to return an *http.Client
+// given a Context value. If it returns an error, the search stops
+// with that error. If it returns (nil, nil), the search continues
+// down the list of registered funcs.
+type ContextClientFunc func(context.Context) (*http.Client, error)
+
+var contextClientFuncs []ContextClientFunc
+
+func RegisterContextClientFunc(fn ContextClientFunc) {
+ contextClientFuncs = append(contextClientFuncs, fn)
+}
+
+func ContextClient(ctx context.Context) (*http.Client, error) {
+ if ctx != nil {
+ if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok {
+ return hc, nil
+ }
+ }
+ for _, fn := range contextClientFuncs {
+ c, err := fn(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if c != nil {
+ return c, nil
+ }
+ }
+ return http.DefaultClient, nil
+}
+
+func ContextTransport(ctx context.Context) http.RoundTripper {
+ hc, err := ContextClient(ctx)
+ // This is a rare error case (somebody using nil on App Engine).
+ if err != nil {
+ return ErrorTransport{err}
+ }
+ return hc.Transport
+}
+
+// ErrorTransport returns the specified error on RoundTrip.
+// This RoundTripper should be used in rare error cases where
+// error handling can be postponed to response handling time.
+type ErrorTransport struct{ Err error }
+
+func (t ErrorTransport) RoundTrip(*http.Request) (*http.Response, error) {
+ return nil, t.Err
+}
diff --git a/vendor/golang.org/x/oauth2/jws/jws.go b/vendor/golang.org/x/oauth2/jws/jws.go
new file mode 100644
index 0000000..683d2d2
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jws/jws.go
@@ -0,0 +1,182 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package jws provides a partial implementation
+// of JSON Web Signature encoding and decoding.
+// It exists to support the golang.org/x/oauth2 package.
+//
+// See RFC 7515.
+//
+// Deprecated: this package is not intended for public use and might be
+// removed in the future. It exists for internal use only.
+// Please switch to another JWS package or copy this package into your own
+// source tree.
+package jws // import "golang.org/x/oauth2/jws"
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+)
+
+// ClaimSet contains information about the JWT signature including the
+// permissions being requested (scopes), the target of the token, the issuer,
+// the time the token was issued, and the lifetime of the token.
+type ClaimSet struct {
+ Iss string `json:"iss"` // email address of the client_id of the application making the access token request
+ Scope string `json:"scope,omitempty"` // space-delimited list of the permissions the application requests
+ Aud string `json:"aud"` // descriptor of the intended target of the assertion (Optional).
+ Exp int64 `json:"exp"` // the expiration time of the assertion (seconds since Unix epoch)
+ Iat int64 `json:"iat"` // the time the assertion was issued (seconds since Unix epoch)
+ Typ string `json:"typ,omitempty"` // token type (Optional).
+
+ // Email for which the application is requesting delegated access (Optional).
+ Sub string `json:"sub,omitempty"`
+
+ // The old name of Sub. Client keeps setting Prn to be
+ // complaint with legacy OAuth 2.0 providers. (Optional)
+ Prn string `json:"prn,omitempty"`
+
+ // See http://tools.ietf.org/html/draft-jones-json-web-token-10#section-4.3
+ // This array is marshalled using custom code (see (c *ClaimSet) encode()).
+ PrivateClaims map[string]interface{} `json:"-"`
+}
+
+func (c *ClaimSet) encode() (string, error) {
+ // Reverting time back for machines whose time is not perfectly in sync.
+ // If client machine's time is in the future according
+ // to Google servers, an access token will not be issued.
+ now := time.Now().Add(-10 * time.Second)
+ if c.Iat == 0 {
+ c.Iat = now.Unix()
+ }
+ if c.Exp == 0 {
+ c.Exp = now.Add(time.Hour).Unix()
+ }
+ if c.Exp < c.Iat {
+ return "", fmt.Errorf("jws: invalid Exp = %v; must be later than Iat = %v", c.Exp, c.Iat)
+ }
+
+ b, err := json.Marshal(c)
+ if err != nil {
+ return "", err
+ }
+
+ if len(c.PrivateClaims) == 0 {
+ return base64.RawURLEncoding.EncodeToString(b), nil
+ }
+
+ // Marshal private claim set and then append it to b.
+ prv, err := json.Marshal(c.PrivateClaims)
+ if err != nil {
+ return "", fmt.Errorf("jws: invalid map of private claims %v", c.PrivateClaims)
+ }
+
+ // Concatenate public and private claim JSON objects.
+ if !bytes.HasSuffix(b, []byte{'}'}) {
+ return "", fmt.Errorf("jws: invalid JSON %s", b)
+ }
+ if !bytes.HasPrefix(prv, []byte{'{'}) {
+ return "", fmt.Errorf("jws: invalid JSON %s", prv)
+ }
+ b[len(b)-1] = ',' // Replace closing curly brace with a comma.
+ b = append(b, prv[1:]...) // Append private claims.
+ return base64.RawURLEncoding.EncodeToString(b), nil
+}
+
+// Header represents the header for the signed JWS payloads.
+type Header struct {
+ // The algorithm used for signature.
+ Algorithm string `json:"alg"`
+
+ // Represents the token type.
+ Typ string `json:"typ"`
+
+ // The optional hint of which key is being used.
+ KeyID string `json:"kid,omitempty"`
+}
+
+func (h *Header) encode() (string, error) {
+ b, err := json.Marshal(h)
+ if err != nil {
+ return "", err
+ }
+ return base64.RawURLEncoding.EncodeToString(b), nil
+}
+
+// Decode decodes a claim set from a JWS payload.
+func Decode(payload string) (*ClaimSet, error) {
+ // decode returned id token to get expiry
+ s := strings.Split(payload, ".")
+ if len(s) < 2 {
+ // TODO(jbd): Provide more context about the error.
+ return nil, errors.New("jws: invalid token received")
+ }
+ decoded, err := base64.RawURLEncoding.DecodeString(s[1])
+ if err != nil {
+ return nil, err
+ }
+ c := &ClaimSet{}
+ err = json.NewDecoder(bytes.NewBuffer(decoded)).Decode(c)
+ return c, err
+}
+
+// Signer returns a signature for the given data.
+type Signer func(data []byte) (sig []byte, err error)
+
+// EncodeWithSigner encodes a header and claim set with the provided signer.
+func EncodeWithSigner(header *Header, c *ClaimSet, sg Signer) (string, error) {
+ head, err := header.encode()
+ if err != nil {
+ return "", err
+ }
+ cs, err := c.encode()
+ if err != nil {
+ return "", err
+ }
+ ss := fmt.Sprintf("%s.%s", head, cs)
+ sig, err := sg([]byte(ss))
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%s.%s", ss, base64.RawURLEncoding.EncodeToString(sig)), nil
+}
+
+// Encode encodes a signed JWS with provided header and claim set.
+// This invokes EncodeWithSigner using crypto/rsa.SignPKCS1v15 with the given RSA private key.
+func Encode(header *Header, c *ClaimSet, key *rsa.PrivateKey) (string, error) {
+ sg := func(data []byte) (sig []byte, err error) {
+ h := sha256.New()
+ h.Write(data)
+ return rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil))
+ }
+ return EncodeWithSigner(header, c, sg)
+}
+
+// Verify tests whether the provided JWT token's signature was produced by the private key
+// associated with the supplied public key.
+func Verify(token string, key *rsa.PublicKey) error {
+ parts := strings.Split(token, ".")
+ if len(parts) != 3 {
+ return errors.New("jws: invalid token received, token must have 3 parts")
+ }
+
+ signedContent := parts[0] + "." + parts[1]
+ signatureString, err := base64.RawURLEncoding.DecodeString(parts[2])
+ if err != nil {
+ return err
+ }
+
+ h := sha256.New()
+ h.Write([]byte(signedContent))
+ return rsa.VerifyPKCS1v15(key, crypto.SHA256, h.Sum(nil), []byte(signatureString))
+}
diff --git a/vendor/golang.org/x/oauth2/jwt/jwt.go b/vendor/golang.org/x/oauth2/jwt/jwt.go
new file mode 100644
index 0000000..e016db4
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jwt/jwt.go
@@ -0,0 +1,159 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package jwt implements the OAuth 2.0 JSON Web Token flow, commonly
+// known as "two-legged OAuth 2.0".
+//
+// See: https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12
+package jwt
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+ "golang.org/x/oauth2/jws"
+)
+
+var (
+ defaultGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"
+ defaultHeader = &jws.Header{Algorithm: "RS256", Typ: "JWT"}
+)
+
+// Config is the configuration for using JWT to fetch tokens,
+// commonly known as "two-legged OAuth 2.0".
+type Config struct {
+ // Email is the OAuth client identifier used when communicating with
+ // the configured OAuth provider.
+ Email string
+
+ // PrivateKey contains the contents of an RSA private key or the
+ // contents of a PEM file that contains a private key. The provided
+ // private key is used to sign JWT payloads.
+ // PEM containers with a passphrase are not supported.
+ // Use the following command to convert a PKCS 12 file into a PEM.
+ //
+ // $ openssl pkcs12 -in key.p12 -out key.pem -nodes
+ //
+ PrivateKey []byte
+
+ // PrivateKeyID contains an optional hint indicating which key is being
+ // used.
+ PrivateKeyID string
+
+ // Subject is the optional user to impersonate.
+ Subject string
+
+ // Scopes optionally specifies a list of requested permission scopes.
+ Scopes []string
+
+ // TokenURL is the endpoint required to complete the 2-legged JWT flow.
+ TokenURL string
+
+ // Expires optionally specifies how long the token is valid for.
+ Expires time.Duration
+}
+
+// TokenSource returns a JWT TokenSource using the configuration
+// in c and the HTTP client from the provided context.
+func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
+ return oauth2.ReuseTokenSource(nil, jwtSource{ctx, c})
+}
+
+// Client returns an HTTP client wrapping the context's
+// HTTP transport and adding Authorization headers with tokens
+// obtained from c.
+//
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context) *http.Client {
+ return oauth2.NewClient(ctx, c.TokenSource(ctx))
+}
+
+// jwtSource is a source that always does a signed JWT request for a token.
+// It should typically be wrapped with a reuseTokenSource.
+type jwtSource struct {
+ ctx context.Context
+ conf *Config
+}
+
+func (js jwtSource) Token() (*oauth2.Token, error) {
+ pk, err := internal.ParseKey(js.conf.PrivateKey)
+ if err != nil {
+ return nil, err
+ }
+ hc := oauth2.NewClient(js.ctx, nil)
+ claimSet := &jws.ClaimSet{
+ Iss: js.conf.Email,
+ Scope: strings.Join(js.conf.Scopes, " "),
+ Aud: js.conf.TokenURL,
+ }
+ if subject := js.conf.Subject; subject != "" {
+ claimSet.Sub = subject
+ // prn is the old name of sub. Keep setting it
+ // to be compatible with legacy OAuth 2.0 providers.
+ claimSet.Prn = subject
+ }
+ if t := js.conf.Expires; t > 0 {
+ claimSet.Exp = time.Now().Add(t).Unix()
+ }
+ h := *defaultHeader
+ h.KeyID = js.conf.PrivateKeyID
+ payload, err := jws.Encode(&h, claimSet, pk)
+ if err != nil {
+ return nil, err
+ }
+ v := url.Values{}
+ v.Set("grant_type", defaultGrantType)
+ v.Set("assertion", payload)
+ resp, err := hc.PostForm(js.conf.TokenURL, v)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ if c := resp.StatusCode; c < 200 || c > 299 {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", resp.Status, body)
+ }
+ // tokenRes is the JSON response body.
+ var tokenRes struct {
+ AccessToken string `json:"access_token"`
+ TokenType string `json:"token_type"`
+ IDToken string `json:"id_token"`
+ ExpiresIn int64 `json:"expires_in"` // relative seconds from now
+ }
+ if err := json.Unmarshal(body, &tokenRes); err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ token := &oauth2.Token{
+ AccessToken: tokenRes.AccessToken,
+ TokenType: tokenRes.TokenType,
+ }
+ raw := make(map[string]interface{})
+ json.Unmarshal(body, &raw) // no error checks for optional fields
+ token = token.WithExtra(raw)
+
+ if secs := tokenRes.ExpiresIn; secs > 0 {
+ token.Expiry = time.Now().Add(time.Duration(secs) * time.Second)
+ }
+ if v := tokenRes.IDToken; v != "" {
+ // decode returned id token to get expiry
+ claimSet, err := jws.Decode(v)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: error decoding JWT token: %v", err)
+ }
+ token.Expiry = time.Unix(claimSet.Exp, 0)
+ }
+ return token, nil
+}
diff --git a/vendor/golang.org/x/oauth2/linkedin/linkedin.go b/vendor/golang.org/x/oauth2/linkedin/linkedin.go
new file mode 100644
index 0000000..b619f93
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/linkedin/linkedin.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package linkedin provides constants for using OAuth2 to access LinkedIn.
+package linkedin // import "golang.org/x/oauth2/linkedin"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is LinkedIn's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.linkedin.com/uas/oauth2/authorization",
+ TokenURL: "https://www.linkedin.com/uas/oauth2/accessToken",
+}
diff --git a/vendor/golang.org/x/oauth2/mediamath/mediamath.go b/vendor/golang.org/x/oauth2/mediamath/mediamath.go
new file mode 100644
index 0000000..3ebce5d
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/mediamath/mediamath.go
@@ -0,0 +1,22 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package mediamath provides constants for using OAuth2 to access MediaMath.
+package mediamath // import "golang.org/x/oauth2/mediamath"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is MediaMath's OAuth 2.0 endpoint for production.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://api.mediamath.com/oauth2/v1.0/authorize",
+ TokenURL: "https://api.mediamath.com/oauth2/v1.0/token",
+}
+
+// SandboxEndpoint is MediaMath's OAuth 2.0 endpoint for sandbox.
+var SandboxEndpoint = oauth2.Endpoint{
+ AuthURL: "https://t1sandbox.mediamath.com/oauth2/v1.0/authorize",
+ TokenURL: "https://t1sandbox.mediamath.com/oauth2/v1.0/token",
+}
diff --git a/vendor/golang.org/x/oauth2/microsoft/microsoft.go b/vendor/golang.org/x/oauth2/microsoft/microsoft.go
new file mode 100644
index 0000000..f21b398
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/microsoft/microsoft.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package microsoft provides constants for using OAuth2 to access Windows Live ID.
+package microsoft // import "golang.org/x/oauth2/microsoft"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// LiveConnectEndpoint is Windows's Live ID OAuth 2.0 endpoint.
+var LiveConnectEndpoint = oauth2.Endpoint{
+ AuthURL: "https://login.live.com/oauth20_authorize.srf",
+ TokenURL: "https://login.live.com/oauth20_token.srf",
+}
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go
new file mode 100644
index 0000000..4bafe87
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/oauth2.go
@@ -0,0 +1,344 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package oauth2 provides support for making
+// OAuth2 authorized and authenticated HTTP requests.
+// It can additionally grant authorization with Bearer JWT.
+package oauth2 // import "golang.org/x/oauth2"
+
+import (
+ "bytes"
+ "errors"
+ "net/http"
+ "net/url"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2/internal"
+)
+
+// NoContext is the default context you should supply if not using
+// your own context.Context (see https://golang.org/x/net/context).
+//
+// Deprecated: Use context.Background() or context.TODO() instead.
+var NoContext = context.TODO()
+
+// RegisterBrokenAuthHeaderProvider registers an OAuth2 server
+// identified by the tokenURL prefix as an OAuth2 implementation
+// which doesn't support the HTTP Basic authentication
+// scheme to authenticate with the authorization server.
+// Once a server is registered, credentials (client_id and client_secret)
+// will be passed as query parameters rather than being present
+// in the Authorization header.
+// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
+func RegisterBrokenAuthHeaderProvider(tokenURL string) {
+ internal.RegisterBrokenAuthHeaderProvider(tokenURL)
+}
+
+// Config describes a typical 3-legged OAuth2 flow, with both the
+// client application information and the server's endpoint URLs.
+// For the client credentials 2-legged OAuth2 flow, see the clientcredentials
+// package (https://golang.org/x/oauth2/clientcredentials).
+type Config struct {
+ // ClientID is the application's ID.
+ ClientID string
+
+ // ClientSecret is the application's secret.
+ ClientSecret string
+
+ // Endpoint contains the resource server's token endpoint
+ // URLs. These are constants specific to each server and are
+ // often available via site-specific packages, such as
+ // google.Endpoint or github.Endpoint.
+ Endpoint Endpoint
+
+ // RedirectURL is the URL to redirect users going through
+ // the OAuth flow, after the resource owner's URLs.
+ RedirectURL string
+
+ // Scope specifies optional requested permissions.
+ Scopes []string
+}
+
+// A TokenSource is anything that can return a token.
+type TokenSource interface {
+ // Token returns a token or an error.
+ // Token must be safe for concurrent use by multiple goroutines.
+ // The returned Token must not be modified.
+ Token() (*Token, error)
+}
+
+// Endpoint contains the OAuth 2.0 provider's authorization and token
+// endpoint URLs.
+type Endpoint struct {
+ AuthURL string
+ TokenURL string
+}
+
+var (
+ // AccessTypeOnline and AccessTypeOffline are options passed
+ // to the Options.AuthCodeURL method. They modify the
+ // "access_type" field that gets sent in the URL returned by
+ // AuthCodeURL.
+ //
+ // Online is the default if neither is specified. If your
+ // application needs to refresh access tokens when the user
+ // is not present at the browser, then use offline. This will
+ // result in your application obtaining a refresh token the
+ // first time your application exchanges an authorization
+ // code for a user.
+ AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online")
+ AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline")
+
+ // ApprovalForce forces the users to view the consent dialog
+ // and confirm the permissions request at the URL returned
+ // from AuthCodeURL, even if they've already done so.
+ ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force")
+)
+
+// An AuthCodeOption is passed to Config.AuthCodeURL.
+type AuthCodeOption interface {
+ setValue(url.Values)
+}
+
+type setParam struct{ k, v string }
+
+func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) }
+
+// SetAuthURLParam builds an AuthCodeOption which passes key/value parameters
+// to a provider's authorization endpoint.
+func SetAuthURLParam(key, value string) AuthCodeOption {
+ return setParam{key, value}
+}
+
+// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
+// that asks for permissions for the required scopes explicitly.
+//
+// State is a token to protect the user from CSRF attacks. You must
+// always provide a non-zero string and validate that it matches the
+// the state query parameter on your redirect callback.
+// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
+//
+// Opts may include AccessTypeOnline or AccessTypeOffline, as well
+// as ApprovalForce.
+func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
+ var buf bytes.Buffer
+ buf.WriteString(c.Endpoint.AuthURL)
+ v := url.Values{
+ "response_type": {"code"},
+ "client_id": {c.ClientID},
+ "redirect_uri": internal.CondVal(c.RedirectURL),
+ "scope": internal.CondVal(strings.Join(c.Scopes, " ")),
+ "state": internal.CondVal(state),
+ }
+ for _, opt := range opts {
+ opt.setValue(v)
+ }
+ if strings.Contains(c.Endpoint.AuthURL, "?") {
+ buf.WriteByte('&')
+ } else {
+ buf.WriteByte('?')
+ }
+ buf.WriteString(v.Encode())
+ return buf.String()
+}
+
+// PasswordCredentialsToken converts a resource owner username and password
+// pair into a token.
+//
+// Per the RFC, this grant type should only be used "when there is a high
+// degree of trust between the resource owner and the client (e.g., the client
+// is part of the device operating system or a highly privileged application),
+// and when other authorization grant types are not available."
+// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info.
+//
+// The HTTP client to use is derived from the context.
+// If nil, http.DefaultClient is used.
+func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) {
+ return retrieveToken(ctx, c, url.Values{
+ "grant_type": {"password"},
+ "username": {username},
+ "password": {password},
+ "scope": internal.CondVal(strings.Join(c.Scopes, " ")),
+ })
+}
+
+// Exchange converts an authorization code into a token.
+//
+// It is used after a resource provider redirects the user back
+// to the Redirect URI (the URL obtained from AuthCodeURL).
+//
+// The HTTP client to use is derived from the context.
+// If a client is not provided via the context, http.DefaultClient is used.
+//
+// The code will be in the *http.Request.FormValue("code"). Before
+// calling Exchange, be sure to validate FormValue("state").
+func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) {
+ return retrieveToken(ctx, c, url.Values{
+ "grant_type": {"authorization_code"},
+ "code": {code},
+ "redirect_uri": internal.CondVal(c.RedirectURL),
+ })
+}
+
+// Client returns an HTTP client using the provided token.
+// The token will auto-refresh as necessary. The underlying
+// HTTP transport will be obtained using the provided context.
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
+ return NewClient(ctx, c.TokenSource(ctx, t))
+}
+
+// TokenSource returns a TokenSource that returns t until t expires,
+// automatically refreshing it as necessary using the provided context.
+//
+// Most users will use Config.Client instead.
+func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
+ tkr := &tokenRefresher{
+ ctx: ctx,
+ conf: c,
+ }
+ if t != nil {
+ tkr.refreshToken = t.RefreshToken
+ }
+ return &reuseTokenSource{
+ t: t,
+ new: tkr,
+ }
+}
+
+// tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token"
+// HTTP requests to renew a token using a RefreshToken.
+type tokenRefresher struct {
+ ctx context.Context // used to get HTTP requests
+ conf *Config
+ refreshToken string
+}
+
+// WARNING: Token is not safe for concurrent access, as it
+// updates the tokenRefresher's refreshToken field.
+// Within this package, it is used by reuseTokenSource which
+// synchronizes calls to this method with its own mutex.
+func (tf *tokenRefresher) Token() (*Token, error) {
+ if tf.refreshToken == "" {
+ return nil, errors.New("oauth2: token expired and refresh token is not set")
+ }
+
+ tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{
+ "grant_type": {"refresh_token"},
+ "refresh_token": {tf.refreshToken},
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ if tf.refreshToken != tk.RefreshToken {
+ tf.refreshToken = tk.RefreshToken
+ }
+ return tk, err
+}
+
+// reuseTokenSource is a TokenSource that holds a single token in memory
+// and validates its expiry before each call to retrieve it with
+// Token. If it's expired, it will be auto-refreshed using the
+// new TokenSource.
+type reuseTokenSource struct {
+ new TokenSource // called when t is expired.
+
+ mu sync.Mutex // guards t
+ t *Token
+}
+
+// Token returns the current token if it's still valid, else will
+// refresh the current token (using r.Context for HTTP client
+// information) and return the new one.
+func (s *reuseTokenSource) Token() (*Token, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.t.Valid() {
+ return s.t, nil
+ }
+ t, err := s.new.Token()
+ if err != nil {
+ return nil, err
+ }
+ s.t = t
+ return t, nil
+}
+
+// StaticTokenSource returns a TokenSource that always returns the same token.
+// Because the provided token t is never refreshed, StaticTokenSource is only
+// useful for tokens that never expire.
+func StaticTokenSource(t *Token) TokenSource {
+ return staticTokenSource{t}
+}
+
+// staticTokenSource is a TokenSource that always returns the same Token.
+type staticTokenSource struct {
+ t *Token
+}
+
+func (s staticTokenSource) Token() (*Token, error) {
+ return s.t, nil
+}
+
+// HTTPClient is the context key to use with golang.org/x/net/context's
+// WithValue function to associate an *http.Client value with a context.
+var HTTPClient internal.ContextKey
+
+// NewClient creates an *http.Client from a Context and TokenSource.
+// The returned client is not valid beyond the lifetime of the context.
+//
+// Note that if a custom *http.Client is provided via the Context it
+// is used only for token acquisition and is not used to configure the
+// *http.Client returned from NewClient.
+//
+// As a special case, if src is nil, a non-OAuth2 client is returned
+// using the provided context. This exists to support related OAuth2
+// packages.
+func NewClient(ctx context.Context, src TokenSource) *http.Client {
+ if src == nil {
+ c, err := internal.ContextClient(ctx)
+ if err != nil {
+ return &http.Client{Transport: internal.ErrorTransport{Err: err}}
+ }
+ return c
+ }
+ return &http.Client{
+ Transport: &Transport{
+ Base: internal.ContextTransport(ctx),
+ Source: ReuseTokenSource(nil, src),
+ },
+ }
+}
+
+// ReuseTokenSource returns a TokenSource which repeatedly returns the
+// same token as long as it's valid, starting with t.
+// When its cached token is invalid, a new token is obtained from src.
+//
+// ReuseTokenSource is typically used to reuse tokens from a cache
+// (such as a file on disk) between runs of a program, rather than
+// obtaining new tokens unnecessarily.
+//
+// The initial token t may be nil, in which case the TokenSource is
+// wrapped in a caching version if it isn't one already. This also
+// means it's always safe to wrap ReuseTokenSource around any other
+// TokenSource without adverse effects.
+func ReuseTokenSource(t *Token, src TokenSource) TokenSource {
+ // Don't wrap a reuseTokenSource in itself. That would work,
+ // but cause an unnecessary number of mutex operations.
+ // Just build the equivalent one.
+ if rt, ok := src.(*reuseTokenSource); ok {
+ if t == nil {
+ // Just use it directly.
+ return rt
+ }
+ src = rt.new
+ }
+ return &reuseTokenSource{
+ t: t,
+ new: src,
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go b/vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go
new file mode 100644
index 0000000..c0d093c
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package odnoklassniki provides constants for using OAuth2 to access Odnoklassniki.
+package odnoklassniki // import "golang.org/x/oauth2/odnoklassniki"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Odnoklassniki's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.odnoklassniki.ru/oauth/authorize",
+ TokenURL: "https://api.odnoklassniki.ru/oauth/token.do",
+}
diff --git a/vendor/golang.org/x/oauth2/paypal/paypal.go b/vendor/golang.org/x/oauth2/paypal/paypal.go
new file mode 100644
index 0000000..2e713c5
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/paypal/paypal.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package paypal provides constants for using OAuth2 to access PayPal.
+package paypal // import "golang.org/x/oauth2/paypal"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is PayPal's OAuth 2.0 endpoint in live (production) environment.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize",
+ TokenURL: "https://api.paypal.com/v1/identity/openidconnect/tokenservice",
+}
+
+// SandboxEndpoint is PayPal's OAuth 2.0 endpoint in sandbox (testing) environment.
+var SandboxEndpoint = oauth2.Endpoint{
+ AuthURL: "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize",
+ TokenURL: "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice",
+}
diff --git a/vendor/golang.org/x/oauth2/slack/slack.go b/vendor/golang.org/x/oauth2/slack/slack.go
new file mode 100644
index 0000000..593d2f6
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/slack/slack.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package slack provides constants for using OAuth2 to access Slack.
+package slack // import "golang.org/x/oauth2/slack"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Slack's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://slack.com/oauth/authorize",
+ TokenURL: "https://slack.com/api/oauth.access",
+}
diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go
new file mode 100644
index 0000000..bdac1de
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/token.go
@@ -0,0 +1,158 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2/internal"
+)
+
+// expiryDelta determines how earlier a token should be considered
+// expired than its actual expiration time. It is used to avoid late
+// expirations due to client-server time mismatches.
+const expiryDelta = 10 * time.Second
+
+// Token represents the credentials used to authorize
+// the requests to access protected resources on the OAuth 2.0
+// provider's backend.
+//
+// Most users of this package should not access fields of Token
+// directly. They're exported mostly for use by related packages
+// implementing derivative OAuth2 flows.
+type Token struct {
+ // AccessToken is the token that authorizes and authenticates
+ // the requests.
+ AccessToken string `json:"access_token"`
+
+ // TokenType is the type of token.
+ // The Type method returns either this or "Bearer", the default.
+ TokenType string `json:"token_type,omitempty"`
+
+ // RefreshToken is a token that's used by the application
+ // (as opposed to the user) to refresh the access token
+ // if it expires.
+ RefreshToken string `json:"refresh_token,omitempty"`
+
+ // Expiry is the optional expiration time of the access token.
+ //
+ // If zero, TokenSource implementations will reuse the same
+ // token forever and RefreshToken or equivalent
+ // mechanisms for that TokenSource will not be used.
+ Expiry time.Time `json:"expiry,omitempty"`
+
+ // raw optionally contains extra metadata from the server
+ // when updating a token.
+ raw interface{}
+}
+
+// Type returns t.TokenType if non-empty, else "Bearer".
+func (t *Token) Type() string {
+ if strings.EqualFold(t.TokenType, "bearer") {
+ return "Bearer"
+ }
+ if strings.EqualFold(t.TokenType, "mac") {
+ return "MAC"
+ }
+ if strings.EqualFold(t.TokenType, "basic") {
+ return "Basic"
+ }
+ if t.TokenType != "" {
+ return t.TokenType
+ }
+ return "Bearer"
+}
+
+// SetAuthHeader sets the Authorization header to r using the access
+// token in t.
+//
+// This method is unnecessary when using Transport or an HTTP Client
+// returned by this package.
+func (t *Token) SetAuthHeader(r *http.Request) {
+ r.Header.Set("Authorization", t.Type()+" "+t.AccessToken)
+}
+
+// WithExtra returns a new Token that's a clone of t, but using the
+// provided raw extra map. This is only intended for use by packages
+// implementing derivative OAuth2 flows.
+func (t *Token) WithExtra(extra interface{}) *Token {
+ t2 := new(Token)
+ *t2 = *t
+ t2.raw = extra
+ return t2
+}
+
+// Extra returns an extra field.
+// Extra fields are key-value pairs returned by the server as a
+// part of the token retrieval response.
+func (t *Token) Extra(key string) interface{} {
+ if raw, ok := t.raw.(map[string]interface{}); ok {
+ return raw[key]
+ }
+
+ vals, ok := t.raw.(url.Values)
+ if !ok {
+ return nil
+ }
+
+ v := vals.Get(key)
+ switch s := strings.TrimSpace(v); strings.Count(s, ".") {
+ case 0: // Contains no "."; try to parse as int
+ if i, err := strconv.ParseInt(s, 10, 64); err == nil {
+ return i
+ }
+ case 1: // Contains a single "."; try to parse as float
+ if f, err := strconv.ParseFloat(s, 64); err == nil {
+ return f
+ }
+ }
+
+ return v
+}
+
+// expired reports whether the token is expired.
+// t must be non-nil.
+func (t *Token) expired() bool {
+ if t.Expiry.IsZero() {
+ return false
+ }
+ return t.Expiry.Add(-expiryDelta).Before(time.Now())
+}
+
+// Valid reports whether t is non-nil, has an AccessToken, and is not expired.
+func (t *Token) Valid() bool {
+ return t != nil && t.AccessToken != "" && !t.expired()
+}
+
+// tokenFromInternal maps an *internal.Token struct into
+// a *Token struct.
+func tokenFromInternal(t *internal.Token) *Token {
+ if t == nil {
+ return nil
+ }
+ return &Token{
+ AccessToken: t.AccessToken,
+ TokenType: t.TokenType,
+ RefreshToken: t.RefreshToken,
+ Expiry: t.Expiry,
+ raw: t.Raw,
+ }
+}
+
+// retrieveToken takes a *Config and uses that to retrieve an *internal.Token.
+// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along
+// with an error..
+func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) {
+ tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v)
+ if err != nil {
+ return nil, err
+ }
+ return tokenFromInternal(tk), nil
+}
diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go
new file mode 100644
index 0000000..92ac7e2
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/transport.go
@@ -0,0 +1,132 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "errors"
+ "io"
+ "net/http"
+ "sync"
+)
+
+// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
+// wrapping a base RoundTripper and adding an Authorization header
+// with a token from the supplied Sources.
+//
+// Transport is a low-level mechanism. Most code will use the
+// higher-level Config.Client method instead.
+type Transport struct {
+ // Source supplies the token to add to outgoing requests'
+ // Authorization headers.
+ Source TokenSource
+
+ // Base is the base RoundTripper used to make HTTP requests.
+ // If nil, http.DefaultTransport is used.
+ Base http.RoundTripper
+
+ mu sync.Mutex // guards modReq
+ modReq map[*http.Request]*http.Request // original -> modified
+}
+
+// RoundTrip authorizes and authenticates the request with an
+// access token. If no token exists or token is expired,
+// tries to refresh/fetch a new token.
+func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ if t.Source == nil {
+ return nil, errors.New("oauth2: Transport's Source is nil")
+ }
+ token, err := t.Source.Token()
+ if err != nil {
+ return nil, err
+ }
+
+ req2 := cloneRequest(req) // per RoundTripper contract
+ token.SetAuthHeader(req2)
+ t.setModReq(req, req2)
+ res, err := t.base().RoundTrip(req2)
+ if err != nil {
+ t.setModReq(req, nil)
+ return nil, err
+ }
+ res.Body = &onEOFReader{
+ rc: res.Body,
+ fn: func() { t.setModReq(req, nil) },
+ }
+ return res, nil
+}
+
+// CancelRequest cancels an in-flight request by closing its connection.
+func (t *Transport) CancelRequest(req *http.Request) {
+ type canceler interface {
+ CancelRequest(*http.Request)
+ }
+ if cr, ok := t.base().(canceler); ok {
+ t.mu.Lock()
+ modReq := t.modReq[req]
+ delete(t.modReq, req)
+ t.mu.Unlock()
+ cr.CancelRequest(modReq)
+ }
+}
+
+func (t *Transport) base() http.RoundTripper {
+ if t.Base != nil {
+ return t.Base
+ }
+ return http.DefaultTransport
+}
+
+func (t *Transport) setModReq(orig, mod *http.Request) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.modReq == nil {
+ t.modReq = make(map[*http.Request]*http.Request)
+ }
+ if mod == nil {
+ delete(t.modReq, orig)
+ } else {
+ t.modReq[orig] = mod
+ }
+}
+
+// cloneRequest returns a clone of the provided *http.Request.
+// The clone is a shallow copy of the struct and its Header map.
+func cloneRequest(r *http.Request) *http.Request {
+ // shallow copy of the struct
+ r2 := new(http.Request)
+ *r2 = *r
+ // deep copy of the Header
+ r2.Header = make(http.Header, len(r.Header))
+ for k, s := range r.Header {
+ r2.Header[k] = append([]string(nil), s...)
+ }
+ return r2
+}
+
+type onEOFReader struct {
+ rc io.ReadCloser
+ fn func()
+}
+
+func (r *onEOFReader) Read(p []byte) (n int, err error) {
+ n, err = r.rc.Read(p)
+ if err == io.EOF {
+ r.runFunc()
+ }
+ return
+}
+
+func (r *onEOFReader) Close() error {
+ err := r.rc.Close()
+ r.runFunc()
+ return err
+}
+
+func (r *onEOFReader) runFunc() {
+ if fn := r.fn; fn != nil {
+ fn()
+ r.fn = nil
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/uber/uber.go b/vendor/golang.org/x/oauth2/uber/uber.go
new file mode 100644
index 0000000..5520a64
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/uber/uber.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package uber provides constants for using OAuth2 to access Uber.
+package uber // import "golang.org/x/oauth2/uber"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Uber's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://login.uber.com/oauth/v2/authorize",
+ TokenURL: "https://login.uber.com/oauth/v2/token",
+}
diff --git a/vendor/golang.org/x/oauth2/vk/vk.go b/vendor/golang.org/x/oauth2/vk/vk.go
new file mode 100644
index 0000000..bd8e159
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/vk/vk.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vk provides constants for using OAuth2 to access VK.com.
+package vk // import "golang.org/x/oauth2/vk"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is VK's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://oauth.vk.com/authorize",
+ TokenURL: "https://oauth.vk.com/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/yandex/yandex.go b/vendor/golang.org/x/oauth2/yandex/yandex.go
new file mode 100644
index 0000000..5ebf666
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/yandex/yandex.go
@@ -0,0 +1,16 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package yandex provides constants for using OAuth2 to access Yandex APIs.
+package yandex // import "golang.org/x/oauth2/yandex"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is the Yandex OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://oauth.yandex.com/authorize",
+ TokenURL: "https://oauth.yandex.com/token",
+}
diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/sys/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/sys/PATENTS b/vendor/golang.org/x/sys/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/sys/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md
new file mode 100644
index 0000000..bc6f603
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/README.md
@@ -0,0 +1,173 @@
+# Building `sys/unix`
+
+The sys/unix package provides access to the raw system call interface of the
+underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
+
+Porting Go to a new architecture/OS combination or adding syscalls, types, or
+constants to an existing architecture/OS pair requires some manual effort;
+however, there are tools that automate much of the process.
+
+## Build Systems
+
+There are currently two ways we generate the necessary files. We are currently
+migrating the build system to use containers so the builds are reproducible.
+This is being done on an OS-by-OS basis. Please update this documentation as
+components of the build system change.
+
+### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`)
+
+The old build system generates the Go files based on the C header files
+present on your system. This means that files
+for a given GOOS/GOARCH pair must be generated on a system with that OS and
+architecture. This also means that the generated code can differ from system
+to system, based on differences in the header files.
+
+To avoid this, if you are using the old build system, only generate the Go
+files on an installation with unmodified header files. It is also important to
+keep track of which version of the OS the files were generated from (ex.
+Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
+and have each OS upgrade correspond to a single change.
+
+To build the files for your current OS and architecture, make sure GOOS and
+GOARCH are set correctly and run `mkall.sh`. This will generate the files for
+your specific system. Running `mkall.sh -n` shows the commands that will be run.
+
+Requirements: bash, perl, go
+
+### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`)
+
+The new build system uses a Docker container to generate the go files directly
+from source checkouts of the kernel and various system libraries. This means
+that on any platform that supports Docker, all the files using the new build
+system can be generated at once, and generated files will not change based on
+what the person running the scripts has installed on their computer.
+
+The OS specific files for the new build system are located in the `${GOOS}`
+directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
+the kernel or system library updates, modify the Dockerfile at
+`${GOOS}/Dockerfile` to checkout the new release of the source.
+
+To build all the files under the new build system, you must be on an amd64/Linux
+system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
+then generate all of the files for all of the GOOS/GOARCH pairs in the new build
+system. Running `mkall.sh -n` shows the commands that will be run.
+
+Requirements: bash, perl, go, docker
+
+## Component files
+
+This section describes the various files used in the code generation process.
+It also contains instructions on how to modify these files to add a new
+architecture/OS or to add additional syscalls, types, or constants. Note that
+if you are using the new build system, the scripts cannot be called normally.
+They must be called from within the docker container.
+
+### asm files
+
+The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
+call dispatch. There are three entry points:
+```
+ func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
+```
+The first and second are the standard ones; they differ only in how many
+arguments can be passed to the kernel. The third is for low-level use by the
+ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
+let it know that a system call is running.
+
+When porting Go to an new architecture/OS, this file must be implemented for
+each GOOS/GOARCH pair.
+
+### mksysnum
+
+Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
+for the old system). This script takes in a list of header files containing the
+syscall number declarations and parses them to produce the corresponding list of
+Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
+constants.
+
+Adding new syscall numbers is mostly done by running the build on a sufficiently
+new installation of the target OS (or updating the source checkouts for the
+new build system). However, depending on the OS, you make need to update the
+parsing in mksysnum.
+
+### mksyscall.pl
+
+The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
+hand-written Go files which implement system calls (for unix, the specific OS,
+or the specific OS/Architecture pair respectively) that need special handling
+and list `//sys` comments giving prototypes for ones that can be generated.
+
+The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
+them into syscalls. This requires the name of the prototype in the comment to
+match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
+prototype can be exported (capitalized) or not.
+
+Adding a new syscall often just requires adding a new `//sys` function prototype
+with the desired arguments and a capitalized name so it is exported. However, if
+you want the interface to the syscall to be different, often one will make an
+unexported `//sys` prototype, an then write a custom wrapper in
+`syscall_${GOOS}.go`.
+
+### types files
+
+For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
+`types_${GOOS}.go` on the old system). This file includes standard C headers and
+creates Go type aliases to the corresponding C types. The file is then fed
+through godef to get the Go compatible definitions. Finally, the generated code
+is fed though mkpost.go to format the code correctly and remove any hidden or
+private identifiers. This cleaned-up code is written to
+`ztypes_${GOOS}_${GOARCH}.go`.
+
+The hardest part about preparing this file is figuring out which headers to
+include and which symbols need to be `#define`d to get the actual data
+structures that pass through to the kernel system calls. Some C libraries
+preset alternate versions for binary compatibility and translate them on the
+way in and out of system calls, but there is almost always a `#define` that can
+get the real ones.
+See `types_darwin.go` and `linux/types.go` for examples.
+
+To add a new type, add in the necessary include statement at the top of the
+file (if it is not already there) and add in a type alias line. Note that if
+your type is significantly different on different architectures, you may need
+some `#if/#elif` macros in your include statements.
+
+### mkerrors.sh
+
+This script is used to generate the system's various constants. This doesn't
+just include the error numbers and error strings, but also the signal numbers
+an a wide variety of miscellaneous constants. The constants come from the list
+of include files in the `includes_${uname}` variable. A regex then picks out
+the desired `#define` statements, and generates the corresponding Go constants.
+The error numbers and strings are generated from `#include `, and the
+signal numbers and strings are generated from `#include `. All of
+these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
+`_errors.c`, which prints out all the constants.
+
+To add a constant, add the header that includes it to the appropriate variable.
+Then, edit the regex (if necessary) to match the desired constant. Avoid making
+the regex too broad to avoid matching unintended constants.
+
+
+## Generated files
+
+### `zerror_${GOOS}_${GOARCH}.go`
+
+A file containing all of the system's generated error numbers, error strings,
+signal numbers, and constants. Generated by `mkerrors.sh` (see above).
+
+### `zsyscall_${GOOS}_${GOARCH}.go`
+
+A file containing all the generated syscalls for a specific GOOS and GOARCH.
+Generated by `mksyscall.pl` (see above).
+
+### `zsysnum_${GOOS}_${GOARCH}.go`
+
+A list of numeric constants for all the syscall number of the specific GOOS
+and GOARCH. Generated by mksysnum (see above).
+
+### `ztypes_${GOOS}_${GOARCH}.go`
+
+A file containing Go types for passing into (or returning from) syscalls.
+Generated by godefs and the types file (see above).
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_386.s b/vendor/golang.org/x/sys/unix/asm_darwin_386.s
new file mode 100644
index 0000000..8a72783
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s b/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
new file mode 100644
index 0000000..6321421
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
new file mode 100644
index 0000000..333242d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_arm.s
@@ -0,0 +1,30 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+// +build arm,darwin
+
+#include "textflag.h"
+
+//
+// System call support for ARM, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s b/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
new file mode 100644
index 0000000..97e0174
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
@@ -0,0 +1,30 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+// +build arm64,darwin
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, Darwin
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s b/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
new file mode 100644
index 0000000..d5ed672
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, DragonFly
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-64
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-88
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-112
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-64
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-88
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_386.s b/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
new file mode 100644
index 0000000..c9a0a26
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
new file mode 100644
index 0000000..3517247
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s b/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
new file mode 100644
index 0000000..9227c87
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, FreeBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_386.s b/vendor/golang.org/x/sys/unix/asm_linux_386.s
new file mode 100644
index 0000000..4db2909
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_386.s
@@ -0,0 +1,35 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for 386, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·socketcall(SB),NOSPLIT,$0-36
+ JMP syscall·socketcall(SB)
+
+TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
+ JMP syscall·rawsocketcall(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-28
+ JMP syscall·seek(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
new file mode 100644
index 0000000..44e25c6
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for AMD64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
+
+TEXT ·gettimeofday(SB),NOSPLIT,$0-16
+ JMP syscall·gettimeofday(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/vendor/golang.org/x/sys/unix/asm_linux_arm.s
new file mode 100644
index 0000000..cf0b574
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for arm, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
+
+TEXT ·seek(SB),NOSPLIT,$0-32
+ B syscall·seek(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
new file mode 100644
index 0000000..4be9bfe
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s
@@ -0,0 +1,24 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build arm64
+// +build !gccgo
+
+#include "textflag.h"
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ B syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
new file mode 100644
index 0000000..724e580
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
@@ -0,0 +1,28 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips64 mips64le
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for mips64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
new file mode 100644
index 0000000..2ea4257
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
@@ -0,0 +1,31 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips mipsle
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for mips, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
new file mode 100644
index 0000000..8d231fe
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
@@ -0,0 +1,28 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build ppc64 ppc64le
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for ppc64, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ BR syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ BR syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ BR syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ BR syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
new file mode 100644
index 0000000..1188985
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s
@@ -0,0 +1,28 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build s390x
+// +build linux
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for s390x, Linux
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ BR syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ BR syscall·Syscall6(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ BR syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ BR syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_386.s b/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
new file mode 100644
index 0000000..48bdcd7
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
new file mode 100644
index 0000000..2ede05c
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s b/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
new file mode 100644
index 0000000..e892857
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, NetBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_386.s b/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
new file mode 100644
index 0000000..00576f3
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for 386, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
new file mode 100644
index 0000000..790ef77
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for AMD64, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-56
+ JMP syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+ JMP syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-104
+ JMP syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+ JMP syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+ JMP syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s b/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
new file mode 100644
index 0000000..469bfa1
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
@@ -0,0 +1,29 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System call support for ARM, OpenBSD
+//
+
+// Just jump to package syscall's implementation for all these functions.
+// The runtime may know about them.
+
+TEXT ·Syscall(SB),NOSPLIT,$0-28
+ B syscall·Syscall(SB)
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-40
+ B syscall·Syscall6(SB)
+
+TEXT ·Syscall9(SB),NOSPLIT,$0-52
+ B syscall·Syscall9(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-28
+ B syscall·RawSyscall(SB)
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
+ B syscall·RawSyscall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
new file mode 100644
index 0000000..ded8260
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
@@ -0,0 +1,17 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+#include "textflag.h"
+
+//
+// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
+//
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·sysvicall6(SB)
+
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
+ JMP syscall·rawSysvicall6(SB)
diff --git a/vendor/golang.org/x/sys/unix/bluetooth_linux.go b/vendor/golang.org/x/sys/unix/bluetooth_linux.go
new file mode 100644
index 0000000..6e32296
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/bluetooth_linux.go
@@ -0,0 +1,35 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Bluetooth sockets and messages
+
+package unix
+
+// Bluetooth Protocols
+const (
+ BTPROTO_L2CAP = 0
+ BTPROTO_HCI = 1
+ BTPROTO_SCO = 2
+ BTPROTO_RFCOMM = 3
+ BTPROTO_BNEP = 4
+ BTPROTO_CMTP = 5
+ BTPROTO_HIDP = 6
+ BTPROTO_AVDTP = 7
+)
+
+const (
+ HCI_CHANNEL_RAW = 0
+ HCI_CHANNEL_USER = 1
+ HCI_CHANNEL_MONITOR = 2
+ HCI_CHANNEL_CONTROL = 3
+)
+
+// Socketoption Level
+const (
+ SOL_BLUETOOTH = 0x112
+ SOL_HCI = 0x0
+ SOL_L2CAP = 0x6
+ SOL_RFCOMM = 0x12
+ SOL_SCO = 0x11
+)
diff --git a/vendor/golang.org/x/sys/unix/cap_freebsd.go b/vendor/golang.org/x/sys/unix/cap_freebsd.go
new file mode 100644
index 0000000..83b6bce
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/cap_freebsd.go
@@ -0,0 +1,195 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd
+
+package unix
+
+import (
+ errorspkg "errors"
+ "fmt"
+)
+
+// Go implementation of C mostly found in /usr/src/sys/kern/subr_capability.c
+
+const (
+ // This is the version of CapRights this package understands. See C implementation for parallels.
+ capRightsGoVersion = CAP_RIGHTS_VERSION_00
+ capArSizeMin = CAP_RIGHTS_VERSION_00 + 2
+ capArSizeMax = capRightsGoVersion + 2
+)
+
+var (
+ bit2idx = []int{
+ -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
+ 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ }
+)
+
+func capidxbit(right uint64) int {
+ return int((right >> 57) & 0x1f)
+}
+
+func rightToIndex(right uint64) (int, error) {
+ idx := capidxbit(right)
+ if idx < 0 || idx >= len(bit2idx) {
+ return -2, fmt.Errorf("index for right 0x%x out of range", right)
+ }
+ return bit2idx[idx], nil
+}
+
+func caprver(right uint64) int {
+ return int(right >> 62)
+}
+
+func capver(rights *CapRights) int {
+ return caprver(rights.Rights[0])
+}
+
+func caparsize(rights *CapRights) int {
+ return capver(rights) + 2
+}
+
+// CapRightsSet sets the permissions in setrights in rights.
+func CapRightsSet(rights *CapRights, setrights []uint64) error {
+ // This is essentially a copy of cap_rights_vset()
+ if capver(rights) != CAP_RIGHTS_VERSION_00 {
+ return fmt.Errorf("bad rights version %d", capver(rights))
+ }
+
+ n := caparsize(rights)
+ if n < capArSizeMin || n > capArSizeMax {
+ return errorspkg.New("bad rights size")
+ }
+
+ for _, right := range setrights {
+ if caprver(right) != CAP_RIGHTS_VERSION_00 {
+ return errorspkg.New("bad right version")
+ }
+ i, err := rightToIndex(right)
+ if err != nil {
+ return err
+ }
+ if i >= n {
+ return errorspkg.New("index overflow")
+ }
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errorspkg.New("index mismatch")
+ }
+ rights.Rights[i] |= right
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errorspkg.New("index mismatch (after assign)")
+ }
+ }
+
+ return nil
+}
+
+// CapRightsClear clears the permissions in clearrights from rights.
+func CapRightsClear(rights *CapRights, clearrights []uint64) error {
+ // This is essentially a copy of cap_rights_vclear()
+ if capver(rights) != CAP_RIGHTS_VERSION_00 {
+ return fmt.Errorf("bad rights version %d", capver(rights))
+ }
+
+ n := caparsize(rights)
+ if n < capArSizeMin || n > capArSizeMax {
+ return errorspkg.New("bad rights size")
+ }
+
+ for _, right := range clearrights {
+ if caprver(right) != CAP_RIGHTS_VERSION_00 {
+ return errorspkg.New("bad right version")
+ }
+ i, err := rightToIndex(right)
+ if err != nil {
+ return err
+ }
+ if i >= n {
+ return errorspkg.New("index overflow")
+ }
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errorspkg.New("index mismatch")
+ }
+ rights.Rights[i] &= ^(right & 0x01FFFFFFFFFFFFFF)
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return errorspkg.New("index mismatch (after assign)")
+ }
+ }
+
+ return nil
+}
+
+// CapRightsIsSet checks whether all the permissions in setrights are present in rights.
+func CapRightsIsSet(rights *CapRights, setrights []uint64) (bool, error) {
+ // This is essentially a copy of cap_rights_is_vset()
+ if capver(rights) != CAP_RIGHTS_VERSION_00 {
+ return false, fmt.Errorf("bad rights version %d", capver(rights))
+ }
+
+ n := caparsize(rights)
+ if n < capArSizeMin || n > capArSizeMax {
+ return false, errorspkg.New("bad rights size")
+ }
+
+ for _, right := range setrights {
+ if caprver(right) != CAP_RIGHTS_VERSION_00 {
+ return false, errorspkg.New("bad right version")
+ }
+ i, err := rightToIndex(right)
+ if err != nil {
+ return false, err
+ }
+ if i >= n {
+ return false, errorspkg.New("index overflow")
+ }
+ if capidxbit(rights.Rights[i]) != capidxbit(right) {
+ return false, errorspkg.New("index mismatch")
+ }
+ if (rights.Rights[i] & right) != right {
+ return false, nil
+ }
+ }
+
+ return true, nil
+}
+
+func capright(idx uint64, bit uint64) uint64 {
+ return ((1 << (57 + idx)) | bit)
+}
+
+// CapRightsInit returns a pointer to an initialised CapRights structure filled with rights.
+// See man cap_rights_init(3) and rights(4).
+func CapRightsInit(rights []uint64) (*CapRights, error) {
+ var r CapRights
+ r.Rights[0] = (capRightsGoVersion << 62) | capright(0, 0)
+ r.Rights[1] = capright(1, 0)
+
+ err := CapRightsSet(&r, rights)
+ if err != nil {
+ return nil, err
+ }
+ return &r, nil
+}
+
+// CapRightsLimit reduces the operations permitted on fd to at most those contained in rights.
+// The capability rights on fd can never be increased by CapRightsLimit.
+// See man cap_rights_limit(2) and rights(4).
+func CapRightsLimit(fd uintptr, rights *CapRights) error {
+ return capRightsLimit(int(fd), rights)
+}
+
+// CapRightsGet returns a CapRights structure containing the operations permitted on fd.
+// See man cap_rights_get(3) and rights(4).
+func CapRightsGet(fd uintptr) (*CapRights, error) {
+ r, err := CapRightsInit(nil)
+ if err != nil {
+ return nil, err
+ }
+ err = capRightsGet(capRightsGoVersion, int(fd), r)
+ if err != nil {
+ return nil, err
+ }
+ return r, nil
+}
diff --git a/vendor/golang.org/x/sys/unix/constants.go b/vendor/golang.org/x/sys/unix/constants.go
new file mode 100644
index 0000000..a96f0eb
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/constants.go
@@ -0,0 +1,13 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package unix
+
+const (
+ R_OK = 0x4
+ W_OK = 0x2
+ X_OK = 0x1
+)
diff --git a/vendor/golang.org/x/sys/unix/dev_darwin.go b/vendor/golang.org/x/sys/unix/dev_darwin.go
new file mode 100644
index 0000000..8d1dc0f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_darwin.go
@@ -0,0 +1,24 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in Darwin's sys/types.h header.
+
+package unix
+
+// Major returns the major component of a Darwin device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev >> 24) & 0xff)
+}
+
+// Minor returns the minor component of a Darwin device number.
+func Minor(dev uint64) uint32 {
+ return uint32(dev & 0xffffff)
+}
+
+// Mkdev returns a Darwin device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ return (uint64(major) << 24) | uint64(minor)
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_dragonfly.go b/vendor/golang.org/x/sys/unix/dev_dragonfly.go
new file mode 100644
index 0000000..8502f20
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_dragonfly.go
@@ -0,0 +1,30 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in Dragonfly's sys/types.h header.
+//
+// The information below is extracted and adapted from sys/types.h:
+//
+// Minor gives a cookie instead of an index since in order to avoid changing the
+// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
+// devices that don't use them.
+
+package unix
+
+// Major returns the major component of a DragonFlyBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev >> 8) & 0xff)
+}
+
+// Minor returns the minor component of a DragonFlyBSD device number.
+func Minor(dev uint64) uint32 {
+ return uint32(dev & 0xffff00ff)
+}
+
+// Mkdev returns a DragonFlyBSD device number generated from the given major and
+// minor components.
+func Mkdev(major, minor uint32) uint64 {
+ return (uint64(major) << 8) | uint64(minor)
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_freebsd.go b/vendor/golang.org/x/sys/unix/dev_freebsd.go
new file mode 100644
index 0000000..eba3b4b
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_freebsd.go
@@ -0,0 +1,30 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in FreeBSD's sys/types.h header.
+//
+// The information below is extracted and adapted from sys/types.h:
+//
+// Minor gives a cookie instead of an index since in order to avoid changing the
+// meanings of bits 0-15 or wasting time and space shifting bits 16-31 for
+// devices that don't use them.
+
+package unix
+
+// Major returns the major component of a FreeBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev >> 8) & 0xff)
+}
+
+// Minor returns the minor component of a FreeBSD device number.
+func Minor(dev uint64) uint32 {
+ return uint32(dev & 0xffff00ff)
+}
+
+// Mkdev returns a FreeBSD device number generated from the given major and
+// minor components.
+func Mkdev(major, minor uint32) uint64 {
+ return (uint64(major) << 8) | uint64(minor)
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_linux.go b/vendor/golang.org/x/sys/unix/dev_linux.go
new file mode 100644
index 0000000..d165d6f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_linux.go
@@ -0,0 +1,42 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used by the Linux kernel and glibc.
+//
+// The information below is extracted and adapted from bits/sysmacros.h in the
+// glibc sources:
+//
+// dev_t in glibc is 64-bit, with 32-bit major and minor numbers. glibc's
+// default encoding is MMMM Mmmm mmmM MMmm, where M is a hex digit of the major
+// number and m is a hex digit of the minor number. This is backward compatible
+// with legacy systems where dev_t is 16 bits wide, encoded as MMmm. It is also
+// backward compatible with the Linux kernel, which for some architectures uses
+// 32-bit dev_t, encoded as mmmM MMmm.
+
+package unix
+
+// Major returns the major component of a Linux device number.
+func Major(dev uint64) uint32 {
+ major := uint32((dev & 0x00000000000fff00) >> 8)
+ major |= uint32((dev & 0xfffff00000000000) >> 32)
+ return major
+}
+
+// Minor returns the minor component of a Linux device number.
+func Minor(dev uint64) uint32 {
+ minor := uint32((dev & 0x00000000000000ff) >> 0)
+ minor |= uint32((dev & 0x00000ffffff00000) >> 12)
+ return minor
+}
+
+// Mkdev returns a Linux device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ dev := (uint64(major) & 0x00000fff) << 8
+ dev |= (uint64(major) & 0xfffff000) << 32
+ dev |= (uint64(minor) & 0x000000ff) << 0
+ dev |= (uint64(minor) & 0xffffff00) << 12
+ return dev
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_netbsd.go b/vendor/golang.org/x/sys/unix/dev_netbsd.go
new file mode 100644
index 0000000..b4a203d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_netbsd.go
@@ -0,0 +1,29 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in NetBSD's sys/types.h header.
+
+package unix
+
+// Major returns the major component of a NetBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev & 0x000fff00) >> 8)
+}
+
+// Minor returns the minor component of a NetBSD device number.
+func Minor(dev uint64) uint32 {
+ minor := uint32((dev & 0x000000ff) >> 0)
+ minor |= uint32((dev & 0xfff00000) >> 12)
+ return minor
+}
+
+// Mkdev returns a NetBSD device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ dev := (uint64(major) << 8) & 0x000fff00
+ dev |= (uint64(minor) << 12) & 0xfff00000
+ dev |= (uint64(minor) << 0) & 0x000000ff
+ return dev
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_openbsd.go b/vendor/golang.org/x/sys/unix/dev_openbsd.go
new file mode 100644
index 0000000..f3430c4
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dev_openbsd.go
@@ -0,0 +1,29 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in OpenBSD's sys/types.h header.
+
+package unix
+
+// Major returns the major component of an OpenBSD device number.
+func Major(dev uint64) uint32 {
+ return uint32((dev & 0x0000ff00) >> 8)
+}
+
+// Minor returns the minor component of an OpenBSD device number.
+func Minor(dev uint64) uint32 {
+ minor := uint32((dev & 0x000000ff) >> 0)
+ minor |= uint32((dev & 0xffff0000) >> 8)
+ return minor
+}
+
+// Mkdev returns an OpenBSD device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+ dev := (uint64(major) << 8) & 0x0000ff00
+ dev |= (uint64(minor) << 8) & 0xffff0000
+ dev |= (uint64(minor) << 0) & 0x000000ff
+ return dev
+}
diff --git a/vendor/golang.org/x/sys/unix/dirent.go b/vendor/golang.org/x/sys/unix/dirent.go
new file mode 100644
index 0000000..bd47581
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/dirent.go
@@ -0,0 +1,102 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package unix
+
+import "unsafe"
+
+// readInt returns the size-bytes unsigned integer in native byte order at offset off.
+func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
+ if len(b) < int(off+size) {
+ return 0, false
+ }
+ if isBigEndian {
+ return readIntBE(b[off:], size), true
+ }
+ return readIntLE(b[off:], size), true
+}
+
+func readIntBE(b []byte, size uintptr) uint64 {
+ switch size {
+ case 1:
+ return uint64(b[0])
+ case 2:
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[1]) | uint64(b[0])<<8
+ case 4:
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
+ case 8:
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+ default:
+ panic("syscall: readInt with unsupported size")
+ }
+}
+
+func readIntLE(b []byte, size uintptr) uint64 {
+ switch size {
+ case 1:
+ return uint64(b[0])
+ case 2:
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8
+ case 4:
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
+ case 8:
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+ default:
+ panic("syscall: readInt with unsupported size")
+ }
+}
+
+// ParseDirent parses up to max directory entries in buf,
+// appending the names to names. It returns the number of
+// bytes consumed from buf, the number of entries added
+// to names, and the new names slice.
+func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
+ origlen := len(buf)
+ count = 0
+ for max != 0 && len(buf) > 0 {
+ reclen, ok := direntReclen(buf)
+ if !ok || reclen > uint64(len(buf)) {
+ return origlen, count, names
+ }
+ rec := buf[:reclen]
+ buf = buf[reclen:]
+ ino, ok := direntIno(rec)
+ if !ok {
+ break
+ }
+ if ino == 0 { // File absent in directory.
+ continue
+ }
+ const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
+ namlen, ok := direntNamlen(rec)
+ if !ok || namoff+namlen > uint64(len(rec)) {
+ break
+ }
+ name := rec[namoff : namoff+namlen]
+ for i, c := range name {
+ if c == 0 {
+ name = name[:i]
+ break
+ }
+ }
+ // Check for useless names before allocating a string.
+ if string(name) == "." || string(name) == ".." {
+ continue
+ }
+ max--
+ count++
+ names = append(names, string(name))
+ }
+ return origlen - len(buf), count, names
+}
diff --git a/vendor/golang.org/x/sys/unix/endian_big.go b/vendor/golang.org/x/sys/unix/endian_big.go
new file mode 100644
index 0000000..5e92690
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/endian_big.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// +build ppc64 s390x mips mips64
+
+package unix
+
+const isBigEndian = true
diff --git a/vendor/golang.org/x/sys/unix/endian_little.go b/vendor/golang.org/x/sys/unix/endian_little.go
new file mode 100644
index 0000000..085df2d
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/endian_little.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le
+
+package unix
+
+const isBigEndian = false
diff --git a/vendor/golang.org/x/sys/unix/env_unix.go b/vendor/golang.org/x/sys/unix/env_unix.go
new file mode 100644
index 0000000..2e06b33
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/env_unix.go
@@ -0,0 +1,27 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+// Unix environment variables.
+
+package unix
+
+import "syscall"
+
+func Getenv(key string) (value string, found bool) {
+ return syscall.Getenv(key)
+}
+
+func Setenv(key, value string) error {
+ return syscall.Setenv(key, value)
+}
+
+func Clearenv() {
+ syscall.Clearenv()
+}
+
+func Environ() []string {
+ return syscall.Environ()
+}
diff --git a/vendor/golang.org/x/sys/unix/env_unset.go b/vendor/golang.org/x/sys/unix/env_unset.go
new file mode 100644
index 0000000..c44fdc4
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/env_unset.go
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.4
+
+package unix
+
+import "syscall"
+
+func Unsetenv(key string) error {
+ // This was added in Go 1.4.
+ return syscall.Unsetenv(key)
+}
diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_386.go b/vendor/golang.org/x/sys/unix/errors_freebsd_386.go
new file mode 100644
index 0000000..c56bc8b
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/errors_freebsd_386.go
@@ -0,0 +1,227 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
+// them here for backwards compatibility.
+
+package unix
+
+const (
+ IFF_SMART = 0x20
+ IFT_1822 = 0x2
+ IFT_A12MPPSWITCH = 0x82
+ IFT_AAL2 = 0xbb
+ IFT_AAL5 = 0x31
+ IFT_ADSL = 0x5e
+ IFT_AFLANE8023 = 0x3b
+ IFT_AFLANE8025 = 0x3c
+ IFT_ARAP = 0x58
+ IFT_ARCNET = 0x23
+ IFT_ARCNETPLUS = 0x24
+ IFT_ASYNC = 0x54
+ IFT_ATM = 0x25
+ IFT_ATMDXI = 0x69
+ IFT_ATMFUNI = 0x6a
+ IFT_ATMIMA = 0x6b
+ IFT_ATMLOGICAL = 0x50
+ IFT_ATMRADIO = 0xbd
+ IFT_ATMSUBINTERFACE = 0x86
+ IFT_ATMVCIENDPT = 0xc2
+ IFT_ATMVIRTUAL = 0x95
+ IFT_BGPPOLICYACCOUNTING = 0xa2
+ IFT_BSC = 0x53
+ IFT_CCTEMUL = 0x3d
+ IFT_CEPT = 0x13
+ IFT_CES = 0x85
+ IFT_CHANNEL = 0x46
+ IFT_CNR = 0x55
+ IFT_COFFEE = 0x84
+ IFT_COMPOSITELINK = 0x9b
+ IFT_DCN = 0x8d
+ IFT_DIGITALPOWERLINE = 0x8a
+ IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+ IFT_DLSW = 0x4a
+ IFT_DOCSCABLEDOWNSTREAM = 0x80
+ IFT_DOCSCABLEMACLAYER = 0x7f
+ IFT_DOCSCABLEUPSTREAM = 0x81
+ IFT_DS0 = 0x51
+ IFT_DS0BUNDLE = 0x52
+ IFT_DS1FDL = 0xaa
+ IFT_DS3 = 0x1e
+ IFT_DTM = 0x8c
+ IFT_DVBASILN = 0xac
+ IFT_DVBASIOUT = 0xad
+ IFT_DVBRCCDOWNSTREAM = 0x93
+ IFT_DVBRCCMACLAYER = 0x92
+ IFT_DVBRCCUPSTREAM = 0x94
+ IFT_ENC = 0xf4
+ IFT_EON = 0x19
+ IFT_EPLRS = 0x57
+ IFT_ESCON = 0x49
+ IFT_ETHER = 0x6
+ IFT_FAITH = 0xf2
+ IFT_FAST = 0x7d
+ IFT_FASTETHER = 0x3e
+ IFT_FASTETHERFX = 0x45
+ IFT_FDDI = 0xf
+ IFT_FIBRECHANNEL = 0x38
+ IFT_FRAMERELAYINTERCONNECT = 0x3a
+ IFT_FRAMERELAYMPI = 0x5c
+ IFT_FRDLCIENDPT = 0xc1
+ IFT_FRELAY = 0x20
+ IFT_FRELAYDCE = 0x2c
+ IFT_FRF16MFRBUNDLE = 0xa3
+ IFT_FRFORWARD = 0x9e
+ IFT_G703AT2MB = 0x43
+ IFT_G703AT64K = 0x42
+ IFT_GIF = 0xf0
+ IFT_GIGABITETHERNET = 0x75
+ IFT_GR303IDT = 0xb2
+ IFT_GR303RDT = 0xb1
+ IFT_H323GATEKEEPER = 0xa4
+ IFT_H323PROXY = 0xa5
+ IFT_HDH1822 = 0x3
+ IFT_HDLC = 0x76
+ IFT_HDSL2 = 0xa8
+ IFT_HIPERLAN2 = 0xb7
+ IFT_HIPPI = 0x2f
+ IFT_HIPPIINTERFACE = 0x39
+ IFT_HOSTPAD = 0x5a
+ IFT_HSSI = 0x2e
+ IFT_HY = 0xe
+ IFT_IBM370PARCHAN = 0x48
+ IFT_IDSL = 0x9a
+ IFT_IEEE80211 = 0x47
+ IFT_IEEE80212 = 0x37
+ IFT_IEEE8023ADLAG = 0xa1
+ IFT_IFGSN = 0x91
+ IFT_IMT = 0xbe
+ IFT_INTERLEAVE = 0x7c
+ IFT_IP = 0x7e
+ IFT_IPFORWARD = 0x8e
+ IFT_IPOVERATM = 0x72
+ IFT_IPOVERCDLC = 0x6d
+ IFT_IPOVERCLAW = 0x6e
+ IFT_IPSWITCH = 0x4e
+ IFT_IPXIP = 0xf9
+ IFT_ISDN = 0x3f
+ IFT_ISDNBASIC = 0x14
+ IFT_ISDNPRIMARY = 0x15
+ IFT_ISDNS = 0x4b
+ IFT_ISDNU = 0x4c
+ IFT_ISO88022LLC = 0x29
+ IFT_ISO88023 = 0x7
+ IFT_ISO88024 = 0x8
+ IFT_ISO88025 = 0x9
+ IFT_ISO88025CRFPINT = 0x62
+ IFT_ISO88025DTR = 0x56
+ IFT_ISO88025FIBER = 0x73
+ IFT_ISO88026 = 0xa
+ IFT_ISUP = 0xb3
+ IFT_L3IPXVLAN = 0x89
+ IFT_LAPB = 0x10
+ IFT_LAPD = 0x4d
+ IFT_LAPF = 0x77
+ IFT_LOCALTALK = 0x2a
+ IFT_LOOP = 0x18
+ IFT_MEDIAMAILOVERIP = 0x8b
+ IFT_MFSIGLINK = 0xa7
+ IFT_MIOX25 = 0x26
+ IFT_MODEM = 0x30
+ IFT_MPC = 0x71
+ IFT_MPLS = 0xa6
+ IFT_MPLSTUNNEL = 0x96
+ IFT_MSDSL = 0x8f
+ IFT_MVL = 0xbf
+ IFT_MYRINET = 0x63
+ IFT_NFAS = 0xaf
+ IFT_NSIP = 0x1b
+ IFT_OPTICALCHANNEL = 0xc3
+ IFT_OPTICALTRANSPORT = 0xc4
+ IFT_OTHER = 0x1
+ IFT_P10 = 0xc
+ IFT_P80 = 0xd
+ IFT_PARA = 0x22
+ IFT_PFLOG = 0xf6
+ IFT_PFSYNC = 0xf7
+ IFT_PLC = 0xae
+ IFT_POS = 0xab
+ IFT_PPPMULTILINKBUNDLE = 0x6c
+ IFT_PROPBWAP2MP = 0xb8
+ IFT_PROPCNLS = 0x59
+ IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
+ IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
+ IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
+ IFT_PROPMUX = 0x36
+ IFT_PROPWIRELESSP2P = 0x9d
+ IFT_PTPSERIAL = 0x16
+ IFT_PVC = 0xf1
+ IFT_QLLC = 0x44
+ IFT_RADIOMAC = 0xbc
+ IFT_RADSL = 0x5f
+ IFT_REACHDSL = 0xc0
+ IFT_RFC1483 = 0x9f
+ IFT_RS232 = 0x21
+ IFT_RSRB = 0x4f
+ IFT_SDLC = 0x11
+ IFT_SDSL = 0x60
+ IFT_SHDSL = 0xa9
+ IFT_SIP = 0x1f
+ IFT_SLIP = 0x1c
+ IFT_SMDSDXI = 0x2b
+ IFT_SMDSICIP = 0x34
+ IFT_SONET = 0x27
+ IFT_SONETOVERHEADCHANNEL = 0xb9
+ IFT_SONETPATH = 0x32
+ IFT_SONETVT = 0x33
+ IFT_SRP = 0x97
+ IFT_SS7SIGLINK = 0x9c
+ IFT_STACKTOSTACK = 0x6f
+ IFT_STARLAN = 0xb
+ IFT_STF = 0xd7
+ IFT_T1 = 0x12
+ IFT_TDLC = 0x74
+ IFT_TERMPAD = 0x5b
+ IFT_TR008 = 0xb0
+ IFT_TRANSPHDLC = 0x7b
+ IFT_TUNNEL = 0x83
+ IFT_ULTRA = 0x1d
+ IFT_USB = 0xa0
+ IFT_V11 = 0x40
+ IFT_V35 = 0x2d
+ IFT_V36 = 0x41
+ IFT_V37 = 0x78
+ IFT_VDSL = 0x61
+ IFT_VIRTUALIPADDRESS = 0x70
+ IFT_VOICEEM = 0x64
+ IFT_VOICEENCAP = 0x67
+ IFT_VOICEFXO = 0x65
+ IFT_VOICEFXS = 0x66
+ IFT_VOICEOVERATM = 0x98
+ IFT_VOICEOVERFRAMERELAY = 0x99
+ IFT_VOICEOVERIP = 0x68
+ IFT_X213 = 0x5d
+ IFT_X25 = 0x5
+ IFT_X25DDN = 0x4
+ IFT_X25HUNTGROUP = 0x7a
+ IFT_X25MLP = 0x79
+ IFT_X25PLE = 0x28
+ IFT_XETHER = 0x1a
+ IPPROTO_MAXID = 0x34
+ IPV6_FAITH = 0x1d
+ IP_FAITH = 0x16
+ MAP_NORESERVE = 0x40
+ MAP_RENAME = 0x20
+ NET_RT_MAXID = 0x6
+ RTF_PRCLONING = 0x10000
+ RTM_OLDADD = 0x9
+ RTM_OLDDEL = 0xa
+ SIOCADDRT = 0x8030720a
+ SIOCALIFADDR = 0x8118691b
+ SIOCDELRT = 0x8030720b
+ SIOCDLIFADDR = 0x8118691d
+ SIOCGLIFADDR = 0xc118691c
+ SIOCGLIFPHYADDR = 0xc118694b
+ SIOCSLIFPHYADDR = 0x8118694a
+)
diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go
new file mode 100644
index 0000000..3e97711
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go
@@ -0,0 +1,227 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Constants that were deprecated or moved to enums in the FreeBSD headers. Keep
+// them here for backwards compatibility.
+
+package unix
+
+const (
+ IFF_SMART = 0x20
+ IFT_1822 = 0x2
+ IFT_A12MPPSWITCH = 0x82
+ IFT_AAL2 = 0xbb
+ IFT_AAL5 = 0x31
+ IFT_ADSL = 0x5e
+ IFT_AFLANE8023 = 0x3b
+ IFT_AFLANE8025 = 0x3c
+ IFT_ARAP = 0x58
+ IFT_ARCNET = 0x23
+ IFT_ARCNETPLUS = 0x24
+ IFT_ASYNC = 0x54
+ IFT_ATM = 0x25
+ IFT_ATMDXI = 0x69
+ IFT_ATMFUNI = 0x6a
+ IFT_ATMIMA = 0x6b
+ IFT_ATMLOGICAL = 0x50
+ IFT_ATMRADIO = 0xbd
+ IFT_ATMSUBINTERFACE = 0x86
+ IFT_ATMVCIENDPT = 0xc2
+ IFT_ATMVIRTUAL = 0x95
+ IFT_BGPPOLICYACCOUNTING = 0xa2
+ IFT_BSC = 0x53
+ IFT_CCTEMUL = 0x3d
+ IFT_CEPT = 0x13
+ IFT_CES = 0x85
+ IFT_CHANNEL = 0x46
+ IFT_CNR = 0x55
+ IFT_COFFEE = 0x84
+ IFT_COMPOSITELINK = 0x9b
+ IFT_DCN = 0x8d
+ IFT_DIGITALPOWERLINE = 0x8a
+ IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+ IFT_DLSW = 0x4a
+ IFT_DOCSCABLEDOWNSTREAM = 0x80
+ IFT_DOCSCABLEMACLAYER = 0x7f
+ IFT_DOCSCABLEUPSTREAM = 0x81
+ IFT_DS0 = 0x51
+ IFT_DS0BUNDLE = 0x52
+ IFT_DS1FDL = 0xaa
+ IFT_DS3 = 0x1e
+ IFT_DTM = 0x8c
+ IFT_DVBASILN = 0xac
+ IFT_DVBASIOUT = 0xad
+ IFT_DVBRCCDOWNSTREAM = 0x93
+ IFT_DVBRCCMACLAYER = 0x92
+ IFT_DVBRCCUPSTREAM = 0x94
+ IFT_ENC = 0xf4
+ IFT_EON = 0x19
+ IFT_EPLRS = 0x57
+ IFT_ESCON = 0x49
+ IFT_ETHER = 0x6
+ IFT_FAITH = 0xf2
+ IFT_FAST = 0x7d
+ IFT_FASTETHER = 0x3e
+ IFT_FASTETHERFX = 0x45
+ IFT_FDDI = 0xf
+ IFT_FIBRECHANNEL = 0x38
+ IFT_FRAMERELAYINTERCONNECT = 0x3a
+ IFT_FRAMERELAYMPI = 0x5c
+ IFT_FRDLCIENDPT = 0xc1
+ IFT_FRELAY = 0x20
+ IFT_FRELAYDCE = 0x2c
+ IFT_FRF16MFRBUNDLE = 0xa3
+ IFT_FRFORWARD = 0x9e
+ IFT_G703AT2MB = 0x43
+ IFT_G703AT64K = 0x42
+ IFT_GIF = 0xf0
+ IFT_GIGABITETHERNET = 0x75
+ IFT_GR303IDT = 0xb2
+ IFT_GR303RDT = 0xb1
+ IFT_H323GATEKEEPER = 0xa4
+ IFT_H323PROXY = 0xa5
+ IFT_HDH1822 = 0x3
+ IFT_HDLC = 0x76
+ IFT_HDSL2 = 0xa8
+ IFT_HIPERLAN2 = 0xb7
+ IFT_HIPPI = 0x2f
+ IFT_HIPPIINTERFACE = 0x39
+ IFT_HOSTPAD = 0x5a
+ IFT_HSSI = 0x2e
+ IFT_HY = 0xe
+ IFT_IBM370PARCHAN = 0x48
+ IFT_IDSL = 0x9a
+ IFT_IEEE80211 = 0x47
+ IFT_IEEE80212 = 0x37
+ IFT_IEEE8023ADLAG = 0xa1
+ IFT_IFGSN = 0x91
+ IFT_IMT = 0xbe
+ IFT_INTERLEAVE = 0x7c
+ IFT_IP = 0x7e
+ IFT_IPFORWARD = 0x8e
+ IFT_IPOVERATM = 0x72
+ IFT_IPOVERCDLC = 0x6d
+ IFT_IPOVERCLAW = 0x6e
+ IFT_IPSWITCH = 0x4e
+ IFT_IPXIP = 0xf9
+ IFT_ISDN = 0x3f
+ IFT_ISDNBASIC = 0x14
+ IFT_ISDNPRIMARY = 0x15
+ IFT_ISDNS = 0x4b
+ IFT_ISDNU = 0x4c
+ IFT_ISO88022LLC = 0x29
+ IFT_ISO88023 = 0x7
+ IFT_ISO88024 = 0x8
+ IFT_ISO88025 = 0x9
+ IFT_ISO88025CRFPINT = 0x62
+ IFT_ISO88025DTR = 0x56
+ IFT_ISO88025FIBER = 0x73
+ IFT_ISO88026 = 0xa
+ IFT_ISUP = 0xb3
+ IFT_L3IPXVLAN = 0x89
+ IFT_LAPB = 0x10
+ IFT_LAPD = 0x4d
+ IFT_LAPF = 0x77
+ IFT_LOCALTALK = 0x2a
+ IFT_LOOP = 0x18
+ IFT_MEDIAMAILOVERIP = 0x8b
+ IFT_MFSIGLINK = 0xa7
+ IFT_MIOX25 = 0x26
+ IFT_MODEM = 0x30
+ IFT_MPC = 0x71
+ IFT_MPLS = 0xa6
+ IFT_MPLSTUNNEL = 0x96
+ IFT_MSDSL = 0x8f
+ IFT_MVL = 0xbf
+ IFT_MYRINET = 0x63
+ IFT_NFAS = 0xaf
+ IFT_NSIP = 0x1b
+ IFT_OPTICALCHANNEL = 0xc3
+ IFT_OPTICALTRANSPORT = 0xc4
+ IFT_OTHER = 0x1
+ IFT_P10 = 0xc
+ IFT_P80 = 0xd
+ IFT_PARA = 0x22
+ IFT_PFLOG = 0xf6
+ IFT_PFSYNC = 0xf7
+ IFT_PLC = 0xae
+ IFT_POS = 0xab
+ IFT_PPPMULTILINKBUNDLE = 0x6c
+ IFT_PROPBWAP2MP = 0xb8
+ IFT_PROPCNLS = 0x59
+ IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
+ IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
+ IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
+ IFT_PROPMUX = 0x36
+ IFT_PROPWIRELESSP2P = 0x9d
+ IFT_PTPSERIAL = 0x16
+ IFT_PVC = 0xf1
+ IFT_QLLC = 0x44
+ IFT_RADIOMAC = 0xbc
+ IFT_RADSL = 0x5f
+ IFT_REACHDSL = 0xc0
+ IFT_RFC1483 = 0x9f
+ IFT_RS232 = 0x21
+ IFT_RSRB = 0x4f
+ IFT_SDLC = 0x11
+ IFT_SDSL = 0x60
+ IFT_SHDSL = 0xa9
+ IFT_SIP = 0x1f
+ IFT_SLIP = 0x1c
+ IFT_SMDSDXI = 0x2b
+ IFT_SMDSICIP = 0x34
+ IFT_SONET = 0x27
+ IFT_SONETOVERHEADCHANNEL = 0xb9
+ IFT_SONETPATH = 0x32
+ IFT_SONETVT = 0x33
+ IFT_SRP = 0x97
+ IFT_SS7SIGLINK = 0x9c
+ IFT_STACKTOSTACK = 0x6f
+ IFT_STARLAN = 0xb
+ IFT_STF = 0xd7
+ IFT_T1 = 0x12
+ IFT_TDLC = 0x74
+ IFT_TERMPAD = 0x5b
+ IFT_TR008 = 0xb0
+ IFT_TRANSPHDLC = 0x7b
+ IFT_TUNNEL = 0x83
+ IFT_ULTRA = 0x1d
+ IFT_USB = 0xa0
+ IFT_V11 = 0x40
+ IFT_V35 = 0x2d
+ IFT_V36 = 0x41
+ IFT_V37 = 0x78
+ IFT_VDSL = 0x61
+ IFT_VIRTUALIPADDRESS = 0x70
+ IFT_VOICEEM = 0x64
+ IFT_VOICEENCAP = 0x67
+ IFT_VOICEFXO = 0x65
+ IFT_VOICEFXS = 0x66
+ IFT_VOICEOVERATM = 0x98
+ IFT_VOICEOVERFRAMERELAY = 0x99
+ IFT_VOICEOVERIP = 0x68
+ IFT_X213 = 0x5d
+ IFT_X25 = 0x5
+ IFT_X25DDN = 0x4
+ IFT_X25HUNTGROUP = 0x7a
+ IFT_X25MLP = 0x79
+ IFT_X25PLE = 0x28
+ IFT_XETHER = 0x1a
+ IPPROTO_MAXID = 0x34
+ IPV6_FAITH = 0x1d
+ IP_FAITH = 0x16
+ MAP_NORESERVE = 0x40
+ MAP_RENAME = 0x20
+ NET_RT_MAXID = 0x6
+ RTF_PRCLONING = 0x10000
+ RTM_OLDADD = 0x9
+ RTM_OLDDEL = 0xa
+ SIOCADDRT = 0x8040720a
+ SIOCALIFADDR = 0x8118691b
+ SIOCDELRT = 0x8040720b
+ SIOCDLIFADDR = 0x8118691d
+ SIOCGLIFADDR = 0xc118691c
+ SIOCGLIFPHYADDR = 0xc118694b
+ SIOCSLIFPHYADDR = 0x8118694a
+)
diff --git a/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go
new file mode 100644
index 0000000..856dca3
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/errors_freebsd_arm.go
@@ -0,0 +1,226 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+const (
+ IFT_1822 = 0x2
+ IFT_A12MPPSWITCH = 0x82
+ IFT_AAL2 = 0xbb
+ IFT_AAL5 = 0x31
+ IFT_ADSL = 0x5e
+ IFT_AFLANE8023 = 0x3b
+ IFT_AFLANE8025 = 0x3c
+ IFT_ARAP = 0x58
+ IFT_ARCNET = 0x23
+ IFT_ARCNETPLUS = 0x24
+ IFT_ASYNC = 0x54
+ IFT_ATM = 0x25
+ IFT_ATMDXI = 0x69
+ IFT_ATMFUNI = 0x6a
+ IFT_ATMIMA = 0x6b
+ IFT_ATMLOGICAL = 0x50
+ IFT_ATMRADIO = 0xbd
+ IFT_ATMSUBINTERFACE = 0x86
+ IFT_ATMVCIENDPT = 0xc2
+ IFT_ATMVIRTUAL = 0x95
+ IFT_BGPPOLICYACCOUNTING = 0xa2
+ IFT_BSC = 0x53
+ IFT_CCTEMUL = 0x3d
+ IFT_CEPT = 0x13
+ IFT_CES = 0x85
+ IFT_CHANNEL = 0x46
+ IFT_CNR = 0x55
+ IFT_COFFEE = 0x84
+ IFT_COMPOSITELINK = 0x9b
+ IFT_DCN = 0x8d
+ IFT_DIGITALPOWERLINE = 0x8a
+ IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+ IFT_DLSW = 0x4a
+ IFT_DOCSCABLEDOWNSTREAM = 0x80
+ IFT_DOCSCABLEMACLAYER = 0x7f
+ IFT_DOCSCABLEUPSTREAM = 0x81
+ IFT_DS0 = 0x51
+ IFT_DS0BUNDLE = 0x52
+ IFT_DS1FDL = 0xaa
+ IFT_DS3 = 0x1e
+ IFT_DTM = 0x8c
+ IFT_DVBASILN = 0xac
+ IFT_DVBASIOUT = 0xad
+ IFT_DVBRCCDOWNSTREAM = 0x93
+ IFT_DVBRCCMACLAYER = 0x92
+ IFT_DVBRCCUPSTREAM = 0x94
+ IFT_ENC = 0xf4
+ IFT_EON = 0x19
+ IFT_EPLRS = 0x57
+ IFT_ESCON = 0x49
+ IFT_ETHER = 0x6
+ IFT_FAST = 0x7d
+ IFT_FASTETHER = 0x3e
+ IFT_FASTETHERFX = 0x45
+ IFT_FDDI = 0xf
+ IFT_FIBRECHANNEL = 0x38
+ IFT_FRAMERELAYINTERCONNECT = 0x3a
+ IFT_FRAMERELAYMPI = 0x5c
+ IFT_FRDLCIENDPT = 0xc1
+ IFT_FRELAY = 0x20
+ IFT_FRELAYDCE = 0x2c
+ IFT_FRF16MFRBUNDLE = 0xa3
+ IFT_FRFORWARD = 0x9e
+ IFT_G703AT2MB = 0x43
+ IFT_G703AT64K = 0x42
+ IFT_GIF = 0xf0
+ IFT_GIGABITETHERNET = 0x75
+ IFT_GR303IDT = 0xb2
+ IFT_GR303RDT = 0xb1
+ IFT_H323GATEKEEPER = 0xa4
+ IFT_H323PROXY = 0xa5
+ IFT_HDH1822 = 0x3
+ IFT_HDLC = 0x76
+ IFT_HDSL2 = 0xa8
+ IFT_HIPERLAN2 = 0xb7
+ IFT_HIPPI = 0x2f
+ IFT_HIPPIINTERFACE = 0x39
+ IFT_HOSTPAD = 0x5a
+ IFT_HSSI = 0x2e
+ IFT_HY = 0xe
+ IFT_IBM370PARCHAN = 0x48
+ IFT_IDSL = 0x9a
+ IFT_IEEE80211 = 0x47
+ IFT_IEEE80212 = 0x37
+ IFT_IEEE8023ADLAG = 0xa1
+ IFT_IFGSN = 0x91
+ IFT_IMT = 0xbe
+ IFT_INTERLEAVE = 0x7c
+ IFT_IP = 0x7e
+ IFT_IPFORWARD = 0x8e
+ IFT_IPOVERATM = 0x72
+ IFT_IPOVERCDLC = 0x6d
+ IFT_IPOVERCLAW = 0x6e
+ IFT_IPSWITCH = 0x4e
+ IFT_ISDN = 0x3f
+ IFT_ISDNBASIC = 0x14
+ IFT_ISDNPRIMARY = 0x15
+ IFT_ISDNS = 0x4b
+ IFT_ISDNU = 0x4c
+ IFT_ISO88022LLC = 0x29
+ IFT_ISO88023 = 0x7
+ IFT_ISO88024 = 0x8
+ IFT_ISO88025 = 0x9
+ IFT_ISO88025CRFPINT = 0x62
+ IFT_ISO88025DTR = 0x56
+ IFT_ISO88025FIBER = 0x73
+ IFT_ISO88026 = 0xa
+ IFT_ISUP = 0xb3
+ IFT_L3IPXVLAN = 0x89
+ IFT_LAPB = 0x10
+ IFT_LAPD = 0x4d
+ IFT_LAPF = 0x77
+ IFT_LOCALTALK = 0x2a
+ IFT_LOOP = 0x18
+ IFT_MEDIAMAILOVERIP = 0x8b
+ IFT_MFSIGLINK = 0xa7
+ IFT_MIOX25 = 0x26
+ IFT_MODEM = 0x30
+ IFT_MPC = 0x71
+ IFT_MPLS = 0xa6
+ IFT_MPLSTUNNEL = 0x96
+ IFT_MSDSL = 0x8f
+ IFT_MVL = 0xbf
+ IFT_MYRINET = 0x63
+ IFT_NFAS = 0xaf
+ IFT_NSIP = 0x1b
+ IFT_OPTICALCHANNEL = 0xc3
+ IFT_OPTICALTRANSPORT = 0xc4
+ IFT_OTHER = 0x1
+ IFT_P10 = 0xc
+ IFT_P80 = 0xd
+ IFT_PARA = 0x22
+ IFT_PFLOG = 0xf6
+ IFT_PFSYNC = 0xf7
+ IFT_PLC = 0xae
+ IFT_POS = 0xab
+ IFT_PPPMULTILINKBUNDLE = 0x6c
+ IFT_PROPBWAP2MP = 0xb8
+ IFT_PROPCNLS = 0x59
+ IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5
+ IFT_PROPDOCSWIRELESSMACLAYER = 0xb4
+ IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6
+ IFT_PROPMUX = 0x36
+ IFT_PROPWIRELESSP2P = 0x9d
+ IFT_PTPSERIAL = 0x16
+ IFT_PVC = 0xf1
+ IFT_QLLC = 0x44
+ IFT_RADIOMAC = 0xbc
+ IFT_RADSL = 0x5f
+ IFT_REACHDSL = 0xc0
+ IFT_RFC1483 = 0x9f
+ IFT_RS232 = 0x21
+ IFT_RSRB = 0x4f
+ IFT_SDLC = 0x11
+ IFT_SDSL = 0x60
+ IFT_SHDSL = 0xa9
+ IFT_SIP = 0x1f
+ IFT_SLIP = 0x1c
+ IFT_SMDSDXI = 0x2b
+ IFT_SMDSICIP = 0x34
+ IFT_SONET = 0x27
+ IFT_SONETOVERHEADCHANNEL = 0xb9
+ IFT_SONETPATH = 0x32
+ IFT_SONETVT = 0x33
+ IFT_SRP = 0x97
+ IFT_SS7SIGLINK = 0x9c
+ IFT_STACKTOSTACK = 0x6f
+ IFT_STARLAN = 0xb
+ IFT_STF = 0xd7
+ IFT_T1 = 0x12
+ IFT_TDLC = 0x74
+ IFT_TERMPAD = 0x5b
+ IFT_TR008 = 0xb0
+ IFT_TRANSPHDLC = 0x7b
+ IFT_TUNNEL = 0x83
+ IFT_ULTRA = 0x1d
+ IFT_USB = 0xa0
+ IFT_V11 = 0x40
+ IFT_V35 = 0x2d
+ IFT_V36 = 0x41
+ IFT_V37 = 0x78
+ IFT_VDSL = 0x61
+ IFT_VIRTUALIPADDRESS = 0x70
+ IFT_VOICEEM = 0x64
+ IFT_VOICEENCAP = 0x67
+ IFT_VOICEFXO = 0x65
+ IFT_VOICEFXS = 0x66
+ IFT_VOICEOVERATM = 0x98
+ IFT_VOICEOVERFRAMERELAY = 0x99
+ IFT_VOICEOVERIP = 0x68
+ IFT_X213 = 0x5d
+ IFT_X25 = 0x5
+ IFT_X25DDN = 0x4
+ IFT_X25HUNTGROUP = 0x7a
+ IFT_X25MLP = 0x79
+ IFT_X25PLE = 0x28
+ IFT_XETHER = 0x1a
+
+ // missing constants on FreeBSD-11.1-RELEASE, copied from old values in ztypes_freebsd_arm.go
+ IFF_SMART = 0x20
+ IFT_FAITH = 0xf2
+ IFT_IPXIP = 0xf9
+ IPPROTO_MAXID = 0x34
+ IPV6_FAITH = 0x1d
+ IP_FAITH = 0x16
+ MAP_NORESERVE = 0x40
+ MAP_RENAME = 0x20
+ NET_RT_MAXID = 0x6
+ RTF_PRCLONING = 0x10000
+ RTM_OLDADD = 0x9
+ RTM_OLDDEL = 0xa
+ SIOCADDRT = 0x8030720a
+ SIOCALIFADDR = 0x8118691b
+ SIOCDELRT = 0x8030720b
+ SIOCDLIFADDR = 0x8118691d
+ SIOCGLIFADDR = 0xc118691c
+ SIOCGLIFPHYADDR = 0xc118694b
+ SIOCSLIFPHYADDR = 0x8118694a
+)
diff --git a/vendor/golang.org/x/sys/unix/flock.go b/vendor/golang.org/x/sys/unix/flock.go
new file mode 100644
index 0000000..2994ce7
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/flock.go
@@ -0,0 +1,22 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package unix
+
+import "unsafe"
+
+// fcntl64Syscall is usually SYS_FCNTL, but is overridden on 32-bit Linux
+// systems by flock_linux_32bit.go to be SYS_FCNTL64.
+var fcntl64Syscall uintptr = SYS_FCNTL
+
+// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
+func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
+ _, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
+ if errno == 0 {
+ return nil
+ }
+ return errno
+}
diff --git a/vendor/golang.org/x/sys/unix/flock_linux_32bit.go b/vendor/golang.org/x/sys/unix/flock_linux_32bit.go
new file mode 100644
index 0000000..fc0e50e
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/flock_linux_32bit.go
@@ -0,0 +1,13 @@
+// +build linux,386 linux,arm linux,mips linux,mipsle
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+func init() {
+ // On 32-bit Linux systems, the fcntl syscall that matches Go's
+ // Flock_t type is SYS_FCNTL64, not SYS_FCNTL.
+ fcntl64Syscall = SYS_FCNTL64
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo.go b/vendor/golang.org/x/sys/unix/gccgo.go
new file mode 100644
index 0000000..40bed3f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo.go
@@ -0,0 +1,46 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+package unix
+
+import "syscall"
+
+// We can't use the gc-syntax .s files for gccgo. On the plus side
+// much of the functionality can be written directly in Go.
+
+//extern gccgoRealSyscall
+func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ syscall.Entersyscall()
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+ syscall.Exitsyscall()
+ return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
+ return r, 0, syscall.Errno(errno)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) {
+ r, errno := realSyscall(trap, a1, a2, a3, a4, a5, a6, 0, 0, 0)
+ return r, 0, syscall.Errno(errno)
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo_c.c b/vendor/golang.org/x/sys/unix/gccgo_c.c
new file mode 100644
index 0000000..99a774f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo_c.c
@@ -0,0 +1,41 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+#include
+#include
+#include
+
+#define _STRINGIFY2_(x) #x
+#define _STRINGIFY_(x) _STRINGIFY2_(x)
+#define GOSYM_PREFIX _STRINGIFY_(__USER_LABEL_PREFIX__)
+
+// Call syscall from C code because the gccgo support for calling from
+// Go to C does not support varargs functions.
+
+struct ret {
+ uintptr_t r;
+ uintptr_t err;
+};
+
+struct ret
+gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
+{
+ struct ret r;
+
+ errno = 0;
+ r.r = syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ r.err = errno;
+ return r;
+}
+
+// Define the use function in C so that it is not inlined.
+
+extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));
+
+void
+use(void *p __attribute__ ((unused)))
+{
+}
diff --git a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
new file mode 100644
index 0000000..251a977
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
@@ -0,0 +1,20 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo,linux,amd64
+
+package unix
+
+import "syscall"
+
+//extern gettimeofday
+func realGettimeofday(*Timeval, *byte) int32
+
+func gettimeofday(tv *Timeval) (err syscall.Errno) {
+ r := realGettimeofday(tv, nil)
+ if r < 0 {
+ return syscall.GetErrno()
+ }
+ return 0
+}
diff --git a/vendor/golang.org/x/sys/unix/linux/mkall.go b/vendor/golang.org/x/sys/unix/linux/mkall.go
new file mode 100644
index 0000000..429754f
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/linux/mkall.go
@@ -0,0 +1,379 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// linux/mkall.go - Generates all Linux zsysnum, zsyscall, zerror, and ztype
+// files for all 11 linux architectures supported by the go compiler. See
+// README.md for more information about the build system.
+
+// To run it you must have a git checkout of the Linux kernel and glibc. Once
+// the appropriate sources are ready, the program is run as:
+// go run linux/mkall.go
+
+// +build ignore
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+// These will be paths to the appropriate source directories.
+var LinuxDir string
+var GlibcDir string
+
+const TempDir = "/tmp"
+const IncludeDir = TempDir + "/include" // To hold our C headers
+const BuildDir = TempDir + "/build" // To hold intermediate build files
+
+const GOOS = "linux" // Only for Linux targets
+const BuildArch = "amd64" // Must be built on this architecture
+const MinKernel = "2.6.23" // https://golang.org/doc/install#requirements
+
+type target struct {
+ GoArch string // Architecture name according to Go
+ LinuxArch string // Architecture name according to the Linux Kernel
+ GNUArch string // Architecture name according to GNU tools (https://wiki.debian.org/Multiarch/Tuples)
+ BigEndian bool // Default Little Endian
+ SignedChar bool // Is -fsigned-char needed (default no)
+ Bits int
+}
+
+// List of the 11 Linux targets supported by the go compiler. sparc64 is not
+// currently supported, though a port is in progress.
+var targets = []target{
+ {
+ GoArch: "386",
+ LinuxArch: "x86",
+ GNUArch: "i686-linux-gnu", // Note "i686" not "i386"
+ Bits: 32,
+ },
+ {
+ GoArch: "amd64",
+ LinuxArch: "x86",
+ GNUArch: "x86_64-linux-gnu",
+ Bits: 64,
+ },
+ {
+ GoArch: "arm64",
+ LinuxArch: "arm64",
+ GNUArch: "aarch64-linux-gnu",
+ SignedChar: true,
+ Bits: 64,
+ },
+ {
+ GoArch: "arm",
+ LinuxArch: "arm",
+ GNUArch: "arm-linux-gnueabi",
+ Bits: 32,
+ },
+ {
+ GoArch: "mips",
+ LinuxArch: "mips",
+ GNUArch: "mips-linux-gnu",
+ BigEndian: true,
+ Bits: 32,
+ },
+ {
+ GoArch: "mipsle",
+ LinuxArch: "mips",
+ GNUArch: "mipsel-linux-gnu",
+ Bits: 32,
+ },
+ {
+ GoArch: "mips64",
+ LinuxArch: "mips",
+ GNUArch: "mips64-linux-gnuabi64",
+ BigEndian: true,
+ Bits: 64,
+ },
+ {
+ GoArch: "mips64le",
+ LinuxArch: "mips",
+ GNUArch: "mips64el-linux-gnuabi64",
+ Bits: 64,
+ },
+ {
+ GoArch: "ppc64",
+ LinuxArch: "powerpc",
+ GNUArch: "powerpc64-linux-gnu",
+ BigEndian: true,
+ Bits: 64,
+ },
+ {
+ GoArch: "ppc64le",
+ LinuxArch: "powerpc",
+ GNUArch: "powerpc64le-linux-gnu",
+ Bits: 64,
+ },
+ {
+ GoArch: "s390x",
+ LinuxArch: "s390",
+ GNUArch: "s390x-linux-gnu",
+ BigEndian: true,
+ SignedChar: true,
+ Bits: 64,
+ },
+ // {
+ // GoArch: "sparc64",
+ // LinuxArch: "sparc",
+ // GNUArch: "sparc64-linux-gnu",
+ // BigEndian: true,
+ // Bits: 64,
+ // },
+}
+
+func main() {
+ if runtime.GOOS != GOOS || runtime.GOARCH != BuildArch {
+ fmt.Printf("Build system has GOOS_GOARCH = %s_%s, need %s_%s\n",
+ runtime.GOOS, runtime.GOARCH, GOOS, BuildArch)
+ return
+ }
+
+ // Check that we are using the new build system if we should
+ if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
+ fmt.Println("In the new build system, mkall.go should not be called directly.")
+ fmt.Println("See README.md")
+ return
+ }
+
+ // Parse the command line options
+ if len(os.Args) != 3 {
+ fmt.Println("USAGE: go run linux/mkall.go ")
+ return
+ }
+ LinuxDir = os.Args[1]
+ GlibcDir = os.Args[2]
+
+ for _, t := range targets {
+ fmt.Printf("----- GENERATING: %s -----\n", t.GoArch)
+ if err := t.generateFiles(); err != nil {
+ fmt.Printf("%v\n***** FAILURE: %s *****\n\n", err, t.GoArch)
+ } else {
+ fmt.Printf("----- SUCCESS: %s -----\n\n", t.GoArch)
+ }
+ }
+}
+
+// Makes an exec.Cmd with Stderr attached to os.Stderr
+func makeCommand(name string, args ...string) *exec.Cmd {
+ cmd := exec.Command(name, args...)
+ cmd.Stderr = os.Stderr
+ return cmd
+}
+
+// Runs the command, pipes output to a formatter, pipes that to an output file.
+func (t *target) commandFormatOutput(formatter string, outputFile string,
+ name string, args ...string) (err error) {
+ mainCmd := makeCommand(name, args...)
+
+ fmtCmd := makeCommand(formatter)
+ if formatter == "mkpost" {
+ fmtCmd = makeCommand("go", "run", "mkpost.go")
+ // Set GOARCH_TARGET so mkpost knows what GOARCH is..
+ fmtCmd.Env = append(os.Environ(), "GOARCH_TARGET="+t.GoArch)
+ // Set GOARCH to host arch for mkpost, so it can run natively.
+ for i, s := range fmtCmd.Env {
+ if strings.HasPrefix(s, "GOARCH=") {
+ fmtCmd.Env[i] = "GOARCH=" + BuildArch
+ }
+ }
+ }
+
+ // mainCmd | fmtCmd > outputFile
+ if fmtCmd.Stdin, err = mainCmd.StdoutPipe(); err != nil {
+ return
+ }
+ if fmtCmd.Stdout, err = os.Create(outputFile); err != nil {
+ return
+ }
+
+ // Make sure the formatter eventually closes
+ if err = fmtCmd.Start(); err != nil {
+ return
+ }
+ defer func() {
+ fmtErr := fmtCmd.Wait()
+ if err == nil {
+ err = fmtErr
+ }
+ }()
+
+ return mainCmd.Run()
+}
+
+// Generates all the files for a Linux target
+func (t *target) generateFiles() error {
+ // Setup environment variables
+ os.Setenv("GOOS", GOOS)
+ os.Setenv("GOARCH", t.GoArch)
+
+ // Get appropriate compiler and emulator (unless on x86)
+ if t.LinuxArch != "x86" {
+ // Check/Setup cross compiler
+ compiler := t.GNUArch + "-gcc"
+ if _, err := exec.LookPath(compiler); err != nil {
+ return err
+ }
+ os.Setenv("CC", compiler)
+
+ // Check/Setup emulator (usually first component of GNUArch)
+ qemuArchName := t.GNUArch[:strings.Index(t.GNUArch, "-")]
+ if t.LinuxArch == "powerpc" {
+ qemuArchName = t.GoArch
+ }
+ os.Setenv("GORUN", "qemu-"+qemuArchName)
+ } else {
+ os.Setenv("CC", "gcc")
+ }
+
+ // Make the include directory and fill it with headers
+ if err := os.MkdirAll(IncludeDir, os.ModePerm); err != nil {
+ return err
+ }
+ defer os.RemoveAll(IncludeDir)
+ if err := t.makeHeaders(); err != nil {
+ return fmt.Errorf("could not make header files: %v", err)
+ }
+ fmt.Println("header files generated")
+
+ // Make each of the four files
+ if err := t.makeZSysnumFile(); err != nil {
+ return fmt.Errorf("could not make zsysnum file: %v", err)
+ }
+ fmt.Println("zsysnum file generated")
+
+ if err := t.makeZSyscallFile(); err != nil {
+ return fmt.Errorf("could not make zsyscall file: %v", err)
+ }
+ fmt.Println("zsyscall file generated")
+
+ if err := t.makeZTypesFile(); err != nil {
+ return fmt.Errorf("could not make ztypes file: %v", err)
+ }
+ fmt.Println("ztypes file generated")
+
+ if err := t.makeZErrorsFile(); err != nil {
+ return fmt.Errorf("could not make zerrors file: %v", err)
+ }
+ fmt.Println("zerrors file generated")
+
+ return nil
+}
+
+// Create the Linux and glibc headers in the include directory.
+func (t *target) makeHeaders() error {
+ // Make the Linux headers we need for this architecture
+ linuxMake := makeCommand("make", "headers_install", "ARCH="+t.LinuxArch, "INSTALL_HDR_PATH="+TempDir)
+ linuxMake.Dir = LinuxDir
+ if err := linuxMake.Run(); err != nil {
+ return err
+ }
+
+ // A Temporary build directory for glibc
+ if err := os.MkdirAll(BuildDir, os.ModePerm); err != nil {
+ return err
+ }
+ defer os.RemoveAll(BuildDir)
+
+ // Make the glibc headers we need for this architecture
+ confScript := filepath.Join(GlibcDir, "configure")
+ glibcConf := makeCommand(confScript, "--prefix="+TempDir, "--host="+t.GNUArch, "--enable-kernel="+MinKernel)
+ glibcConf.Dir = BuildDir
+ if err := glibcConf.Run(); err != nil {
+ return err
+ }
+ glibcMake := makeCommand("make", "install-headers")
+ glibcMake.Dir = BuildDir
+ if err := glibcMake.Run(); err != nil {
+ return err
+ }
+ // We only need an empty stubs file
+ stubsFile := filepath.Join(IncludeDir, "gnu/stubs.h")
+ if file, err := os.Create(stubsFile); err != nil {
+ return err
+ } else {
+ file.Close()
+ }
+
+ return nil
+}
+
+// makes the zsysnum_linux_$GOARCH.go file
+func (t *target) makeZSysnumFile() error {
+ zsysnumFile := fmt.Sprintf("zsysnum_linux_%s.go", t.GoArch)
+ unistdFile := filepath.Join(IncludeDir, "asm/unistd.h")
+
+ args := append(t.cFlags(), unistdFile)
+ return t.commandFormatOutput("gofmt", zsysnumFile, "linux/mksysnum.pl", args...)
+}
+
+// makes the zsyscall_linux_$GOARCH.go file
+func (t *target) makeZSyscallFile() error {
+ zsyscallFile := fmt.Sprintf("zsyscall_linux_%s.go", t.GoArch)
+ // Find the correct architecture syscall file (might end with x.go)
+ archSyscallFile := fmt.Sprintf("syscall_linux_%s.go", t.GoArch)
+ if _, err := os.Stat(archSyscallFile); os.IsNotExist(err) {
+ shortArch := strings.TrimSuffix(t.GoArch, "le")
+ archSyscallFile = fmt.Sprintf("syscall_linux_%sx.go", shortArch)
+ }
+
+ args := append(t.mksyscallFlags(), "-tags", "linux,"+t.GoArch,
+ "syscall_linux.go", archSyscallFile)
+ return t.commandFormatOutput("gofmt", zsyscallFile, "./mksyscall.pl", args...)
+}
+
+// makes the zerrors_linux_$GOARCH.go file
+func (t *target) makeZErrorsFile() error {
+ zerrorsFile := fmt.Sprintf("zerrors_linux_%s.go", t.GoArch)
+
+ return t.commandFormatOutput("gofmt", zerrorsFile, "./mkerrors.sh", t.cFlags()...)
+}
+
+// makes the ztypes_linux_$GOARCH.go file
+func (t *target) makeZTypesFile() error {
+ ztypesFile := fmt.Sprintf("ztypes_linux_%s.go", t.GoArch)
+
+ args := []string{"tool", "cgo", "-godefs", "--"}
+ args = append(args, t.cFlags()...)
+ args = append(args, "linux/types.go")
+ return t.commandFormatOutput("mkpost", ztypesFile, "go", args...)
+}
+
+// Flags that should be given to gcc and cgo for this target
+func (t *target) cFlags() []string {
+ // Compile statically to avoid cross-architecture dynamic linking.
+ flags := []string{"-Wall", "-Werror", "-static", "-I" + IncludeDir}
+
+ // Architecture-specific flags
+ if t.SignedChar {
+ flags = append(flags, "-fsigned-char")
+ }
+ if t.LinuxArch == "x86" {
+ flags = append(flags, fmt.Sprintf("-m%d", t.Bits))
+ }
+
+ return flags
+}
+
+// Flags that should be given to mksyscall for this target
+func (t *target) mksyscallFlags() (flags []string) {
+ if t.Bits == 32 {
+ if t.BigEndian {
+ flags = append(flags, "-b32")
+ } else {
+ flags = append(flags, "-l32")
+ }
+ }
+
+ // This flag menas a 64-bit value should use (even, odd)-pair.
+ if t.GoArch == "arm" || (t.LinuxArch == "mips" && t.Bits == 32) {
+ flags = append(flags, "-arm")
+ }
+ return
+}
diff --git a/vendor/golang.org/x/sys/unix/linux/types.go b/vendor/golang.org/x/sys/unix/linux/types.go
new file mode 100644
index 0000000..d3bf24a
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/linux/types.go
@@ -0,0 +1,536 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo -godefs. See README.md
+*/
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package unix
+
+/*
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
+#define _GNU_SOURCE
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// On mips64, the glibc stat and kernel stat do not agree
+#if (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64)
+
+// Use the stat defined by the kernel with a few modifications. These are:
+// * The time fields (like st_atime and st_atimensec) use the timespec
+// struct (like st_atim) for consitancy with the glibc fields.
+// * The padding fields get different names to not break compatibility.
+// * st_blocks is signed, again for compatibility.
+struct stat {
+ unsigned int st_dev;
+ unsigned int st_pad1[3]; // Reserved for st_dev expansion
+
+ unsigned long st_ino;
+
+ mode_t st_mode;
+ __u32 st_nlink;
+
+ uid_t st_uid;
+ gid_t st_gid;
+
+ unsigned int st_rdev;
+ unsigned int st_pad2[3]; // Reserved for st_rdev expansion
+
+ off_t st_size;
+
+ // These are declared as speperate fields in the kernel. Here we use
+ // the timespec struct for consistancy with the other stat structs.
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+
+ unsigned int st_blksize;
+ unsigned int st_pad4;
+
+ long st_blocks;
+};
+
+// These are needed because we do not include fcntl.h or sys/types.h
+#include
+#include
+
+#else
+
+// Use the stat defined by glibc
+#include
+#include
+
+#endif
+
+// Certain constants and structs are missing from the fs/crypto UAPI
+#define FS_MAX_KEY_SIZE 64
+struct fscrypt_key {
+ __u32 mode;
+ __u8 raw[FS_MAX_KEY_SIZE];
+ __u32 size;
+};
+
+#ifdef TCSETS2
+// On systems that have "struct termios2" use this as type Termios.
+typedef struct termios2 termios_t;
+#else
+typedef struct termios termios_t;
+#endif
+
+enum {
+ sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+ struct sockaddr s1; // this one gets used for fields
+ struct sockaddr_in s2; // these pad it out
+ struct sockaddr_in6 s3;
+ struct sockaddr_un s4;
+ struct sockaddr_ll s5;
+ struct sockaddr_nl s6;
+};
+
+struct sockaddr_any {
+ struct sockaddr addr;
+ char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+// copied from /usr/include/bluetooth/hci.h
+struct sockaddr_hci {
+ sa_family_t hci_family;
+ unsigned short hci_dev;
+ unsigned short hci_channel;
+};;
+
+// copied from /usr/include/linux/un.h
+struct my_sockaddr_un {
+ sa_family_t sun_family;
+#if defined(__ARM_EABI__) || defined(__powerpc64__)
+ // on ARM char is by default unsigned
+ signed char sun_path[108];
+#else
+ char sun_path[108];
+#endif
+};
+
+#ifdef __ARM_EABI__
+typedef struct user_regs PtraceRegs;
+#elif defined(__aarch64__)
+typedef struct user_pt_regs PtraceRegs;
+#elif defined(__powerpc64__)
+typedef struct pt_regs PtraceRegs;
+#elif defined(__mips__)
+typedef struct user PtraceRegs;
+#elif defined(__s390x__)
+typedef struct _user_regs_struct PtraceRegs;
+#elif defined(__sparc__)
+#include
+typedef struct pt_regs PtraceRegs;
+#else
+typedef struct user_regs_struct PtraceRegs;
+#endif
+
+#if defined(__s390x__)
+typedef struct _user_psw_struct ptracePsw;
+typedef struct _user_fpregs_struct ptraceFpregs;
+typedef struct _user_per_struct ptracePer;
+#else
+typedef struct {} ptracePsw;
+typedef struct {} ptraceFpregs;
+typedef struct {} ptracePer;
+#endif
+
+// The real epoll_event is a union, and godefs doesn't handle it well.
+struct my_epoll_event {
+ uint32_t events;
+#if defined(__ARM_EABI__) || defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABIO32)
+ // padding is not specified in linux/eventpoll.h but added to conform to the
+ // alignment requirements of EABI
+ int32_t padFd;
+#elif defined(__powerpc64__) || defined(__s390x__) || defined(__sparc__)
+ int32_t _padFd;
+#endif
+ int32_t fd;
+ int32_t pad;
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+ sizeofPtr = C.sizeofPtr
+ sizeofShort = C.sizeof_short
+ sizeofInt = C.sizeof_int
+ sizeofLong = C.sizeof_long
+ sizeofLongLong = C.sizeof_longlong
+ PathMax = C.PATH_MAX
+)
+
+// Basic types
+
+type (
+ _C_short C.short
+ _C_int C.int
+ _C_long C.long
+ _C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+type Timex C.struct_timex
+
+type Time_t C.time_t
+
+type Tms C.struct_tms
+
+type Utimbuf C.struct_utimbuf
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+type Stat_t C.struct_stat
+
+type Statfs_t C.struct_statfs
+
+type Dirent C.struct_dirent
+
+type Fsid C.fsid_t
+
+type Flock_t C.struct_flock
+
+// Filesystem Encryption
+
+type FscryptPolicy C.struct_fscrypt_policy
+
+type FscryptKey C.struct_fscrypt_key
+
+// Advice to Fadvise
+
+const (
+ FADV_NORMAL = C.POSIX_FADV_NORMAL
+ FADV_RANDOM = C.POSIX_FADV_RANDOM
+ FADV_SEQUENTIAL = C.POSIX_FADV_SEQUENTIAL
+ FADV_WILLNEED = C.POSIX_FADV_WILLNEED
+ FADV_DONTNEED = C.POSIX_FADV_DONTNEED
+ FADV_NOREUSE = C.POSIX_FADV_NOREUSE
+)
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_my_sockaddr_un
+
+type RawSockaddrLinklayer C.struct_sockaddr_ll
+
+type RawSockaddrNetlink C.struct_sockaddr_nl
+
+type RawSockaddrHCI C.struct_sockaddr_hci
+
+type RawSockaddrCAN C.struct_sockaddr_can
+
+type RawSockaddrALG C.struct_sockaddr_alg
+
+type RawSockaddrVM C.struct_sockaddr_vm
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPMreqn C.struct_ip_mreqn
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet4Pktinfo C.struct_in_pktinfo
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+type IPv6MTUInfo C.struct_ip6_mtuinfo
+
+type ICMPv6Filter C.struct_icmp6_filter
+
+type Ucred C.struct_ucred
+
+type TCPInfo C.struct_tcp_info
+
+const (
+ SizeofSockaddrInet4 = C.sizeof_struct_sockaddr_in
+ SizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
+ SizeofSockaddrAny = C.sizeof_struct_sockaddr_any
+ SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un
+ SizeofSockaddrLinklayer = C.sizeof_struct_sockaddr_ll
+ SizeofSockaddrNetlink = C.sizeof_struct_sockaddr_nl
+ SizeofSockaddrHCI = C.sizeof_struct_sockaddr_hci
+ SizeofSockaddrCAN = C.sizeof_struct_sockaddr_can
+ SizeofSockaddrALG = C.sizeof_struct_sockaddr_alg
+ SizeofSockaddrVM = C.sizeof_struct_sockaddr_vm
+ SizeofLinger = C.sizeof_struct_linger
+ SizeofIPMreq = C.sizeof_struct_ip_mreq
+ SizeofIPMreqn = C.sizeof_struct_ip_mreqn
+ SizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
+ SizeofMsghdr = C.sizeof_struct_msghdr
+ SizeofCmsghdr = C.sizeof_struct_cmsghdr
+ SizeofInet4Pktinfo = C.sizeof_struct_in_pktinfo
+ SizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
+ SizeofIPv6MTUInfo = C.sizeof_struct_ip6_mtuinfo
+ SizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
+ SizeofUcred = C.sizeof_struct_ucred
+ SizeofTCPInfo = C.sizeof_struct_tcp_info
+)
+
+// Netlink routing and interface messages
+
+const (
+ IFA_UNSPEC = C.IFA_UNSPEC
+ IFA_ADDRESS = C.IFA_ADDRESS
+ IFA_LOCAL = C.IFA_LOCAL
+ IFA_LABEL = C.IFA_LABEL
+ IFA_BROADCAST = C.IFA_BROADCAST
+ IFA_ANYCAST = C.IFA_ANYCAST
+ IFA_CACHEINFO = C.IFA_CACHEINFO
+ IFA_MULTICAST = C.IFA_MULTICAST
+ IFLA_UNSPEC = C.IFLA_UNSPEC
+ IFLA_ADDRESS = C.IFLA_ADDRESS
+ IFLA_BROADCAST = C.IFLA_BROADCAST
+ IFLA_IFNAME = C.IFLA_IFNAME
+ IFLA_MTU = C.IFLA_MTU
+ IFLA_LINK = C.IFLA_LINK
+ IFLA_QDISC = C.IFLA_QDISC
+ IFLA_STATS = C.IFLA_STATS
+ IFLA_COST = C.IFLA_COST
+ IFLA_PRIORITY = C.IFLA_PRIORITY
+ IFLA_MASTER = C.IFLA_MASTER
+ IFLA_WIRELESS = C.IFLA_WIRELESS
+ IFLA_PROTINFO = C.IFLA_PROTINFO
+ IFLA_TXQLEN = C.IFLA_TXQLEN
+ IFLA_MAP = C.IFLA_MAP
+ IFLA_WEIGHT = C.IFLA_WEIGHT
+ IFLA_OPERSTATE = C.IFLA_OPERSTATE
+ IFLA_LINKMODE = C.IFLA_LINKMODE
+ IFLA_LINKINFO = C.IFLA_LINKINFO
+ IFLA_NET_NS_PID = C.IFLA_NET_NS_PID
+ IFLA_IFALIAS = C.IFLA_IFALIAS
+ IFLA_MAX = C.IFLA_MAX
+ RT_SCOPE_UNIVERSE = C.RT_SCOPE_UNIVERSE
+ RT_SCOPE_SITE = C.RT_SCOPE_SITE
+ RT_SCOPE_LINK = C.RT_SCOPE_LINK
+ RT_SCOPE_HOST = C.RT_SCOPE_HOST
+ RT_SCOPE_NOWHERE = C.RT_SCOPE_NOWHERE
+ RT_TABLE_UNSPEC = C.RT_TABLE_UNSPEC
+ RT_TABLE_COMPAT = C.RT_TABLE_COMPAT
+ RT_TABLE_DEFAULT = C.RT_TABLE_DEFAULT
+ RT_TABLE_MAIN = C.RT_TABLE_MAIN
+ RT_TABLE_LOCAL = C.RT_TABLE_LOCAL
+ RT_TABLE_MAX = C.RT_TABLE_MAX
+ RTA_UNSPEC = C.RTA_UNSPEC
+ RTA_DST = C.RTA_DST
+ RTA_SRC = C.RTA_SRC
+ RTA_IIF = C.RTA_IIF
+ RTA_OIF = C.RTA_OIF
+ RTA_GATEWAY = C.RTA_GATEWAY
+ RTA_PRIORITY = C.RTA_PRIORITY
+ RTA_PREFSRC = C.RTA_PREFSRC
+ RTA_METRICS = C.RTA_METRICS
+ RTA_MULTIPATH = C.RTA_MULTIPATH
+ RTA_FLOW = C.RTA_FLOW
+ RTA_CACHEINFO = C.RTA_CACHEINFO
+ RTA_TABLE = C.RTA_TABLE
+ RTN_UNSPEC = C.RTN_UNSPEC
+ RTN_UNICAST = C.RTN_UNICAST
+ RTN_LOCAL = C.RTN_LOCAL
+ RTN_BROADCAST = C.RTN_BROADCAST
+ RTN_ANYCAST = C.RTN_ANYCAST
+ RTN_MULTICAST = C.RTN_MULTICAST
+ RTN_BLACKHOLE = C.RTN_BLACKHOLE
+ RTN_UNREACHABLE = C.RTN_UNREACHABLE
+ RTN_PROHIBIT = C.RTN_PROHIBIT
+ RTN_THROW = C.RTN_THROW
+ RTN_NAT = C.RTN_NAT
+ RTN_XRESOLVE = C.RTN_XRESOLVE
+ RTNLGRP_NONE = C.RTNLGRP_NONE
+ RTNLGRP_LINK = C.RTNLGRP_LINK
+ RTNLGRP_NOTIFY = C.RTNLGRP_NOTIFY
+ RTNLGRP_NEIGH = C.RTNLGRP_NEIGH
+ RTNLGRP_TC = C.RTNLGRP_TC
+ RTNLGRP_IPV4_IFADDR = C.RTNLGRP_IPV4_IFADDR
+ RTNLGRP_IPV4_MROUTE = C.RTNLGRP_IPV4_MROUTE
+ RTNLGRP_IPV4_ROUTE = C.RTNLGRP_IPV4_ROUTE
+ RTNLGRP_IPV4_RULE = C.RTNLGRP_IPV4_RULE
+ RTNLGRP_IPV6_IFADDR = C.RTNLGRP_IPV6_IFADDR
+ RTNLGRP_IPV6_MROUTE = C.RTNLGRP_IPV6_MROUTE
+ RTNLGRP_IPV6_ROUTE = C.RTNLGRP_IPV6_ROUTE
+ RTNLGRP_IPV6_IFINFO = C.RTNLGRP_IPV6_IFINFO
+ RTNLGRP_IPV6_PREFIX = C.RTNLGRP_IPV6_PREFIX
+ RTNLGRP_IPV6_RULE = C.RTNLGRP_IPV6_RULE
+ RTNLGRP_ND_USEROPT = C.RTNLGRP_ND_USEROPT
+ SizeofNlMsghdr = C.sizeof_struct_nlmsghdr
+ SizeofNlMsgerr = C.sizeof_struct_nlmsgerr
+ SizeofRtGenmsg = C.sizeof_struct_rtgenmsg
+ SizeofNlAttr = C.sizeof_struct_nlattr
+ SizeofRtAttr = C.sizeof_struct_rtattr
+ SizeofIfInfomsg = C.sizeof_struct_ifinfomsg
+ SizeofIfAddrmsg = C.sizeof_struct_ifaddrmsg
+ SizeofRtMsg = C.sizeof_struct_rtmsg
+ SizeofRtNexthop = C.sizeof_struct_rtnexthop
+)
+
+type NlMsghdr C.struct_nlmsghdr
+
+type NlMsgerr C.struct_nlmsgerr
+
+type RtGenmsg C.struct_rtgenmsg
+
+type NlAttr C.struct_nlattr
+
+type RtAttr C.struct_rtattr
+
+type IfInfomsg C.struct_ifinfomsg
+
+type IfAddrmsg C.struct_ifaddrmsg
+
+type RtMsg C.struct_rtmsg
+
+type RtNexthop C.struct_rtnexthop
+
+// Linux socket filter
+
+const (
+ SizeofSockFilter = C.sizeof_struct_sock_filter
+ SizeofSockFprog = C.sizeof_struct_sock_fprog
+)
+
+type SockFilter C.struct_sock_filter
+
+type SockFprog C.struct_sock_fprog
+
+// Inotify
+
+type InotifyEvent C.struct_inotify_event
+
+const SizeofInotifyEvent = C.sizeof_struct_inotify_event
+
+// Ptrace
+
+// Register structures
+type PtraceRegs C.PtraceRegs
+
+// Structures contained in PtraceRegs on s390x (exported by mkpost.go)
+type PtracePsw C.ptracePsw
+
+type PtraceFpregs C.ptraceFpregs
+
+type PtracePer C.ptracePer
+
+// Misc
+
+type FdSet C.fd_set
+
+type Sysinfo_t C.struct_sysinfo
+
+type Utsname C.struct_utsname
+
+type Ustat_t C.struct_ustat
+
+type EpollEvent C.struct_my_epoll_event
+
+const (
+ AT_FDCWD = C.AT_FDCWD
+ AT_REMOVEDIR = C.AT_REMOVEDIR
+ AT_SYMLINK_FOLLOW = C.AT_SYMLINK_FOLLOW
+ AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
+)
+
+type PollFd C.struct_pollfd
+
+const (
+ POLLIN = C.POLLIN
+ POLLPRI = C.POLLPRI
+ POLLOUT = C.POLLOUT
+ POLLRDHUP = C.POLLRDHUP
+ POLLERR = C.POLLERR
+ POLLHUP = C.POLLHUP
+ POLLNVAL = C.POLLNVAL
+)
+
+type Sigset_t C.sigset_t
+
+// sysconf information
+
+const _SC_PAGESIZE = C._SC_PAGESIZE
+
+// Terminal handling
+
+type Termios C.termios_t
diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh
new file mode 100755
index 0000000..00b7ce7
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mkall.sh
@@ -0,0 +1,194 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This script runs or (given -n) prints suggested commands to generate files for
+# the Architecture/OS specified by the GOARCH and GOOS environment variables.
+# See README.md for more information about how the build system works.
+
+GOOSARCH="${GOOS}_${GOARCH}"
+
+# defaults
+mksyscall="./mksyscall.pl"
+mkerrors="./mkerrors.sh"
+zerrors="zerrors_$GOOSARCH.go"
+mksysctl=""
+zsysctl="zsysctl_$GOOSARCH.go"
+mksysnum=
+mktypes=
+run="sh"
+cmd=""
+
+case "$1" in
+-syscalls)
+ for i in zsyscall*go
+ do
+ # Run the command line that appears in the first line
+ # of the generated file to regenerate it.
+ sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
+ rm _$i
+ done
+ exit 0
+ ;;
+-n)
+ run="cat"
+ cmd="echo"
+ shift
+esac
+
+case "$#" in
+0)
+ ;;
+*)
+ echo 'usage: mkall.sh [-n]' 1>&2
+ exit 2
+esac
+
+if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
+ # Use then new build system
+ # Files generated through docker (use $cmd so you can Ctl-C the build or run)
+ $cmd docker build --tag generate:$GOOS $GOOS
+ $cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS
+ exit
+fi
+
+GOOSARCH_in=syscall_$GOOSARCH.go
+case "$GOOSARCH" in
+_* | *_ | _)
+ echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+darwin_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_amd64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_arm)
+ mkerrors="$mkerrors"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+darwin_arm64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+dragonfly_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -dragonfly"
+ mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+dragonfly_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -dragonfly"
+ mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+freebsd_arm)
+ mkerrors="$mkerrors"
+ mksyscall="./mksyscall.pl -l32 -arm"
+ mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+ # Let the type of C char be signed for making the bare syscall
+ # API consistent across platforms.
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
+ ;;
+linux_sparc64)
+ GOOSARCH_in=syscall_linux_sparc64.go
+ unistd_h=/usr/include/sparc64-linux-gnu/asm/unistd.h
+ mkerrors="$mkerrors -m64"
+ mksysnum="./mksysnum_linux.pl $unistd_h"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -netbsd"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -netbsd"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+netbsd_arm)
+ mkerrors="$mkerrors"
+ mksyscall="./mksyscall.pl -l32 -netbsd -arm"
+ mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+ # Let the type of C char be signed for making the bare syscall
+ # API consistent across platforms.
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
+ ;;
+openbsd_386)
+ mkerrors="$mkerrors -m32"
+ mksyscall="./mksyscall.pl -l32 -openbsd"
+ mksysctl="./mksysctl_openbsd.pl"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+openbsd_amd64)
+ mkerrors="$mkerrors -m64"
+ mksyscall="./mksyscall.pl -openbsd"
+ mksysctl="./mksysctl_openbsd.pl"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+openbsd_arm)
+ mkerrors="$mkerrors"
+ mksyscall="./mksyscall.pl -l32 -openbsd -arm"
+ mksysctl="./mksysctl_openbsd.pl"
+ mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+ # Let the type of C char be signed for making the bare syscall
+ # API consistent across platforms.
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
+ ;;
+solaris_amd64)
+ mksyscall="./mksyscall_solaris.pl"
+ mkerrors="$mkerrors -m64"
+ mksysnum=
+ mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+ ;;
+*)
+ echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
+ exit 1
+ ;;
+esac
+
+(
+ if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
+ case "$GOOS" in
+ *)
+ syscall_goos="syscall_$GOOS.go"
+ case "$GOOS" in
+ darwin | dragonfly | freebsd | netbsd | openbsd)
+ syscall_goos="syscall_bsd.go $syscall_goos"
+ ;;
+ esac
+ if [ -n "$mksyscall" ]; then echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi
+ ;;
+ esac
+ if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
+ if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
+ if [ -n "$mktypes" ]; then
+ echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go";
+ fi
+) | $run
diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh
new file mode 100755
index 0000000..2a44da5
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -0,0 +1,577 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Generate Go code listing errors and other #defined constant
+# values (ENAMETOOLONG etc.), by asking the preprocessor
+# about the definitions.
+
+unset LANG
+export LC_ALL=C
+export LC_CTYPE=C
+
+if test -z "$GOARCH" -o -z "$GOOS"; then
+ echo 1>&2 "GOARCH or GOOS not defined in environment"
+ exit 1
+fi
+
+# Check that we are using the new build system if we should
+if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then
+ if [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then
+ echo 1>&2 "In the new build system, mkerrors should not be called directly."
+ echo 1>&2 "See README.md"
+ exit 1
+ fi
+fi
+
+CC=${CC:-cc}
+
+if [[ "$GOOS" = "solaris" ]]; then
+ # Assumes GNU versions of utilities in PATH.
+ export PATH=/usr/gnu/bin:$PATH
+fi
+
+uname=$(uname)
+
+includes_Darwin='
+#define _DARWIN_C_SOURCE
+#define KERNEL
+#define _DARWIN_USE_64_BIT_INODE
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+includes_DragonFly='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+includes_FreeBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if __FreeBSD__ >= 10
+#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10
+#undef SIOCAIFADDR
+#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data
+#undef SIOCSIFPHYADDR
+#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data
+#endif
+'
+
+includes_Linux='
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#ifndef __LP64__
+#define _FILE_OFFSET_BITS 64
+#endif
+#define _GNU_SOURCE
+
+// is broken on powerpc64, as it fails to include definitions of
+// these structures. We just include them copied from .
+#if defined(__powerpc__)
+struct sgttyb {
+ char sg_ispeed;
+ char sg_ospeed;
+ char sg_erase;
+ char sg_kill;
+ short sg_flags;
+};
+
+struct tchars {
+ char t_intrc;
+ char t_quitc;
+ char t_startc;
+ char t_stopc;
+ char t_eofc;
+ char t_brkc;
+};
+
+struct ltchars {
+ char t_suspc;
+ char t_dsuspc;
+ char t_rprntc;
+ char t_flushc;
+ char t_werasc;
+ char t_lnextc;
+};
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef MSG_FASTOPEN
+#define MSG_FASTOPEN 0x20000000
+#endif
+
+#ifndef PTRACE_GETREGS
+#define PTRACE_GETREGS 0xc
+#endif
+
+#ifndef PTRACE_SETREGS
+#define PTRACE_SETREGS 0xd
+#endif
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+#ifdef SOL_BLUETOOTH
+// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
+// but it is already in bluetooth_linux.go
+#undef SOL_BLUETOOTH
+#endif
+
+// Certain constants are missing from the fs/crypto UAPI
+#define FS_KEY_DESC_PREFIX "fscrypt:"
+#define FS_KEY_DESC_PREFIX_SIZE 8
+#define FS_MAX_KEY_SIZE 64
+'
+
+includes_NetBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Needed since refers to it...
+#define schedppq 1
+'
+
+includes_OpenBSD='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// We keep some constants not supported in OpenBSD 5.5 and beyond for
+// the promise of compatibility.
+#define EMUL_ENABLED 0x1
+#define EMUL_NATIVE 0x2
+#define IPV6_FAITH 0x1d
+#define IPV6_OPTIONS 0x1
+#define IPV6_RTHDR_STRICT 0x1
+#define IPV6_SOCKOPT_RESERVED1 0x3
+#define SIOCGIFGENERIC 0xc020693a
+#define SIOCSIFGENERIC 0x80206939
+#define WALTSIG 0x4
+'
+
+includes_SunOS='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+
+
+includes='
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+'
+ccflags="$@"
+
+# Write go tool cgo -godefs input.
+(
+ echo package unix
+ echo
+ echo '/*'
+ indirect="includes_$(uname)"
+ echo "${!indirect} $includes"
+ echo '*/'
+ echo 'import "C"'
+ echo 'import "syscall"'
+ echo
+ echo 'const ('
+
+ # The gcc command line prints all the #defines
+ # it encounters while processing the input
+ echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
+ awk '
+ $1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
+
+ $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
+ $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
+ $2 ~ /^(SCM_SRCRT)$/ {next}
+ $2 ~ /^(MAP_FAILED)$/ {next}
+ $2 ~ /^ELF_.*$/ {next}# contains ELF_ARCH, etc.
+
+ $2 ~ /^EXTATTR_NAMESPACE_NAMES/ ||
+ $2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next}
+
+ $2 !~ /^ETH_/ &&
+ $2 !~ /^EPROC_/ &&
+ $2 !~ /^EQUIV_/ &&
+ $2 !~ /^EXPR_/ &&
+ $2 ~ /^E[A-Z0-9_]+$/ ||
+ $2 ~ /^B[0-9_]+$/ ||
+ $2 ~ /^(OLD|NEW)DEV$/ ||
+ $2 == "BOTHER" ||
+ $2 ~ /^CI?BAUD(EX)?$/ ||
+ $2 == "IBSHIFT" ||
+ $2 ~ /^V[A-Z0-9]+$/ ||
+ $2 ~ /^CS[A-Z0-9]/ ||
+ $2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
+ $2 ~ /^IGN/ ||
+ $2 ~ /^IX(ON|ANY|OFF)$/ ||
+ $2 ~ /^IN(LCR|PCK)$/ ||
+ $2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
+ $2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ ||
+ $2 == "BRKINT" ||
+ $2 == "HUPCL" ||
+ $2 == "PENDIN" ||
+ $2 == "TOSTOP" ||
+ $2 == "XCASE" ||
+ $2 == "ALTWERASE" ||
+ $2 == "NOKERNINFO" ||
+ $2 ~ /^PAR/ ||
+ $2 ~ /^SIG[^_]/ ||
+ $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
+ $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
+ $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
+ $2 ~ /^O?XTABS$/ ||
+ $2 ~ /^TC[IO](ON|OFF)$/ ||
+ $2 ~ /^IN_/ ||
+ $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
+ $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
+ $2 ~ /^FALLOC_/ ||
+ $2 == "ICMPV6_FILTER" ||
+ $2 == "SOMAXCONN" ||
+ $2 == "NAME_MAX" ||
+ $2 == "IFNAMSIZ" ||
+ $2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
+ $2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
+ $2 ~ /^HW_MACHINE$/ ||
+ $2 ~ /^SYSCTL_VERS/ ||
+ $2 ~ /^(MS|MNT|UMOUNT)_/ ||
+ $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
+ $2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ ||
+ $2 ~ /^LINUX_REBOOT_CMD_/ ||
+ $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
+ $2 !~ "NLA_TYPE_MASK" &&
+ $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
+ $2 ~ /^SIOC/ ||
+ $2 ~ /^TIOC/ ||
+ $2 ~ /^TCGET/ ||
+ $2 ~ /^TCSET/ ||
+ $2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
+ $2 !~ "RTF_BITS" &&
+ $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
+ $2 ~ /^BIOC/ ||
+ $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
+ $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
+ $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
+ $2 ~ /^CLONE_[A-Z_]+/ ||
+ $2 !~ /^(BPF_TIMEVAL)$/ &&
+ $2 ~ /^(BPF|DLT)_/ ||
+ $2 ~ /^CLOCK_/ ||
+ $2 ~ /^CAN_/ ||
+ $2 ~ /^CAP_/ ||
+ $2 ~ /^ALG_/ ||
+ $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ ||
+ $2 ~ /^GRND_/ ||
+ $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
+ $2 ~ /^KEYCTL_/ ||
+ $2 ~ /^PERF_EVENT_IOC_/ ||
+ $2 ~ /^SECCOMP_MODE_/ ||
+ $2 ~ /^SPLICE_/ ||
+ $2 ~ /^(VM|VMADDR)_/ ||
+ $2 ~ /^IOCTL_VM_SOCKETS_/ ||
+ $2 ~ /^(TASKSTATS|TS)_/ ||
+ $2 ~ /^GENL_/ ||
+ $2 ~ /^UTIME_/ ||
+ $2 ~ /^XATTR_(CREATE|REPLACE)/ ||
+ $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
+ $2 ~ /^FSOPT_/ ||
+ $2 ~ /^WDIOC_/ ||
+ $2 !~ "WMESGLEN" &&
+ $2 ~ /^W[A-Z0-9]+$/ ||
+ $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
+ $2 ~ /^__WCOREFLAG$/ {next}
+ $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
+
+ {next}
+ ' | sort
+
+ echo ')'
+) >_const.go
+
+# Pull out the error names for later.
+errors=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
+ sort
+)
+
+# Pull out the signal names for later.
+signals=$(
+ echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort
+)
+
+# Again, writing regexps to a file.
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ sort >_error.grep
+echo '#include ' | $CC -x c - -E -dM $ccflags |
+ awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
+ egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
+ sort >_signal.grep
+
+echo '// mkerrors.sh' "$@"
+echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
+echo
+echo "// +build ${GOARCH},${GOOS}"
+echo
+go tool cgo -godefs -- "$@" _const.go >_error.out
+cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
+echo
+echo '// Errors'
+echo 'const ('
+cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/'
+echo ')'
+
+echo
+echo '// Signals'
+echo 'const ('
+cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/'
+echo ')'
+
+# Run C program to print error and syscall strings.
+(
+ echo -E "
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
+
+enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
+
+int errors[] = {
+"
+ for i in $errors
+ do
+ echo -E ' '$i,
+ done
+
+ echo -E "
+};
+
+int signals[] = {
+"
+ for i in $signals
+ do
+ echo -E ' '$i,
+ done
+
+ # Use -E because on some systems bash builtin interprets \n itself.
+ echo -E '
+};
+
+static int
+intcmp(const void *a, const void *b)
+{
+ return *(int*)a - *(int*)b;
+}
+
+int
+main(void)
+{
+ int i, e;
+ char buf[1024], *p;
+
+ printf("\n\n// Error table\n");
+ printf("var errors = [...]string {\n");
+ qsort(errors, nelem(errors), sizeof errors[0], intcmp);
+ for(i=0; i 0 && errors[i-1] == e)
+ continue;
+ strcpy(buf, strerror(e));
+ // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+ if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
+ buf[0] += a - A;
+ printf("\t%d: \"%s\",\n", e, buf);
+ }
+ printf("}\n\n");
+
+ printf("\n\n// Signal table\n");
+ printf("var signals = [...]string {\n");
+ qsort(signals, nelem(signals), sizeof signals[0], intcmp);
+ for(i=0; i 0 && signals[i-1] == e)
+ continue;
+ strcpy(buf, strsignal(e));
+ // lowercase first letter: Bad -> bad, but STREAM -> STREAM.
+ if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
+ buf[0] += a - A;
+ // cut trailing : number.
+ p = strrchr(buf, ":"[0]);
+ if(p)
+ *p = '\0';
+ printf("\t%d: \"%s\",\n", e, buf);
+ }
+ printf("}\n\n");
+
+ return 0;
+}
+
+'
+) >_errors.c
+
+$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out
diff --git a/vendor/golang.org/x/sys/unix/mksyscall.pl b/vendor/golang.org/x/sys/unix/mksyscall.pl
new file mode 100755
index 0000000..fb929b4
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mksyscall.pl
@@ -0,0 +1,328 @@
+#!/usr/bin/env perl
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This program reads a file containing function prototypes
+# (like syscall_darwin.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named errno.
+
+# A line beginning with //sysnb is like //sys, except that the
+# goroutine will not be suspended during the execution of the system
+# call. This must only be used for system calls which can never
+# block, as otherwise the system call could cause all goroutines to
+# hang.
+
+use strict;
+
+my $cmdline = "mksyscall.pl " . join(' ', @ARGV);
+my $errors = 0;
+my $_32bit = "";
+my $plan9 = 0;
+my $openbsd = 0;
+my $netbsd = 0;
+my $dragonfly = 0;
+my $arm = 0; # 64-bit value should use (even, odd)-pair
+my $tags = ""; # build tags
+
+if($ARGV[0] eq "-b32") {
+ $_32bit = "big-endian";
+ shift;
+} elsif($ARGV[0] eq "-l32") {
+ $_32bit = "little-endian";
+ shift;
+}
+if($ARGV[0] eq "-plan9") {
+ $plan9 = 1;
+ shift;
+}
+if($ARGV[0] eq "-openbsd") {
+ $openbsd = 1;
+ shift;
+}
+if($ARGV[0] eq "-netbsd") {
+ $netbsd = 1;
+ shift;
+}
+if($ARGV[0] eq "-dragonfly") {
+ $dragonfly = 1;
+ shift;
+}
+if($ARGV[0] eq "-arm") {
+ $arm = 1;
+ shift;
+}
+if($ARGV[0] eq "-tags") {
+ shift;
+ $tags = $ARGV[0];
+ shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+ print STDERR "usage: mksyscall.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
+ exit 1;
+}
+
+# Check that we are using the new build system if we should
+if($ENV{'GOOS'} eq "linux" && $ENV{'GOARCH'} ne "sparc64") {
+ if($ENV{'GOLANG_SYS_BUILD'} ne "docker") {
+ print STDERR "In the new build system, mksyscall should not be called directly.\n";
+ print STDERR "See README.md\n";
+ exit 1;
+ }
+}
+
+
+sub parseparamlist($) {
+ my ($list) = @_;
+ $list =~ s/^\s*//;
+ $list =~ s/\s*$//;
+ if($list eq "") {
+ return ();
+ }
+ return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+ my ($p) = @_;
+ if($p !~ /^(\S*) (\S*)$/) {
+ print STDERR "$ARGV:$.: malformed parameter: $p\n";
+ $errors = 1;
+ return ("xx", "int");
+ }
+ return ($1, $2);
+}
+
+my $text = "";
+while(<>) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, errno error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($func, $in, $out, $sysname) = ($2, $3, $4, $5);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ # Try in vain to keep people from editing this file.
+ # The theory is that they jump into the middle of the file
+ # without reading the header.
+ $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+
+ # Go function header.
+ my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : "";
+ $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl;
+
+ # Check if err return available
+ my $errvar = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ last;
+ }
+ }
+
+ # Prepare arguments to Syscall.
+ my @args = ();
+ my $n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @args, "uintptr(unsafe.Pointer($name))";
+ } elsif($type eq "string" && $errvar ne "") {
+ $text .= "\tvar _p$n *byte\n";
+ $text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
+ $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $text .= "\tvar _p$n *byte\n";
+ $text .= "\t_p$n, _ = BytePtrFromString($name)\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass dummy pointer in that case.
+ # Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
+ $text .= "\tvar _p$n unsafe.Pointer\n";
+ $text .= "\tif len($name) > 0 {\n\t\t_p$n = unsafe.Pointer(\&${name}[0])\n\t}";
+ $text .= " else {\n\t\t_p$n = unsafe.Pointer(&_zero)\n\t}";
+ $text .= "\n";
+ push @args, "uintptr(_p$n)", "uintptr(len($name))";
+ $n++;
+ } elsif($type eq "int64" && ($openbsd || $netbsd)) {
+ push @args, "0";
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } elsif($_32bit eq "little-endian") {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ } else {
+ push @args, "uintptr($name)";
+ }
+ } elsif($type eq "int64" && $dragonfly) {
+ if ($func !~ /^extp(read|write)/i) {
+ push @args, "0";
+ }
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } elsif($_32bit eq "little-endian") {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ } else {
+ push @args, "uintptr($name)";
+ }
+ } elsif($type eq "int64" && $_32bit ne "") {
+ if(@args % 2 && $arm) {
+ # arm abi specifies 64-bit argument uses
+ # (even, odd) pair
+ push @args, "0"
+ }
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name>>32)", "uintptr($name)";
+ } else {
+ push @args, "uintptr($name)", "uintptr($name>>32)";
+ }
+ } else {
+ push @args, "uintptr($name)";
+ }
+ }
+
+ # Determine which form to use; pad args with zeros.
+ my $asm = "Syscall";
+ if ($nonblock) {
+ $asm = "RawSyscall";
+ }
+ if(@args <= 3) {
+ while(@args < 3) {
+ push @args, "0";
+ }
+ } elsif(@args <= 6) {
+ $asm .= "6";
+ while(@args < 6) {
+ push @args, "0";
+ }
+ } elsif(@args <= 9) {
+ $asm .= "9";
+ while(@args < 9) {
+ push @args, "0";
+ }
+ } else {
+ print STDERR "$ARGV:$.: too many arguments to system call\n";
+ }
+
+ # System call number.
+ if($sysname eq "") {
+ $sysname = "SYS_$func";
+ $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
+ $sysname =~ y/a-z/A-Z/;
+ }
+
+ # Actual call.
+ my $args = join(', ', @args);
+ my $call = "$asm($sysname, $args)";
+
+ # Assign return values.
+ my $body = "";
+ my @ret = ("_", "_", "_");
+ my $do_errno = 0;
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err" && !$plan9) {
+ $reg = "e1";
+ $ret[2] = $reg;
+ $do_errno = 1;
+ } elsif($name eq "err" && $plan9) {
+ $ret[0] = "r0";
+ $ret[2] = "e1";
+ next;
+ } else {
+ $reg = sprintf("r%d", $i);
+ $ret[$i] = $reg;
+ }
+ if($type eq "bool") {
+ $reg = "$reg != 0";
+ }
+ if($type eq "int64" && $_32bit ne "") {
+ # 64-bit number in r1:r0 or r0:r1.
+ if($i+2 > @out) {
+ print STDERR "$ARGV:$.: not enough registers for int64 return\n";
+ }
+ if($_32bit eq "big-endian") {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
+ } else {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
+ }
+ $ret[$i] = sprintf("r%d", $i);
+ $ret[$i+1] = sprintf("r%d", $i+1);
+ }
+ if($reg ne "e1" || $plan9) {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+ if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
+ $text .= "\t$call\n";
+ } else {
+ $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
+ }
+ $text .= $body;
+
+ if ($plan9 && $ret[2] eq "e1") {
+ $text .= "\tif int32(r0) == -1 {\n";
+ $text .= "\t\terr = e1\n";
+ $text .= "\t}\n";
+ } elsif ($do_errno) {
+ $text .= "\tif e1 != 0 {\n";
+ $text .= "\t\terr = errnoErr(e1)\n";
+ $text .= "\t}\n";
+ }
+ $text .= "\treturn\n";
+ $text .= "}\n\n";
+}
+
+chomp $text;
+chomp $text;
+
+if($errors) {
+ exit 1;
+}
+
+print <) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ $package = $1 if !$package && /^package (\S+)$/;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, err error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ # So file name.
+ if($modname eq "") {
+ $modname = "libc";
+ }
+
+ # System call name.
+ if($sysname eq "") {
+ $sysname = "$func";
+ }
+
+ # System call pointer variable name.
+ my $sysvarname = "proc$sysname";
+
+ my $strconvfunc = "BytePtrFromString";
+ my $strconvtype = "*byte";
+
+ $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
+
+ # Runtime import of function to allow cross-platform builds.
+ $dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n";
+ # Link symbol to proc address variable.
+ $linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n";
+ # Library proc address variable.
+ push @vars, $sysvarname;
+
+ # Go function header.
+ $out = join(', ', @out);
+ if($out ne "") {
+ $out = " ($out)";
+ }
+ if($text ne "") {
+ $text .= "\n"
+ }
+ $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out;
+
+ # Check if err return available
+ my $errvar = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ last;
+ }
+ }
+
+ # Prepare arguments to Syscall.
+ my @args = ();
+ my $n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @args, "uintptr(unsafe.Pointer($name))";
+ } elsif($type eq "string" && $errvar ne "") {
+ $text .= "\tvar _p$n $strconvtype\n";
+ $text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
+ $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $text .= "\tvar _p$n $strconvtype\n";
+ $text .= "\t_p$n, _ = $strconvfunc($name)\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass nil in that case.
+ $text .= "\tvar _p$n *$1\n";
+ $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))";
+ $n++;
+ } elsif($type eq "int64" && $_32bit ne "") {
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name >> 32)", "uintptr($name)";
+ } else {
+ push @args, "uintptr($name)", "uintptr($name >> 32)";
+ }
+ } elsif($type eq "bool") {
+ $text .= "\tvar _p$n uint32\n";
+ $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
+ push @args, "uintptr(_p$n)";
+ $n++;
+ } else {
+ push @args, "uintptr($name)";
+ }
+ }
+ my $nargs = @args;
+
+ # Determine which form to use; pad args with zeros.
+ my $asm = "sysvicall6";
+ if ($nonblock) {
+ $asm = "rawSysvicall6";
+ }
+ if(@args <= 6) {
+ while(@args < 6) {
+ push @args, "0";
+ }
+ } else {
+ print STDERR "$ARGV:$.: too many arguments to system call\n";
+ }
+
+ # Actual call.
+ my $args = join(', ', @args);
+ my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)";
+
+ # Assign return values.
+ my $body = "";
+ my $failexpr = "";
+ my @ret = ("_", "_", "_");
+ my @pout= ();
+ my $do_errno = 0;
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err") {
+ $reg = "e1";
+ $ret[2] = $reg;
+ $do_errno = 1;
+ } else {
+ $reg = sprintf("r%d", $i);
+ $ret[$i] = $reg;
+ }
+ if($type eq "bool") {
+ $reg = "$reg != 0";
+ }
+ if($type eq "int64" && $_32bit ne "") {
+ # 64-bit number in r1:r0 or r0:r1.
+ if($i+2 > @out) {
+ print STDERR "$ARGV:$.: not enough registers for int64 return\n";
+ }
+ if($_32bit eq "big-endian") {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
+ } else {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
+ }
+ $ret[$i] = sprintf("r%d", $i);
+ $ret[$i+1] = sprintf("r%d", $i+1);
+ }
+ if($reg ne "e1") {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+ if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
+ $text .= "\t$call\n";
+ } else {
+ $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
+ }
+ $text .= $body;
+
+ if ($do_errno) {
+ $text .= "\tif e1 != 0 {\n";
+ $text .= "\t\terr = e1\n";
+ $text .= "\t}\n";
+ }
+ $text .= "\treturn\n";
+ $text .= "}\n";
+}
+
+if($errors) {
+ exit 1;
+}
+
+print < "net.inet",
+ "net.inet.ipproto" => "net.inet",
+ "net.inet6.ipv6proto" => "net.inet6",
+ "net.inet6.ipv6" => "net.inet6.ip6",
+ "net.inet.icmpv6" => "net.inet6.icmp6",
+ "net.inet6.divert6" => "net.inet6.divert",
+ "net.inet6.tcp6" => "net.inet.tcp",
+ "net.inet6.udp6" => "net.inet.udp",
+ "mpls" => "net.mpls",
+ "swpenc" => "vm.swapencrypt"
+);
+
+# Node mappings
+my %node_map = (
+ "net.inet.ip.ifq" => "net.ifq",
+ "net.inet.pfsync" => "net.pfsync",
+ "net.mpls.ifq" => "net.ifq"
+);
+
+my $ctlname;
+my %mib = ();
+my %sysctl = ();
+my $node;
+
+sub debug() {
+ print STDERR "$_[0]\n" if $debug;
+}
+
+# Walk the MIB and build a sysctl name to OID mapping.
+sub build_sysctl() {
+ my ($node, $name, $oid) = @_;
+ my %node = %{$node};
+ my @oid = @{$oid};
+
+ foreach my $key (sort keys %node) {
+ my @node = @{$node{$key}};
+ my $nodename = $name.($name ne '' ? '.' : '').$key;
+ my @nodeoid = (@oid, $node[0]);
+ if ($node[1] eq 'CTLTYPE_NODE') {
+ if (exists $node_map{$nodename}) {
+ $node = \%mib;
+ $ctlname = $node_map{$nodename};
+ foreach my $part (split /\./, $ctlname) {
+ $node = \%{@{$$node{$part}}[2]};
+ }
+ } else {
+ $node = $node[2];
+ }
+ &build_sysctl($node, $nodename, \@nodeoid);
+ } elsif ($node[1] ne '') {
+ $sysctl{$nodename} = \@nodeoid;
+ }
+ }
+}
+
+foreach my $ctl (@ctls) {
+ $ctls{$ctl} = $ctl;
+}
+
+# Build MIB
+foreach my $header (@headers) {
+ &debug("Processing $header...");
+ open HEADER, "/usr/include/$header" ||
+ print STDERR "Failed to open $header\n";
+ while () {
+ if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ ||
+ $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ ||
+ $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) {
+ if ($1 eq 'CTL_NAMES') {
+ # Top level.
+ $node = \%mib;
+ } else {
+ # Node.
+ my $nodename = lc($2);
+ if ($header =~ /^netinet\//) {
+ $ctlname = "net.inet.$nodename";
+ } elsif ($header =~ /^netinet6\//) {
+ $ctlname = "net.inet6.$nodename";
+ } elsif ($header =~ /^net\//) {
+ $ctlname = "net.$nodename";
+ } else {
+ $ctlname = "$nodename";
+ $ctlname =~ s/^(fs|net|kern)_/$1\./;
+ }
+ if (exists $ctl_map{$ctlname}) {
+ $ctlname = $ctl_map{$ctlname};
+ }
+ if (not exists $ctls{$ctlname}) {
+ &debug("Ignoring $ctlname...");
+ next;
+ }
+
+ # Walk down from the top of the MIB.
+ $node = \%mib;
+ foreach my $part (split /\./, $ctlname) {
+ if (not exists $$node{$part}) {
+ &debug("Missing node $part");
+ $$node{$part} = [ 0, '', {} ];
+ }
+ $node = \%{@{$$node{$part}}[2]};
+ }
+ }
+
+ # Populate current node with entries.
+ my $i = -1;
+ while (defined($_) && $_ !~ /^}/) {
+ $_ = ;
+ $i++ if $_ =~ /{.*}/;
+ next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/;
+ $$node{$1} = [ $i, $2, {} ];
+ }
+ }
+ }
+ close HEADER;
+}
+
+&build_sysctl(\%mib, "", []);
+
+print <){
+ if(/^#define\s+SYS_(\w+)\s+([0-9]+)/){
+ my $name = $1;
+ my $num = $2;
+ $name =~ y/a-z/A-Z/;
+ print " SYS_$name = $num;"
+ }
+}
+
+print <){
+ if(/^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$/){
+ my $num = $1;
+ my $proto = $2;
+ my $name = "SYS_$3";
+ $name =~ y/a-z/A-Z/;
+
+ # There are multiple entries for enosys and nosys, so comment them out.
+ if($name =~ /^SYS_E?NOSYS$/){
+ $name = "// $name";
+ }
+ if($name eq 'SYS_SYS_EXIT'){
+ $name = 'SYS_EXIT';
+ }
+
+ print " $name = $num; // $proto\n";
+ }
+}
+
+print <